@@ -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. */
@@ -168,6 +170,10 @@ static const s64 imx477_link_freq_menu[] = {
168170 IMX477_DEFAULT_LINK_FREQ ,
169171};
170172
173+ static const s64 imx477_double_link_freq_menu [] = {
174+ IMX477_DEFAULT_LINK_FREQ * 2 ,
175+ };
176+
171177static const struct imx477_reg mode_common_regs [] = {
172178 {0x0136 , 0x18 },
173179 {0x0137 , 0x00 },
@@ -492,7 +498,6 @@ static const struct imx477_reg mode_common_regs[] = {
492498 {0x9e9f , 0x00 },
493499 {0x0301 , 0x05 },
494500 {0x0303 , 0x02 },
495- {0x030b , 0x02 },
496501 {0x030d , 0x02 },
497502 {0x030e , 0x00 },
498503 {0x030f , 0x96 },
@@ -787,7 +792,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
787792 /* 12MPix 10fps mode */
788793 .width = 4056 ,
789794 .height = 3040 ,
790- .line_length_pix = 0x5dc0 ,
795+ .line_length_pix = 24000 ,
791796 .crop = {
792797 .left = IMX477_PIXEL_ARRAY_LEFT ,
793798 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -804,7 +809,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
804809 /* 2x2 binned 40fps mode */
805810 .width = 2028 ,
806811 .height = 1520 ,
807- .line_length_pix = 0x31c4 ,
812+ .line_length_pix = 12740 ,
808813 .crop = {
809814 .left = IMX477_PIXEL_ARRAY_LEFT ,
810815 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -821,7 +826,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
821826 /* 1080p 50fps cropped mode */
822827 .width = 2028 ,
823828 .height = 1080 ,
824- .line_length_pix = 0x31c4 ,
829+ .line_length_pix = 12740 ,
825830 .crop = {
826831 .left = IMX477_PIXEL_ARRAY_LEFT ,
827832 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -970,6 +975,12 @@ struct imx477 {
970975 */
971976 unsigned int csi2_flags ;
972977
978+ /*
979+ * Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
980+ * line_length_pix can be halved in that case.
981+ */
982+ bool double_link_freq ;
983+
973984 /* Rewrite common registers on stream on? */
974985 bool common_regs_written ;
975986
@@ -1413,6 +1424,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14131424{
14141425 unsigned int frm_length_default , hblank_min ;
14151426 const struct imx477_mode * mode = imx477 -> mode ;
1427+ unsigned int line_length_pix ;
14161428
14171429 frm_length_default =
14181430 imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1429,7 +1441,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14291441 /* Setting this will adjust the exposure limits as well. */
14301442 __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
14311443
1432- hblank_min = mode -> line_length_pix - mode -> width ;
1444+ line_length_pix = mode -> line_length_pix ;
1445+ if (imx477 -> double_link_freq )
1446+ line_length_pix /= 2 ;
1447+ hblank_min = line_length_pix - mode -> width ;
14331448 __v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
14341449 IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
14351450 __v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1569,6 +1584,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
15691584 imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
15701585 1 : 0 );
15711586
1587+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1588+ IMX477_REG_VALUE_08BIT ,
1589+ imx477 -> double_link_freq ? 1 : 2 );
1590+
15721591 imx477 -> common_regs_written = true;
15731592 }
15741593
@@ -1826,6 +1845,7 @@ static int imx477_init_controls(struct imx477 *imx477)
18261845 struct v4l2_ctrl_handler * ctrl_hdlr ;
18271846 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
18281847 struct v4l2_fwnode_device_properties props ;
1848+ const u64 * link_freq_menu ;
18291849 unsigned int i ;
18301850 int ret ;
18311851
@@ -1847,11 +1867,16 @@ static int imx477_init_controls(struct imx477 *imx477)
18471867 imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
18481868
18491869 /* LINK_FREQ is also read only */
1870+ if (imx477 -> double_link_freq )
1871+ link_freq_menu = imx477_double_link_freq_menu ;
1872+ else
1873+ link_freq_menu = imx477_link_freq_menu ;
1874+
18501875 imx477 -> link_freq =
18511876 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
18521877 V4L2_CID_LINK_FREQ ,
18531878 ARRAY_SIZE (imx477_link_freq_menu ) - 1 , 0 ,
1854- imx477_link_freq_menu );
1879+ link_freq_menu );
18551880 if (imx477 -> link_freq )
18561881 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
18571882
@@ -1981,11 +2006,14 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
19812006 }
19822007
19832008 if (ep_cfg .nr_of_link_frequencies != 1 ||
1984- ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ ) {
2009+ (ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ &&
2010+ ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ * 2 )) {
19852011 dev_err (dev , "Link frequency not supported: %lld\n" ,
19862012 ep_cfg .link_frequencies [0 ]);
19872013 goto error_out ;
19882014 }
2015+ if (ep_cfg .link_frequencies [0 ] == IMX477_DEFAULT_LINK_FREQ * 2 )
2016+ imx477 -> double_link_freq = true;
19892017
19902018 imx477 -> csi2_flags = ep_cfg .bus .mipi_csi2 .flags ;
19912019
0 commit comments