@@ -164,8 +164,48 @@ struct imx477_mode {
164164 struct imx477_reg_list reg_list ;
165165};
166166
167- static const s64 imx477_link_freq_menu [] = {
168- IMX477_DEFAULT_LINK_FREQ ,
167+ /* Link frequency setup */
168+ enum {
169+ IMX477_LINK_FREQ_450MHZ ,
170+ IMX477_LINK_FREQ_447MHZ ,
171+ IMX477_LINK_FREQ_453MHZ ,
172+ };
173+
174+ static const s64 link_freqs [] = {
175+ [IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
176+ [IMX477_LINK_FREQ_447MHZ ] = 447000000 ,
177+ [IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
178+ };
179+
180+ /* 450MHz is the nominal "default" link frequency */
181+ static const struct imx477_reg link_450Mhz_regs [] = {
182+ {0x030E , 0x00 },
183+ {0x030F , 0x96 },
184+ };
185+
186+ static const struct imx477_reg link_447Mhz_regs [] = {
187+ {0x030E , 0x00 },
188+ {0x030F , 0x95 },
189+ };
190+
191+ static const struct imx477_reg link_453Mhz_regs [] = {
192+ {0x030E , 0x00 },
193+ {0x030F , 0x97 },
194+ };
195+
196+ static const struct imx477_reg_list link_freq_regs [] = {
197+ [IMX477_LINK_FREQ_450MHZ ] = {
198+ .regs = link_450Mhz_regs ,
199+ .num_of_regs = ARRAY_SIZE (link_450Mhz_regs )
200+ },
201+ [IMX477_LINK_FREQ_447MHZ ] = {
202+ .regs = link_447Mhz_regs ,
203+ .num_of_regs = ARRAY_SIZE (link_447Mhz_regs )
204+ },
205+ [IMX477_LINK_FREQ_453MHZ ] = {
206+ .regs = link_453Mhz_regs ,
207+ .num_of_regs = ARRAY_SIZE (link_453Mhz_regs )
208+ },
169209};
170210
171211static const struct imx477_reg mode_common_regs [] = {
@@ -558,8 +598,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
558598 {0x0309 , 0x0c },
559599 {0x030b , 0x02 },
560600 {0x030d , 0x02 },
561- {0x030e , 0x00 },
562- {0x030f , 0x96 },
563601 {0x0310 , 0x01 },
564602 {0x0820 , 0x07 },
565603 {0x0821 , 0x08 },
@@ -659,8 +697,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
659697 {0x0309 , 0x0c },
660698 {0x030b , 0x02 },
661699 {0x030d , 0x02 },
662- {0x030e , 0x00 },
663- {0x030f , 0x96 },
664700 {0x0310 , 0x01 },
665701 {0x0820 , 0x07 },
666702 {0x0821 , 0x08 },
@@ -760,8 +796,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
760796 {0x0309 , 0x0c },
761797 {0x030b , 0x02 },
762798 {0x030d , 0x02 },
763- {0x030e , 0x00 },
764- {0x030f , 0x96 },
765799 {0x0310 , 0x01 },
766800 {0x0820 , 0x07 },
767801 {0x0821 , 0x08 },
@@ -890,8 +924,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
890924 {0x0309 , 0x0a },
891925 {0x030b , 0x02 },
892926 {0x030d , 0x02 },
893- {0x030e , 0x00 },
894- {0x030f , 0x96 },
895927 {0x0310 , 0x01 },
896928 {0x0820 , 0x07 },
897929 {0x0821 , 0x08 },
@@ -1121,6 +1153,8 @@ struct imx477 {
11211153 struct v4l2_ctrl * vblank ;
11221154 struct v4l2_ctrl * hblank ;
11231155
1156+ unsigned int link_freq_idx ;
1157+
11241158 /* Current mode */
11251159 const struct imx477_mode * mode ;
11261160
@@ -1712,7 +1746,7 @@ static int imx477_get_selection(struct v4l2_subdev *sd,
17121746static int imx477_start_streaming (struct imx477 * imx477 )
17131747{
17141748 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1715- const struct imx477_reg_list * reg_list ;
1749+ const struct imx477_reg_list * reg_list , * freq_regs ;
17161750 const struct imx477_reg_list * extra_regs ;
17171751 int ret , tm ;
17181752
@@ -1725,6 +1759,13 @@ static int imx477_start_streaming(struct imx477 *imx477)
17251759 extra_regs -> num_of_regs );
17261760 }
17271761
1762+ if (!ret ) {
1763+ /* Update the link frequency registers */
1764+ freq_regs = & link_freq_regs [imx477 -> link_freq_idx ];
1765+ ret = imx477_write_regs (imx477 , freq_regs -> regs ,
1766+ freq_regs -> num_of_regs );
1767+ }
1768+
17281769 if (ret ) {
17291770 dev_err (& client -> dev , "%s failed to set common settings\n" ,
17301771 __func__ );
@@ -2010,9 +2051,8 @@ static int imx477_init_controls(struct imx477 *imx477)
20102051 /* LINK_FREQ is also read only */
20112052 imx477 -> link_freq =
20122053 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
2013- V4L2_CID_LINK_FREQ ,
2014- ARRAY_SIZE (imx477_link_freq_menu ) - 1 , 0 ,
2015- imx477_link_freq_menu );
2054+ V4L2_CID_LINK_FREQ , 1 , 0 ,
2055+ & link_freqs [imx477 -> link_freq_idx ]);
20162056 if (imx477 -> link_freq )
20172057 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
20182058
@@ -2110,13 +2150,14 @@ static void imx477_free_controls(struct imx477 *imx477)
21102150 mutex_destroy (& imx477 -> mutex );
21112151}
21122152
2113- static int imx477_check_hwcfg (struct device * dev )
2153+ static int imx477_check_hwcfg (struct device * dev , struct imx477 * imx477 )
21142154{
21152155 struct fwnode_handle * endpoint ;
21162156 struct v4l2_fwnode_endpoint ep_cfg = {
21172157 .bus_type = V4L2_MBUS_CSI2_DPHY
21182158 };
21192159 int ret = - EINVAL ;
2160+ int i ;
21202161
21212162 endpoint = fwnode_graph_get_next_endpoint (dev_fwnode (dev ), NULL );
21222163 if (!endpoint ) {
@@ -2141,11 +2182,18 @@ static int imx477_check_hwcfg(struct device *dev)
21412182 goto error_out ;
21422183 }
21432184
2144- if (ep_cfg .nr_of_link_frequencies != 1 ||
2145- ep_cfg .link_frequencies [0 ] != IMX477_DEFAULT_LINK_FREQ ) {
2185+ for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2186+ if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2187+ imx477 -> link_freq_idx = i ;
2188+ break ;
2189+ }
2190+ }
2191+
2192+ if (i == ARRAY_SIZE (link_freqs )) {
21462193 dev_err (dev , "Link frequency not supported: %lld\n" ,
21472194 ep_cfg .link_frequencies [0 ]);
2148- goto error_out ;
2195+ ret = - EINVAL ;
2196+ goto error_out ;
21492197 }
21502198
21512199 ret = 0 ;
@@ -2206,7 +2254,7 @@ static int imx477_probe(struct i2c_client *client)
22062254 (const struct imx477_compatible_data * )match -> data ;
22072255
22082256 /* Check the hardware configuration in device tree */
2209- if (imx477_check_hwcfg (dev ))
2257+ if (imx477_check_hwcfg (dev , imx477 ))
22102258 return - EINVAL ;
22112259
22122260 /* Default the trigger mode from OF to -1, which means invalid */
0 commit comments