@@ -86,6 +86,8 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
86
86
#define IMX477_DGTL_GAIN_DEFAULT 0x0100
87
87
#define IMX477_DGTL_GAIN_STEP 1
88
88
89
+ #define IMX477_REG_DIV_IOP_PX 0x030b
90
+
89
91
/* Test Pattern Control */
90
92
#define IMX477_REG_TEST_PATTERN 0x0600
91
93
#define IMX477_TEST_PATTERN_DISABLE 0
@@ -151,7 +153,7 @@ struct imx477_mode {
151
153
/* Frame height */
152
154
unsigned int height ;
153
155
154
- /* H-timing in pixels */
156
+ /* H-timing in pixels when at 450MHz link freq */
155
157
unsigned int line_length_pix ;
156
158
157
159
/* Analog crop rectangle. */
@@ -168,6 +170,10 @@ static const s64 imx477_link_freq_menu[] = {
168
170
IMX477_DEFAULT_LINK_FREQ ,
169
171
};
170
172
173
+ static const s64 imx477_double_link_freq_menu [] = {
174
+ IMX477_DEFAULT_LINK_FREQ * 2 ,
175
+ };
176
+
171
177
static const struct imx477_reg mode_common_regs [] = {
172
178
{0x0136 , 0x18 },
173
179
{0x0137 , 0x00 },
@@ -492,7 +498,6 @@ static const struct imx477_reg mode_common_regs[] = {
492
498
{0x9e9f , 0x00 },
493
499
{0x0301 , 0x05 },
494
500
{0x0303 , 0x02 },
495
- {0x030b , 0x02 },
496
501
{0x030d , 0x02 },
497
502
{0x030e , 0x00 },
498
503
{0x030f , 0x96 },
@@ -787,7 +792,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
787
792
/* 12MPix 10fps mode */
788
793
.width = 4056 ,
789
794
.height = 3040 ,
790
- .line_length_pix = 0x5dc0 ,
795
+ .line_length_pix = 24000 ,
791
796
.crop = {
792
797
.left = IMX477_PIXEL_ARRAY_LEFT ,
793
798
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -804,7 +809,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
804
809
/* 2x2 binned 40fps mode */
805
810
.width = 2028 ,
806
811
.height = 1520 ,
807
- .line_length_pix = 0x31c4 ,
812
+ .line_length_pix = 12740 ,
808
813
.crop = {
809
814
.left = IMX477_PIXEL_ARRAY_LEFT ,
810
815
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -821,7 +826,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
821
826
/* 1080p 50fps cropped mode */
822
827
.width = 2028 ,
823
828
.height = 1080 ,
824
- .line_length_pix = 0x31c4 ,
829
+ .line_length_pix = 12740 ,
825
830
.crop = {
826
831
.left = IMX477_PIXEL_ARRAY_LEFT ,
827
832
.top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -970,6 +975,12 @@ struct imx477 {
970
975
*/
971
976
unsigned int csi2_flags ;
972
977
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
+
973
984
/* Rewrite common registers on stream on? */
974
985
bool common_regs_written ;
975
986
@@ -1413,6 +1424,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1413
1424
{
1414
1425
unsigned int frm_length_default , hblank_min ;
1415
1426
const struct imx477_mode * mode = imx477 -> mode ;
1427
+ unsigned int line_length_pix ;
1416
1428
1417
1429
frm_length_default =
1418
1430
imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1429,7 +1441,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1429
1441
/* Setting this will adjust the exposure limits as well. */
1430
1442
__v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
1431
1443
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 ;
1433
1448
__v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
1434
1449
IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
1435
1450
__v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1569,6 +1584,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
1569
1584
imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
1570
1585
1 : 0 );
1571
1586
1587
+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1588
+ IMX477_REG_VALUE_08BIT ,
1589
+ imx477 -> double_link_freq ? 1 : 2 );
1590
+
1572
1591
imx477 -> common_regs_written = true;
1573
1592
}
1574
1593
@@ -1826,6 +1845,7 @@ static int imx477_init_controls(struct imx477 *imx477)
1826
1845
struct v4l2_ctrl_handler * ctrl_hdlr ;
1827
1846
struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1828
1847
struct v4l2_fwnode_device_properties props ;
1848
+ const u64 * link_freq_menu ;
1829
1849
unsigned int i ;
1830
1850
int ret ;
1831
1851
@@ -1847,11 +1867,16 @@ static int imx477_init_controls(struct imx477 *imx477)
1847
1867
imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
1848
1868
1849
1869
/* 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
+
1850
1875
imx477 -> link_freq =
1851
1876
v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
1852
1877
V4L2_CID_LINK_FREQ ,
1853
1878
ARRAY_SIZE (imx477_link_freq_menu ) - 1 , 0 ,
1854
- imx477_link_freq_menu );
1879
+ link_freq_menu );
1855
1880
if (imx477 -> link_freq )
1856
1881
imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
1857
1882
@@ -1981,11 +2006,14 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
1981
2006
}
1982
2007
1983
2008
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 )) {
1985
2011
dev_err (dev , "Link frequency not supported: %lld\n" ,
1986
2012
ep_cfg .link_frequencies [0 ]);
1987
2013
goto error_out ;
1988
2014
}
2015
+ if (ep_cfg .link_frequencies [0 ] == IMX477_DEFAULT_LINK_FREQ * 2 )
2016
+ imx477 -> double_link_freq = true;
1989
2017
1990
2018
imx477 -> csi2_flags = ep_cfg .bus .mipi_csi2 .flags ;
1991
2019
0 commit comments