@@ -87,6 +87,12 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8787#define IMX477_DGTL_GAIN_DEFAULT 0x0100
8888#define IMX477_DGTL_GAIN_STEP 1
8989
90+ #define IMX477_REG_IOP_SYSCK_DIV CCI_REG8(0x030b)
91+ #define IMX477_IOP_SYSCK_DIV 0x02
92+ #define IMX477_REG_IOP_PREDIV CCI_REG8(0x030d)
93+ #define IMX477_IOP_PREDIV 0x02
94+ #define IMX477_REG_IOP_MPY CCI_REG16(0x030e)
95+
9096/* Test Pattern Control */
9197#define IMX477_REG_TEST_PATTERN CCI_REG8(0x0600)
9298#define IMX477_TEST_PATTERN_DISABLE 0
@@ -161,83 +167,6 @@ struct imx477_mode {
161167 struct imx477_reg_list reg_list ;
162168};
163169
164- /* Link frequency setup */
165- enum {
166- IMX477_LINK_FREQ_450MHZ ,
167- IMX477_LINK_FREQ_453MHZ ,
168- IMX477_LINK_FREQ_456MHZ ,
169- IMX477_LINK_FREQ_459MHZ ,
170- IMX477_LINK_FREQ_462MHZ ,
171- IMX477_LINK_FREQ_498MHZ ,
172- };
173-
174- static const s64 link_freqs [] = {
175- [IMX477_LINK_FREQ_450MHZ ] = 450000000 ,
176- [IMX477_LINK_FREQ_453MHZ ] = 453000000 ,
177- [IMX477_LINK_FREQ_456MHZ ] = 456000000 ,
178- [IMX477_LINK_FREQ_459MHZ ] = 459000000 ,
179- [IMX477_LINK_FREQ_462MHZ ] = 462000000 ,
180- [IMX477_LINK_FREQ_498MHZ ] = 498000000 ,
181- };
182-
183- /* 450MHz is the nominal "default" link frequency */
184- static const struct cci_reg_sequence link_450Mhz_regs [] = {
185- {CCI_REG8 (0x030e ), 0x00 },
186- {CCI_REG8 (0x030f ), 0x96 },
187- };
188-
189- static const struct cci_reg_sequence link_453Mhz_regs [] = {
190- {CCI_REG8 (0x030e ), 0x00 },
191- {CCI_REG8 (0x030f ), 0x97 },
192- };
193-
194- static const struct cci_reg_sequence link_456Mhz_regs [] = {
195- {CCI_REG8 (0x030e ), 0x00 },
196- {CCI_REG8 (0x030f ), 0x98 },
197- };
198-
199- static const struct cci_reg_sequence link_459Mhz_regs [] = {
200- {CCI_REG8 (0x030e ), 0x00 },
201- {CCI_REG8 (0x030f ), 0x99 },
202- };
203-
204- static const struct cci_reg_sequence link_462Mhz_regs [] = {
205- {CCI_REG8 (0x030e ), 0x00 },
206- {CCI_REG8 (0x030f ), 0x9a },
207- };
208-
209- static const struct cci_reg_sequence link_498Mhz_regs [] = {
210- {CCI_REG8 (0x030e ), 0x00 },
211- {CCI_REG8 (0x030f ), 0xa6 },
212- };
213-
214- static const struct imx477_reg_list link_freq_regs [] = {
215- [IMX477_LINK_FREQ_450MHZ ] = {
216- .regs = link_450Mhz_regs ,
217- .num_of_regs = ARRAY_SIZE (link_450Mhz_regs )
218- },
219- [IMX477_LINK_FREQ_453MHZ ] = {
220- .regs = link_453Mhz_regs ,
221- .num_of_regs = ARRAY_SIZE (link_453Mhz_regs )
222- },
223- [IMX477_LINK_FREQ_456MHZ ] = {
224- .regs = link_456Mhz_regs ,
225- .num_of_regs = ARRAY_SIZE (link_456Mhz_regs )
226- },
227- [IMX477_LINK_FREQ_459MHZ ] = {
228- .regs = link_459Mhz_regs ,
229- .num_of_regs = ARRAY_SIZE (link_459Mhz_regs )
230- },
231- [IMX477_LINK_FREQ_462MHZ ] = {
232- .regs = link_462Mhz_regs ,
233- .num_of_regs = ARRAY_SIZE (link_462Mhz_regs )
234- },
235- [IMX477_LINK_FREQ_498MHZ ] = {
236- .regs = link_498Mhz_regs ,
237- .num_of_regs = ARRAY_SIZE (link_498Mhz_regs )
238- },
239- };
240-
241170static const struct cci_reg_sequence mode_common_regs [] = {
242171 {CCI_REG8 (0x0136 ), 0x18 },
243172 {CCI_REG8 (0x0137 ), 0x00 },
@@ -565,8 +494,8 @@ static const struct cci_reg_sequence mode_common_regs[] = {
565494 {CCI_REG8 (0x9e9f ), 0x00 },
566495 {CCI_REG8 (0x0301 ), 0x05 },
567496 {CCI_REG8 (0x0303 ), 0x02 },
568- {CCI_REG8 ( 0x030b ), 0x02 },
569- {CCI_REG8 ( 0x030d ), 0x02 },
497+ {IMX477_REG_IOP_SYSCK_DIV , IMX477_IOP_SYSCK_DIV },
498+ {IMX477_REG_IOP_PREDIV , IMX477_IOP_PREDIV },
570499 {CCI_REG8 (0x0310 ), 0x01 },
571500 {CCI_REG8 (0x0820 ), 0x07 },
572501 {CCI_REG8 (0x0821 ), 0x08 },
@@ -1109,7 +1038,8 @@ struct imx477 {
11091038 struct v4l2_ctrl * vblank ;
11101039 struct v4l2_ctrl * hblank ;
11111040
1112- unsigned int link_freq_idx ;
1041+ u64 link_freq_value ;
1042+ u16 iop_pll_mpy ;
11131043
11141044 /* Current mode */
11151045 const struct imx477_mode * mode ;
@@ -1614,7 +1544,7 @@ static int imx477_get_selection(struct v4l2_subdev *sd,
16141544static int imx477_start_streaming (struct imx477 * imx477 )
16151545{
16161546 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1617- const struct imx477_reg_list * reg_list , * freq_regs ;
1547+ const struct imx477_reg_list * reg_list ;
16181548 const struct imx477_reg_list * extra_regs ;
16191549 int ret , tm ;
16201550
@@ -1626,10 +1556,9 @@ static int imx477_start_streaming(struct imx477 *imx477)
16261556 cci_multi_reg_write (imx477 -> regmap , extra_regs -> regs ,
16271557 extra_regs -> num_of_regs , & ret );
16281558
1629- /* Update the link frequency registers */
1630- freq_regs = & link_freq_regs [imx477 -> link_freq_idx ];
1631- cci_multi_reg_write (imx477 -> regmap , freq_regs -> regs ,
1632- freq_regs -> num_of_regs , & ret );
1559+ /* Update the link frequency PLL multiplier register */
1560+ cci_write (imx477 -> regmap , IMX477_REG_IOP_MPY ,
1561+ imx477 -> iop_pll_mpy , & ret );
16331562
16341563 if (ret ) {
16351564 dev_err (& client -> dev , "%s failed to set common settings\n" ,
@@ -1922,7 +1851,7 @@ static int imx477_init_controls(struct imx477 *imx477)
19221851 imx477 -> link_freq =
19231852 v4l2_ctrl_new_int_menu (ctrl_hdlr , & imx477_ctrl_ops ,
19241853 V4L2_CID_LINK_FREQ , 0 , 0 ,
1925- & link_freqs [ imx477 -> link_freq_idx ] );
1854+ & imx477 -> link_freq_value );
19261855 if (imx477 -> link_freq )
19271856 imx477 -> link_freq -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
19281857
@@ -2021,6 +1950,25 @@ static void imx477_free_controls(struct imx477 *imx477)
20211950 mutex_destroy (& imx477 -> mutex );
20221951}
20231952
1953+ static int imx477_check_link_freq (u64 link_frequency , u16 * mpy_out )
1954+ {
1955+ u64 mpy = link_frequency * 2 * IMX477_IOP_SYSCK_DIV * IMX477_IOP_PREDIV ;
1956+ u64 tmp ;
1957+
1958+ do_div (mpy , IMX477_XCLK_FREQ );
1959+
1960+ tmp = mpy * (IMX477_XCLK_FREQ / IMX477_IOP_PREDIV );
1961+ do_div (tmp , IMX477_IOP_SYSCK_DIV * 2 );
1962+
1963+ if (tmp != link_frequency )
1964+ return - EINVAL ;
1965+
1966+ if (mpy_out )
1967+ * mpy_out = mpy ;
1968+
1969+ return 0 ;
1970+ }
1971+
20241972static int imx477_check_hwcfg (struct device * dev , struct imx477 * imx477 )
20251973{
20261974 struct fwnode_handle * endpoint ;
@@ -2053,16 +2001,16 @@ static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
20532001 goto error_out ;
20542002 }
20552003
2056- for (i = 0 ; i < ARRAY_SIZE (link_freqs ); i ++ ) {
2057- if (link_freqs [i ] == ep_cfg .link_frequencies [0 ]) {
2058- imx477 -> link_freq_idx = i ;
2004+ for (i = 0 ; i < ep_cfg .nr_of_link_frequencies ; i ++ ) {
2005+ if (!imx477_check_link_freq (ep_cfg .link_frequencies [i ],
2006+ & imx477 -> iop_pll_mpy )) {
2007+ imx477 -> link_freq_value = ep_cfg .link_frequencies [i ];
20592008 break ;
20602009 }
20612010 }
20622011
2063- if (i == ARRAY_SIZE (link_freqs )) {
2064- dev_err (dev , "Link frequency not supported: %lld\n" ,
2065- ep_cfg .link_frequencies [0 ]);
2012+ if (i == ep_cfg .nr_of_link_frequencies ) {
2013+ dev_err (dev , "No supported link frequency configured\n" );
20662014 ret = - EINVAL ;
20672015 goto error_out ;
20682016 }
0 commit comments