@@ -103,6 +103,12 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
103103#define IMX477_DGTL_GAIN_DEFAULT 0x0100
104104#define IMX477_DGTL_GAIN_STEP 1
105105
106+ #define IMX477_REG_IOP_SYSCK_DIV CCI_REG8(0x030b)
107+ #define IMX477_IOP_SYSCK_DIV 0x02
108+ #define IMX477_REG_IOP_PREDIV CCI_REG8(0x030d)
109+ #define IMX477_IOP_PREDIV 0x02
110+ #define IMX477_REG_IOP_MPY CCI_REG16(0x030e)
111+
106112/* Test Pattern Control */
107113#define IMX477_REG_TEST_PATTERN CCI_REG8(0x0600)
108114#define IMX477_TEST_PATTERN_DISABLE 0
@@ -177,83 +183,6 @@ struct imx477_mode {
177183 struct imx477_reg_list reg_list ;
178184};
179185
180- /* Link frequency setup */
181- enum {
182- IMX477_LINK_FREQ_450MHZ ,
183- IMX477_LINK_FREQ_453MHZ ,
184- IMX477_LINK_FREQ_456MHZ ,
185- IMX477_LINK_FREQ_459MHZ ,
186- IMX477_LINK_FREQ_462MHZ ,
187- IMX477_LINK_FREQ_498MHZ ,
188- };
189-
190- static const s64 link_freqs [] = {
191- [IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
192- [IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
193- [IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
194- [IMX477_LINK_FREQ_459MHZ ] = 459000000 ,
195- [IMX477_LINK_FREQ_462MHZ ] = 462000000 ,
196- [IMX477_LINK_FREQ_498MHZ ] = 498000000 ,
197- };
198-
199- /* 450MHz is the nominal "default" link frequency */
200- static const struct cci_reg_sequence link_450Mhz_regs [] = {
201- {CCI_REG8 (0x030e ), 0x00 },
202- {CCI_REG8 (0x030f ), 0x96 },
203- };
204-
205- static const struct cci_reg_sequence link_453Mhz_regs [] = {
206- {CCI_REG8 (0x030e ), 0x00 },
207- {CCI_REG8 (0x030f ), 0x97 },
208- };
209-
210- static const struct cci_reg_sequence link_456Mhz_regs [] = {
211- {CCI_REG8 (0x030e ), 0x00 },
212- {CCI_REG8 (0x030f ), 0x98 },
213- };
214-
215- static const struct cci_reg_sequence link_459Mhz_regs [] = {
216- {CCI_REG8 (0x030e ), 0x00 },
217- {CCI_REG8 (0x030f ), 0x99 },
218- };
219-
220- static const struct cci_reg_sequence link_462Mhz_regs [] = {
221- {CCI_REG8 (0x030e ), 0x00 },
222- {CCI_REG8 (0x030f ), 0x9a },
223- };
224-
225- static const struct cci_reg_sequence link_498Mhz_regs [] = {
226- {CCI_REG8 (0x030e ), 0x00 },
227- {CCI_REG8 (0x030f ), 0xa6 },
228- };
229-
230- static const struct imx477_reg_list link_freq_regs [] = {
231- [IMX477_LINK_FREQ_450MHZ ] = {
232- .regs = link_450Mhz_regs ,
233- .num_of_regs = ARRAY_SIZE (link_450Mhz_regs )
234- },
235- [IMX477_LINK_FREQ_453MHZ ] = {
236- .regs = link_453Mhz_regs ,
237- .num_of_regs = ARRAY_SIZE (link_453Mhz_regs )
238- },
239- [IMX477_LINK_FREQ_456MHZ ] = {
240- .regs = link_456Mhz_regs ,
241- .num_of_regs = ARRAY_SIZE (link_456Mhz_regs )
242- },
243- [IMX477_LINK_FREQ_459MHZ ] = {
244- .regs = link_459Mhz_regs ,
245- .num_of_regs = ARRAY_SIZE (link_459Mhz_regs )
246- },
247- [IMX477_LINK_FREQ_462MHZ ] = {
248- .regs = link_462Mhz_regs ,
249- .num_of_regs = ARRAY_SIZE (link_462Mhz_regs )
250- },
251- [IMX477_LINK_FREQ_498MHZ ] = {
252- .regs = link_498Mhz_regs ,
253- .num_of_regs = ARRAY_SIZE (link_498Mhz_regs )
254- },
255- };
256-
257186static const struct cci_reg_sequence mode_common_regs [] = {
258187 {CCI_REG8 (0x0136 ), 0x18 },
259188 {CCI_REG8 (0x0137 ), 0x00 },
@@ -581,8 +510,8 @@ static const struct cci_reg_sequence mode_common_regs[] = {
581510 {CCI_REG8 (0x9e9f ), 0x00 },
582511 {CCI_REG8 (0x0301 ), 0x05 },
583512 {CCI_REG8 (0x0303 ), 0x02 },
584- {CCI_REG8 ( 0x030b ), 0x02 },
585- {CCI_REG8 ( 0x030d ), 0x02 },
513+ {IMX477_REG_IOP_SYSCK_DIV , IMX477_IOP_SYSCK_DIV },
514+ {IMX477_REG_IOP_PREDIV , IMX477_IOP_PREDIV },
586515 {CCI_REG8 (0x0310 ), 0x01 },
587516 {CCI_REG8 (0x0820 ), 0x07 },
588517 {CCI_REG8 (0x0821 ), 0x08 },
@@ -1125,7 +1054,8 @@ struct imx477 {
11251054 struct v4l2_ctrl * vblank ;
11261055 struct v4l2_ctrl * hblank ;
11271056
1128- unsigned int link_freq_idx ;
1057+ u64 link_freq_value ;
1058+ u16 iop_pll_mpy ;
11291059
11301060 /* Current mode */
11311061 const struct imx477_mode * mode ;
@@ -1630,7 +1560,7 @@ static int imx477_get_selection(struct v4l2_subdev *sd,
16301560static int imx477_start_streaming (struct imx477 * imx477 )
16311561{
16321562 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1633- const struct imx477_reg_list * reg_list , * freq_regs ;
1563+ const struct imx477_reg_list * reg_list ;
16341564 const struct imx477_reg_list * extra_regs ;
16351565 unsigned int fst_width ;
16361566 unsigned int fst_mult ;
@@ -1644,10 +1574,9 @@ static int imx477_start_streaming(struct imx477 *imx477)
16441574 cci_multi_reg_write (imx477 -> regmap , extra_regs -> regs ,
16451575 extra_regs -> num_of_regs , & ret );
16461576
1647- /* Update the link frequency registers */
1648- freq_regs = & link_freq_regs [imx477 -> link_freq_idx ];
1649- cci_multi_reg_write (imx477 -> regmap , freq_regs -> regs ,
1650- freq_regs -> num_of_regs , & ret );
1577+ /* Update the link frequency PLL multiplier register */
1578+ cci_write (imx477 -> regmap , IMX477_REG_IOP_MPY ,
1579+ imx477 -> iop_pll_mpy , & ret );
16511580
16521581 if (ret ) {
16531582 dev_err (& client -> dev , "%s failed to set common settings\n" ,
@@ -1962,7 +1891,7 @@ static int imx477_init_controls(struct imx477 *imx477)
19621891 imx477 -> link_freq =
19631892 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
19641893 V4L2_CID_LINK_FREQ , 0 , 0 ,
1965- & link_freqs [ imx477 -> link_freq_idx ] );
1894+ & imx477 -> link_freq_value );
19661895 if (imx477 -> link_freq )
19671896 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19681897
@@ -2061,6 +1990,25 @@ static void imx477_free_controls(struct imx477 *imx477)
20611990 mutex_destroy (& imx477 -> mutex );
20621991}
20631992
1993+ static int imx477_check_link_freq (u64 link_frequency , u16 * mpy_out )
1994+ {
1995+ u64 mpy = link_frequency * 2 * IMX477_IOP_SYSCK_DIV * IMX477_IOP_PREDIV ;
1996+ u64 tmp ;
1997+
1998+ do_div (mpy , IMX477_XCLK_FREQ );
1999+
2000+ tmp = mpy * (IMX477_XCLK_FREQ / IMX477_IOP_PREDIV );
2001+ do_div (tmp , IMX477_IOP_SYSCK_DIV * 2 );
2002+
2003+ if (tmp != link_frequency )
2004+ return - EINVAL ;
2005+
2006+ if (mpy_out )
2007+ * mpy_out = mpy ;
2008+
2009+ return 0 ;
2010+ }
2011+
20642012static int imx477_check_hwcfg (struct device * dev , struct imx477 * imx477 )
20652013{
20662014 struct fwnode_handle * endpoint ;
@@ -2093,16 +2041,16 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20932041 goto error_out ;
20942042 }
20952043
2096- for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2097- if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2098- imx477 -> link_freq_idx = i ;
2044+ for (i = 0 ; i < ep_cfg .nr_of_link_frequencies ; i ++ ) {
2045+ if (!imx477_check_link_freq (ep_cfg .link_frequencies [i ],
2046+ & imx477 -> iop_pll_mpy )) {
2047+ imx477 -> link_freq_value = ep_cfg .link_frequencies [i ];
20992048 break ;
21002049 }
21012050 }
21022051
2103- if (i == ARRAY_SIZE (link_freqs )) {
2104- dev_err (dev , "Link frequency not supported: %lld\n" ,
2105- ep_cfg .link_frequencies [0 ]);
2052+ if (i == ep_cfg .nr_of_link_frequencies ) {
2053+ dev_err (dev , "No supported link frequency configured\n" );
21062054 ret = - EINVAL ;
21072055 goto error_out ;
21082056 }
0 commit comments