@@ -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
@@ -154,7 +156,7 @@ struct imx477_mode {
154156 /* Frame height */
155157 unsigned int height ;
156158
157- /* H-timing in pixels */
159+ /* H-timing in pixels when at 450MHz link freq */
158160 unsigned int line_length_pix ;
159161
160162 /* Analog crop rectangle. */
@@ -177,7 +179,7 @@ enum {
177179 IMX477_LINK_FREQ_498MHZ ,
178180};
179181
180- static const s64 link_freqs [] = {
182+ static const u64 imx477_link_freq_menu [] = {
181183 [IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
182184 [IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
183185 [IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
@@ -186,6 +188,12 @@ static const s64 link_freqs[] = {
186188 [IMX477_LINK_FREQ_498MHZ ] = 498000000 ,
187189};
188190
191+ static const u64 imx477_double_link_freq_menu [] = {
192+ [IMX477_LINK_FREQ_450MHZ ] = 450000000 * 2 ,
193+ [IMX477_LINK_FREQ_453MHZ ] = 453000000 * 2 ,
194+ [IMX477_LINK_FREQ_456MHZ ] = 456000000 * 2 ,
195+ };
196+
189197/* 450MHz is the nominal "default" link frequency */
190198static const struct imx477_reg link_450Mhz_regs [] = {
191199 {0x030E , 0x00 },
@@ -568,7 +576,6 @@ static const struct imx477_reg mode_common_regs[] = {
568576 {0x9e9f , 0x00 },
569577 {0x0301 , 0x05 },
570578 {0x0303 , 0x02 },
571- {0x030b , 0x02 },
572579 {0x030d , 0x02 },
573580 {0x0310 , 0x01 },
574581 {0x0820 , 0x07 },
@@ -861,7 +868,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
861868 /* 12MPix 10fps mode */
862869 .width = 4056 ,
863870 .height = 3040 ,
864- .line_length_pix = 0x5dc0 ,
871+ .line_length_pix = 24000 ,
865872 .crop = {
866873 .left = IMX477_PIXEL_ARRAY_LEFT ,
867874 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -878,7 +885,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
878885 /* 2x2 binned 40fps mode */
879886 .width = 2028 ,
880887 .height = 1520 ,
881- .line_length_pix = 0x31c4 ,
888+ .line_length_pix = 12740 ,
882889 .crop = {
883890 .left = IMX477_PIXEL_ARRAY_LEFT ,
884891 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -895,7 +902,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
895902 /* 1080p 50fps cropped mode */
896903 .width = 2028 ,
897904 .height = 1080 ,
898- .line_length_pix = 0x31c4 ,
905+ .line_length_pix = 12740 ,
899906 .crop = {
900907 .left = IMX477_PIXEL_ARRAY_LEFT ,
901908 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -1046,6 +1053,12 @@ struct imx477 {
10461053 */
10471054 unsigned int csi2_flags ;
10481055
1056+ /*
1057+ * Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1058+ * line_length_pix can be halved in that case.
1059+ */
1060+ bool double_link_freq ;
1061+
10491062 /* Rewrite common registers on stream on? */
10501063 bool common_regs_written ;
10511064
@@ -1496,6 +1509,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14961509{
14971510 unsigned int frm_length_default , hblank_min ;
14981511 const struct imx477_mode * mode = imx477 -> mode ;
1512+ unsigned int line_length_pix ;
14991513
15001514 frm_length_default =
15011515 imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1512,7 +1526,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
15121526 /* Setting this will adjust the exposure limits as well. */
15131527 __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
15141528
1515- hblank_min = mode -> line_length_pix - mode -> width ;
1529+ line_length_pix = mode -> line_length_pix ;
1530+ if (imx477 -> double_link_freq )
1531+ line_length_pix /= 2 ;
1532+ hblank_min = line_length_pix - mode -> width ;
15161533 __v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
15171534 IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
15181535 __v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1659,6 +1676,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
16591676 imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
16601677 1 : 0 );
16611678
1679+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1680+ IMX477_REG_VALUE_08BIT ,
1681+ imx477 -> double_link_freq ? 1 : 2 );
1682+
16621683 imx477 -> common_regs_written = true;
16631684 }
16641685
@@ -1926,6 +1947,7 @@ static int imx477_init_controls(struct imx477 *imx477)
19261947 struct v4l2_ctrl_handler * ctrl_hdlr ;
19271948 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
19281949 struct v4l2_fwnode_device_properties props ;
1950+ const u64 * link_freq_menu ;
19291951 unsigned int i ;
19301952 int ret ;
19311953
@@ -1947,10 +1969,15 @@ static int imx477_init_controls(struct imx477 *imx477)
19471969 imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19481970
19491971 /* LINK_FREQ is also read only */
1972+ if (imx477 -> double_link_freq )
1973+ link_freq_menu = & imx477_double_link_freq_menu [imx477 -> link_freq_idx ];
1974+ else
1975+ link_freq_menu = & imx477_link_freq_menu [imx477 -> link_freq_idx ];
1976+
19501977 imx477 -> link_freq =
19511978 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
19521979 V4L2_CID_LINK_FREQ , 0 , 0 ,
1953- & link_freqs [ imx477 -> link_freq_idx ] );
1980+ link_freq_menu );
19541981 if (imx477 -> link_freq )
19551982 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19561983
@@ -2080,14 +2107,21 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20802107 goto error_out ;
20812108 }
20822109
2083- for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2084- if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2110+ for (i = 0 ; i < ARRAY_SIZE (imx477_link_freq_menu ); i ++ ) {
2111+ if (imx477_link_freq_menu [i ] == ep_cfg .link_frequencies [0 ] ||
2112+ imx477_double_link_freq_menu [i ] ==
2113+ ep_cfg .link_frequencies [0 ]) {
20852114 imx477 -> link_freq_idx = i ;
2115+
2116+ if (imx477_double_link_freq_menu [i ] ==
2117+ ep_cfg .link_frequencies [0 ])
2118+ imx477 -> double_link_freq = true;
2119+
20862120 break ;
20872121 }
20882122 }
20892123
2090- if (i == ARRAY_SIZE (link_freqs )) {
2124+ if (i == ARRAY_SIZE (imx477_link_freq_menu )) {
20912125 dev_err (dev , "Link frequency not supported: %lld\n" ,
20922126 ep_cfg .link_frequencies [0 ]);
20932127 ret = - EINVAL ;
0 commit comments