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