@@ -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. */
@@ -177,6 +179,12 @@ static const s64 link_freqs[] = {
177
179
[IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
178
180
};
179
181
182
+ static const s64 imx477_double_link_freq_menu [] = {
183
+ [IMX477_LINK_FREQ_450MHZ ] = 450000000 * 2 ,
184
+ [IMX477_LINK_FREQ_453MHZ ] = 453000000 * 2 ,
185
+ [IMX477_LINK_FREQ_456MHZ ] = 456000000 * 2 ,
186
+ };
187
+
180
188
/* 450MHz is the nominal "default" link frequency */
181
189
static const struct imx477_reg link_450Mhz_regs [] = {
182
190
{0x030E , 0x00 },
@@ -532,7 +540,6 @@ static const struct imx477_reg mode_common_regs[] = {
532
540
{0x9e9f , 0x00 },
533
541
{0x0301 , 0x05 },
534
542
{0x0303 , 0x02 },
535
- {0x030b , 0x02 },
536
543
{0x030d , 0x02 },
537
544
{0x0310 , 0x01 },
538
545
{0x0820 , 0x07 },
@@ -825,7 +832,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
825
832
/* 12MPix 10fps mode */
826
833
.width = 4056 ,
827
834
.height = 3040 ,
828
- .line_length_pix = 0x5dc0 ,
835
+ .line_length_pix = 24000 ,
829
836
.crop = {
830
837
.left = IMX477_PIXEL_ARRAY_LEFT ,
831
838
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -842,7 +849,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
842
849
/* 2x2 binned 40fps mode */
843
850
.width = 2028 ,
844
851
.height = 1520 ,
845
- .line_length_pix = 0x31c4 ,
852
+ .line_length_pix = 12740 ,
846
853
.crop = {
847
854
.left = IMX477_PIXEL_ARRAY_LEFT ,
848
855
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -859,7 +866,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
859
866
/* 1080p 50fps cropped mode */
860
867
.width = 2028 ,
861
868
.height = 1080 ,
862
- .line_length_pix = 0x31c4 ,
869
+ .line_length_pix = 12740 ,
863
870
.crop = {
864
871
.left = IMX477_PIXEL_ARRAY_LEFT ,
865
872
.top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -1010,6 +1017,12 @@ struct imx477 {
1010
1017
*/
1011
1018
unsigned int csi2_flags ;
1012
1019
1020
+ /*
1021
+ * Flag that CSI2 link is running at twice IMX477_DEFAULT_LINK_FREQ.
1022
+ * line_length_pix can be halved in that case.
1023
+ */
1024
+ bool double_link_freq ;
1025
+
1013
1026
/* Rewrite common registers on stream on? */
1014
1027
bool common_regs_written ;
1015
1028
@@ -1453,6 +1466,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1453
1466
{
1454
1467
unsigned int frm_length_default , hblank_min ;
1455
1468
const struct imx477_mode * mode = imx477 -> mode ;
1469
+ unsigned int line_length_pix ;
1456
1470
1457
1471
frm_length_default =
1458
1472
imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1469,7 +1483,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1469
1483
/* Setting this will adjust the exposure limits as well. */
1470
1484
__v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
1471
1485
1472
- hblank_min = mode -> line_length_pix - mode -> width ;
1486
+ line_length_pix = mode -> line_length_pix ;
1487
+ if (imx477 -> double_link_freq )
1488
+ line_length_pix /= 2 ;
1489
+ hblank_min = line_length_pix - mode -> width ;
1473
1490
__v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
1474
1491
IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
1475
1492
__v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1616,6 +1633,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
1616
1633
imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
1617
1634
1 : 0 );
1618
1635
1636
+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1637
+ IMX477_REG_VALUE_08BIT ,
1638
+ imx477 -> double_link_freq ? 1 : 2 );
1639
+
1619
1640
imx477 -> common_regs_written = true;
1620
1641
}
1621
1642
@@ -1873,6 +1894,7 @@ static int imx477_init_controls(struct imx477 *imx477)
1873
1894
struct v4l2_ctrl_handler * ctrl_hdlr ;
1874
1895
struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1875
1896
struct v4l2_fwnode_device_properties props ;
1897
+ const u64 * link_freq_menu ;
1876
1898
unsigned int i ;
1877
1899
int ret ;
1878
1900
@@ -1894,10 +1916,15 @@ static int imx477_init_controls(struct imx477 *imx477)
1894
1916
imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
1895
1917
1896
1918
/* LINK_FREQ is also read only */
1919
+ if (imx477 -> double_link_freq )
1920
+ link_freq_menu = imx477_double_link_freq_menu [imx477 -> link_freq_idx ];
1921
+ else
1922
+ link_freq_menu = imx477_link_freq_menu [imx477 -> link_freq_idx ];
1923
+
1897
1924
imx477 -> link_freq =
1898
1925
v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
1899
1926
V4L2_CID_LINK_FREQ , 0 , 0 ,
1900
- & link_freqs [ imx477 -> link_freq_idx ] );
1927
+ link_freq_menu );
1901
1928
if (imx477 -> link_freq )
1902
1929
imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
1903
1930
@@ -2028,8 +2055,15 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
2028
2055
}
2029
2056
2030
2057
for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2031
- if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2058
+ if (link_freqs [i ] == ep_cfg .link_frequencies [0 ] ||
2059
+ imx477_double_link_freq_menu [i ] ==
2060
+ ep_cfg .link_frequencies [0 ]) {
2032
2061
imx477 -> link_freq_idx = i ;
2062
+
2063
+ if (imx477_double_link_freq_menu [i ] ==
2064
+ ep_cfg .link_frequencies [0 ])
2065
+ imx477 -> double_link_freq = true;
2066
+
2033
2067
break ;
2034
2068
}
2035
2069
}
0 commit comments