@@ -86,6 +86,8 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8686#define IMX477_DGTL_GAIN_DEFAULT 0x0100
8787#define IMX477_DGTL_GAIN_STEP 1
8888
89+ #define IMX477_REG_DIV_IOP_PX 0x030b
90+
8991/* Test Pattern Control */
9092#define IMX477_REG_TEST_PATTERN 0x0600
9193#define IMX477_TEST_PATTERN_DISABLE 0
@@ -151,7 +153,7 @@ struct imx477_mode {
151153 /* Frame height */
152154 unsigned int height ;
153155
154- /* H-timing in pixels */
156+ /* H-timing in pixels when at 450MHz link freq */
155157 unsigned int line_length_pix ;
156158
157159 /* Analog crop rectangle. */
@@ -171,12 +173,18 @@ enum {
171173 IMX477_LINK_FREQ_456MHZ ,
172174};
173175
174- static const s64 link_freqs [] = {
176+ static const u64 imx477_link_freq_menu [] = {
175177 [IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
176178 [IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
177179 [IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
178180};
179181
182+ static const u64 imx477_double_link_freq_menu [] = {
183+ [IMX477_LINK_FREQ_450MHZ ] = 450000000 * 2 ,
184+ [IMX477_LINK_FREQ_453MHZ ] = 453000000 * 2 ,
185+ [IMX477_LINK_FREQ_456MHZ ] = 456000000 * 2 ,
186+ };
187+
180188/* 450MHz is the nominal "default" link frequency */
181189static const struct imx477_reg link_450Mhz_regs [] = {
182190 {0x030E , 0x00 },
@@ -532,7 +540,6 @@ static const struct imx477_reg mode_common_regs[] = {
532540 {0x9e9f , 0x00 },
533541 {0x0301 , 0x05 },
534542 {0x0303 , 0x02 },
535- {0x030b , 0x02 },
536543 {0x030d , 0x02 },
537544 {0x0310 , 0x01 },
538545 {0x0820 , 0x07 },
@@ -825,7 +832,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
825832 /* 12MPix 10fps mode */
826833 .width = 4056 ,
827834 .height = 3040 ,
828- .line_length_pix = 0x5dc0 ,
835+ .line_length_pix = 24000 ,
829836 .crop = {
830837 .left = IMX477_PIXEL_ARRAY_LEFT ,
831838 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -842,7 +849,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
842849 /* 2x2 binned 40fps mode */
843850 .width = 2028 ,
844851 .height = 1520 ,
845- .line_length_pix = 0x31c4 ,
852+ .line_length_pix = 12740 ,
846853 .crop = {
847854 .left = IMX477_PIXEL_ARRAY_LEFT ,
848855 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -859,7 +866,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
859866 /* 1080p 50fps cropped mode */
860867 .width = 2028 ,
861868 .height = 1080 ,
862- .line_length_pix = 0x31c4 ,
869+ .line_length_pix = 12740 ,
863870 .crop = {
864871 .left = IMX477_PIXEL_ARRAY_LEFT ,
865872 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -1010,6 +1017,12 @@ struct imx477 {
10101017 */
10111018 unsigned int csi2_flags ;
10121019
1020+ /*
1021+ * Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1022+ * line_length_pix can be halved in that case.
1023+ */
1024+ bool double_link_freq ;
1025+
10131026 /* Rewrite common registers on stream on? */
10141027 bool common_regs_written ;
10151028
@@ -1453,6 +1466,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14531466{
14541467 unsigned int frm_length_default , hblank_min ;
14551468 const struct imx477_mode * mode = imx477 -> mode ;
1469+ unsigned int line_length_pix ;
14561470
14571471 frm_length_default =
14581472 imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1469,7 +1483,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14691483 /* Setting this will adjust the exposure limits as well. */
14701484 __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
14711485
1472- hblank_min = mode -> line_length_pix - mode -> width ;
1486+ line_length_pix = mode -> line_length_pix ;
1487+ if (imx477 -> double_link_freq )
1488+ line_length_pix /= 2 ;
1489+ hblank_min = line_length_pix - mode -> width ;
14731490 __v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
14741491 IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
14751492 __v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1616,6 +1633,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
16161633 imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
16171634 1 : 0 );
16181635
1636+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1637+ IMX477_REG_VALUE_08BIT ,
1638+ imx477 -> double_link_freq ? 1 : 2 );
1639+
16191640 imx477 -> common_regs_written = true;
16201641 }
16211642
@@ -1873,6 +1894,7 @@ static int imx477_init_controls(struct imx477 *imx477)
18731894 struct v4l2_ctrl_handler * ctrl_hdlr ;
18741895 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
18751896 struct v4l2_fwnode_device_properties props ;
1897+ const u64 * link_freq_menu ;
18761898 unsigned int i ;
18771899 int ret ;
18781900
@@ -1894,10 +1916,15 @@ static int imx477_init_controls(struct imx477 *imx477)
18941916 imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
18951917
18961918 /* LINK_FREQ is also read only */
1919+ if (imx477 -> double_link_freq )
1920+ link_freq_menu = & imx477_double_link_freq_menu [imx477 -> link_freq_idx ];
1921+ else
1922+ link_freq_menu = & imx477_link_freq_menu [imx477 -> link_freq_idx ];
1923+
18971924 imx477 -> link_freq =
18981925 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
18991926 V4L2_CID_LINK_FREQ , 0 , 0 ,
1900- & link_freqs [ imx477 -> link_freq_idx ] );
1927+ link_freq_menu );
19011928 if (imx477 -> link_freq )
19021929 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19031930
@@ -2027,14 +2054,21 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20272054 goto error_out ;
20282055 }
20292056
2030- for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2031- if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2057+ for (i = 0 ; i < ARRAY_SIZE (imx477_link_freq_menu ); i ++ ) {
2058+ if (imx477_link_freq_menu [i ] == ep_cfg .link_frequencies [0 ] ||
2059+ imx477_double_link_freq_menu [i ] ==
2060+ ep_cfg .link_frequencies [0 ]) {
20322061 imx477 -> link_freq_idx = i ;
2062+
2063+ if (imx477_double_link_freq_menu [i ] ==
2064+ ep_cfg .link_frequencies [0 ])
2065+ imx477 -> double_link_freq = true;
2066+
20332067 break ;
20342068 }
20352069 }
20362070
2037- if (i == ARRAY_SIZE (link_freqs )) {
2071+ if (i == ARRAY_SIZE (imx477_link_freq_menu )) {
20382072 dev_err (dev , "Link frequency not supported: %lld\n" ,
20392073 ep_cfg .link_frequencies [0 ]);
20402074 ret = - EINVAL ;
0 commit comments