@@ -85,6 +85,8 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8585#define IMX477_DGTL_GAIN_DEFAULT 0x0100
8686#define IMX477_DGTL_GAIN_STEP 1
8787
88+ #define IMX477_REG_DIV_IOP_PX 0x030b
89+
8890/* Test Pattern Control */
8991#define IMX477_REG_TEST_PATTERN 0x0600
9092#define IMX477_TEST_PATTERN_DISABLE 0
@@ -150,7 +152,7 @@ struct imx477_mode {
150152 /* Frame height */
151153 unsigned int height ;
152154
153- /* H-timing in pixels */
155+ /* H-timing in pixels when at 450MHz link freq */
154156 unsigned int line_length_pix ;
155157
156158 /* Analog crop rectangle. */
@@ -167,6 +169,10 @@ static const s64 imx477_link_freq_menu[] = {
167169 IMX477_DEFAULT_LINK_FREQ ,
168170};
169171
172+ static const s64 imx477_double_link_freq_menu [] = {
173+ IMX477_DEFAULT_LINK_FREQ * 2 ,
174+ };
175+
170176static const struct imx477_reg mode_common_regs [] = {
171177 {0x0136 , 0x18 },
172178 {0x0137 , 0x00 },
@@ -491,7 +497,6 @@ static const struct imx477_reg mode_common_regs[] = {
491497 {0x9e9f , 0x00 },
492498 {0x0301 , 0x05 },
493499 {0x0303 , 0x02 },
494- {0x030b , 0x02 },
495500 {0x030d , 0x02 },
496501 {0x030e , 0x00 },
497502 {0x030f , 0x96 },
@@ -786,7 +791,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
786791 /* 12MPix 10fps mode */
787792 .width = 4056 ,
788793 .height = 3040 ,
789- .line_length_pix = 0x5dc0 ,
794+ .line_length_pix = 24000 ,
790795 .crop = {
791796 .left = IMX477_PIXEL_ARRAY_LEFT ,
792797 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -803,7 +808,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
803808 /* 2x2 binned 40fps mode */
804809 .width = 2028 ,
805810 .height = 1520 ,
806- .line_length_pix = 0x31c4 ,
811+ .line_length_pix = 12740 ,
807812 .crop = {
808813 .left = IMX477_PIXEL_ARRAY_LEFT ,
809814 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -820,7 +825,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
820825 /* 1080p 50fps cropped mode */
821826 .width = 2028 ,
822827 .height = 1080 ,
823- .line_length_pix = 0x31c4 ,
828+ .line_length_pix = 12740 ,
824829 .crop = {
825830 .left = IMX477_PIXEL_ARRAY_LEFT ,
826831 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -969,6 +974,12 @@ struct imx477 {
969974 */
970975 unsigned int csi2_flags ;
971976
977+ /*
978+ * Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
979+ * line_length_pix can be halved in that case.
980+ */
981+ bool double_link_freq ;
982+
972983 /* Rewrite common registers on stream on? */
973984 bool common_regs_written ;
974985
@@ -1412,6 +1423,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14121423{
14131424 unsigned int frm_length_default , hblank_min ;
14141425 const struct imx477_mode * mode = imx477 -> mode ;
1426+ unsigned int line_length_pix ;
14151427
14161428 frm_length_default =
14171429 imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1428,7 +1440,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14281440 /* Setting this will adjust the exposure limits as well. */
14291441 __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
14301442
1431- hblank_min = mode -> line_length_pix - mode -> width ;
1443+ line_length_pix = mode -> line_length_pix ;
1444+ if (imx477 -> double_link_freq )
1445+ line_length_pix /= 2 ;
1446+ hblank_min = line_length_pix - mode -> width ;
14321447 __v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
14331448 IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
14341449 __v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1568,6 +1583,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
15681583 imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
15691584 1 : 0 );
15701585
1586+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1587+ IMX477_REG_VALUE_08BIT ,
1588+ imx477 -> double_link_freq ? 1 : 2 );
1589+
15711590 imx477 -> common_regs_written = true;
15721591 }
15731592
@@ -1825,6 +1844,7 @@ static int imx477_init_controls(struct imx477 *imx477)
18251844 struct v4l2_ctrl_handler * ctrl_hdlr ;
18261845 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
18271846 struct v4l2_fwnode_device_properties props ;
1847+ const u64 * link_freq_menu ;
18281848 unsigned int i ;
18291849 int ret ;
18301850
@@ -1846,11 +1866,16 @@ static int imx477_init_controls(struct imx477 *imx477)
18461866 imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
18471867
18481868 /* LINK_FREQ is also read only */
1869+ if (imx477 -> double_link_freq )
1870+ link_freq_menu = imx477_double_link_freq_menu ;
1871+ else
1872+ link_freq_menu = imx477_link_freq_menu ;
1873+
18491874 imx477 -> link_freq =
18501875 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
18511876 V4L2_CID_LINK_FREQ ,
18521877 ARRAY_SIZE (imx477_link_freq_menu ) - 1 , 0 ,
1853- imx477_link_freq_menu );
1878+ link_freq_menu );
18541879 if (imx477 -> link_freq )
18551880 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
18561881
@@ -1980,11 +2005,14 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
19802005 }
19812006
19822007 if (ep_cfg .nr_of_link_frequencies != 1 ||
1983- ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ ) {
2008+ (ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ &&
2009+ ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ * 2 )) {
19842010 dev_err (dev , "Link frequency not supported: %lld\n" ,
19852011 ep_cfg .link_frequencies [0 ]);
19862012 goto error_out ;
19872013 }
2014+ if (ep_cfg .link_frequencies [0 ] == IMX477_DEFAULT_LINK_FREQ * 2 )
2015+ imx477 -> double_link_freq = true;
19882016
19892017 imx477 -> csi2_flags = ep_cfg .bus .mipi_csi2 .flags ;
19902018
0 commit comments