@@ -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. */
@@ -174,7 +176,7 @@ enum {
174176 IMX477_LINK_FREQ_498MHZ ,
175177};
176178
177- static const s64 link_freqs [] = {
179+ static const u64 imx477_link_freq_menu [] = {
178180 [IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
179181 [IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
180182 [IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
@@ -183,6 +185,12 @@ static const s64 link_freqs[] = {
183185 [IMX477_LINK_FREQ_498MHZ ] = 498000000 ,
184186};
185187
188+ static const u64 imx477_double_link_freq_menu [] = {
189+ [IMX477_LINK_FREQ_450MHZ ] = 450000000 * 2 ,
190+ [IMX477_LINK_FREQ_453MHZ ] = 453000000 * 2 ,
191+ [IMX477_LINK_FREQ_456MHZ ] = 456000000 * 2 ,
192+ };
193+
186194/* 450MHz is the nominal "default" link frequency */
187195static const struct imx477_reg link_450Mhz_regs [] = {
188196 {0x030E , 0x00 },
@@ -565,7 +573,6 @@ static const struct imx477_reg mode_common_regs[] = {
565573 {0x9e9f , 0x00 },
566574 {0x0301 , 0x05 },
567575 {0x0303 , 0x02 },
568- {0x030b , 0x02 },
569576 {0x030d , 0x02 },
570577 {0x0310 , 0x01 },
571578 {0x0820 , 0x07 },
@@ -858,7 +865,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
858865 /* 12MPix 10fps mode */
859866 .width = 4056 ,
860867 .height = 3040 ,
861- .line_length_pix = 0x5dc0 ,
868+ .line_length_pix = 24000 ,
862869 .crop = {
863870 .left = IMX477_PIXEL_ARRAY_LEFT ,
864871 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -875,7 +882,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
875882 /* 2x2 binned 40fps mode */
876883 .width = 2028 ,
877884 .height = 1520 ,
878- .line_length_pix = 0x31c4 ,
885+ .line_length_pix = 12740 ,
879886 .crop = {
880887 .left = IMX477_PIXEL_ARRAY_LEFT ,
881888 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -892,7 +899,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
892899 /* 1080p 50fps cropped mode */
893900 .width = 2028 ,
894901 .height = 1080 ,
895- .line_length_pix = 0x31c4 ,
902+ .line_length_pix = 12740 ,
896903 .crop = {
897904 .left = IMX477_PIXEL_ARRAY_LEFT ,
898905 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -1043,6 +1050,12 @@ struct imx477 {
10431050 */
10441051 unsigned int csi2_flags ;
10451052
1053+ /*
1054+ * Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1055+ * line_length_pix can be halved in that case.
1056+ */
1057+ bool double_link_freq ;
1058+
10461059 /* Rewrite common registers on stream on? */
10471060 bool common_regs_written ;
10481061
@@ -1486,6 +1499,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14861499{
14871500 unsigned int frm_length_default , hblank_min ;
14881501 const struct imx477_mode * mode = imx477 -> mode ;
1502+ unsigned int line_length_pix ;
14891503
14901504 frm_length_default =
14911505 imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1502,7 +1516,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
15021516 /* Setting this will adjust the exposure limits as well. */
15031517 __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
15041518
1505- hblank_min = mode -> line_length_pix - mode -> width ;
1519+ line_length_pix = mode -> line_length_pix ;
1520+ if (imx477 -> double_link_freq )
1521+ line_length_pix /= 2 ;
1522+ hblank_min = line_length_pix - mode -> width ;
15061523 __v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
15071524 IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
15081525 __v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1649,6 +1666,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
16491666 imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
16501667 1 : 0 );
16511668
1669+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1670+ IMX477_REG_VALUE_08BIT ,
1671+ imx477 -> double_link_freq ? 1 : 2 );
1672+
16521673 imx477 -> common_regs_written = true;
16531674 }
16541675
@@ -1906,6 +1927,7 @@ static int imx477_init_controls(struct imx477 *imx477)
19061927 struct v4l2_ctrl_handler * ctrl_hdlr ;
19071928 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
19081929 struct v4l2_fwnode_device_properties props ;
1930+ const u64 * link_freq_menu ;
19091931 unsigned int i ;
19101932 int ret ;
19111933
@@ -1927,10 +1949,15 @@ static int imx477_init_controls(struct imx477 *imx477)
19271949 imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19281950
19291951 /* LINK_FREQ is also read only */
1952+ if (imx477 -> double_link_freq )
1953+ link_freq_menu = & imx477_double_link_freq_menu [imx477 -> link_freq_idx ];
1954+ else
1955+ link_freq_menu = & imx477_link_freq_menu [imx477 -> link_freq_idx ];
1956+
19301957 imx477 -> link_freq =
19311958 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
19321959 V4L2_CID_LINK_FREQ , 0 , 0 ,
1933- & link_freqs [ imx477 -> link_freq_idx ] );
1960+ link_freq_menu );
19341961 if (imx477 -> link_freq )
19351962 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19361963
@@ -2060,14 +2087,21 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20602087 goto error_out ;
20612088 }
20622089
2063- for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2064- if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2090+ for (i = 0 ; i < ARRAY_SIZE (imx477_link_freq_menu ); i ++ ) {
2091+ if (imx477_link_freq_menu [i ] == ep_cfg .link_frequencies [0 ] ||
2092+ imx477_double_link_freq_menu [i ] ==
2093+ ep_cfg .link_frequencies [0 ]) {
20652094 imx477 -> link_freq_idx = i ;
2095+
2096+ if (imx477_double_link_freq_menu [i ] ==
2097+ ep_cfg .link_frequencies [0 ])
2098+ imx477 -> double_link_freq = true;
2099+
20662100 break ;
20672101 }
20682102 }
20692103
2070- if (i == ARRAY_SIZE (link_freqs )) {
2104+ if (i == ARRAY_SIZE (imx477_link_freq_menu )) {
20712105 dev_err (dev , "Link frequency not supported: %lld\n" ,
20722106 ep_cfg .link_frequencies [0 ]);
20732107 ret = - EINVAL ;
0 commit comments