@@ -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. */
@@ -174,7 +176,7 @@ enum {
174
176
IMX477_LINK_FREQ_498MHZ ,
175
177
};
176
178
177
- static const s64 link_freqs [] = {
179
+ static const u64 imx477_link_freq_menu [] = {
178
180
[IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
179
181
[IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
180
182
[IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
@@ -183,6 +185,12 @@ static const s64 link_freqs[] = {
183
185
[IMX477_LINK_FREQ_498MHZ ] = 498000000 ,
184
186
};
185
187
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
+
186
194
/* 450MHz is the nominal "default" link frequency */
187
195
static const struct imx477_reg link_450Mhz_regs [] = {
188
196
{0x030E , 0x00 },
@@ -565,7 +573,6 @@ static const struct imx477_reg mode_common_regs[] = {
565
573
{0x9e9f , 0x00 },
566
574
{0x0301 , 0x05 },
567
575
{0x0303 , 0x02 },
568
- {0x030b , 0x02 },
569
576
{0x030d , 0x02 },
570
577
{0x0310 , 0x01 },
571
578
{0x0820 , 0x07 },
@@ -858,7 +865,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
858
865
/* 12MPix 10fps mode */
859
866
.width = 4056 ,
860
867
.height = 3040 ,
861
- .line_length_pix = 0x5dc0 ,
868
+ .line_length_pix = 24000 ,
862
869
.crop = {
863
870
.left = IMX477_PIXEL_ARRAY_LEFT ,
864
871
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -875,7 +882,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
875
882
/* 2x2 binned 40fps mode */
876
883
.width = 2028 ,
877
884
.height = 1520 ,
878
- .line_length_pix = 0x31c4 ,
885
+ .line_length_pix = 12740 ,
879
886
.crop = {
880
887
.left = IMX477_PIXEL_ARRAY_LEFT ,
881
888
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -892,7 +899,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
892
899
/* 1080p 50fps cropped mode */
893
900
.width = 2028 ,
894
901
.height = 1080 ,
895
- .line_length_pix = 0x31c4 ,
902
+ .line_length_pix = 12740 ,
896
903
.crop = {
897
904
.left = IMX477_PIXEL_ARRAY_LEFT ,
898
905
.top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -1043,6 +1050,12 @@ struct imx477 {
1043
1050
*/
1044
1051
unsigned int csi2_flags ;
1045
1052
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
+
1046
1059
/* Rewrite common registers on stream on? */
1047
1060
bool common_regs_written ;
1048
1061
@@ -1486,6 +1499,7 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1486
1499
{
1487
1500
unsigned int frm_length_default , hblank_min ;
1488
1501
const struct imx477_mode * mode = imx477 -> mode ;
1502
+ unsigned int line_length_pix ;
1489
1503
1490
1504
frm_length_default =
1491
1505
imx477_get_frame_length (mode , mode -> framerate_default );
@@ -1502,7 +1516,10 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1502
1516
/* Setting this will adjust the exposure limits as well. */
1503
1517
__v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
1504
1518
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 ;
1506
1523
__v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
1507
1524
IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
1508
1525
__v4l2_ctrl_s_ctrl (imx477 -> hblank , hblank_min );
@@ -1649,6 +1666,10 @@ static int imx477_start_streaming(struct imx477 *imx477)
1649
1666
imx477 -> csi2_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ?
1650
1667
1 : 0 );
1651
1668
1669
+ imx477_write_reg (imx477 , IMX477_REG_DIV_IOP_PX ,
1670
+ IMX477_REG_VALUE_08BIT ,
1671
+ imx477 -> double_link_freq ? 1 : 2 );
1672
+
1652
1673
imx477 -> common_regs_written = true;
1653
1674
}
1654
1675
@@ -1906,6 +1927,7 @@ static int imx477_init_controls(struct imx477 *imx477)
1906
1927
struct v4l2_ctrl_handler * ctrl_hdlr ;
1907
1928
struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1908
1929
struct v4l2_fwnode_device_properties props ;
1930
+ const u64 * link_freq_menu ;
1909
1931
unsigned int i ;
1910
1932
int ret ;
1911
1933
@@ -1927,10 +1949,15 @@ static int imx477_init_controls(struct imx477 *imx477)
1927
1949
imx477 -> pixel_rate -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
1928
1950
1929
1951
/* 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
+
1930
1957
imx477 -> link_freq =
1931
1958
v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
1932
1959
V4L2_CID_LINK_FREQ , 0 , 0 ,
1933
- & link_freqs [ imx477 -> link_freq_idx ] );
1960
+ link_freq_menu );
1934
1961
if (imx477 -> link_freq )
1935
1962
imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
1936
1963
@@ -2060,14 +2087,21 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
2060
2087
goto error_out ;
2061
2088
}
2062
2089
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 ]) {
2065
2094
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
+
2066
2100
break ;
2067
2101
}
2068
2102
}
2069
2103
2070
- if (i == ARRAY_SIZE (link_freqs )) {
2104
+ if (i == ARRAY_SIZE (imx477_link_freq_menu )) {
2071
2105
dev_err (dev , "Link frequency not supported: %lld\n" ,
2072
2106
ep_cfg .link_frequencies [0 ]);
2073
2107
ret = - EINVAL ;
0 commit comments