2525#define IMX355_REG_CHIP_ID 0x0016
2626#define IMX355_CHIP_ID 0x0355
2727
28+ /* PLL registers that depend on the external clock frequency */
29+ #define IMX355_REG_EXTCLK_FREQ 0x0136
30+ #define IMX355_REG_PLL_VT_MUL 0x0306
31+ #define IMX355_REG_PLL_OP_MUL 0x030e
32+
2833/* V_TIMING internal */
2934#define IMX355_REG_FLL 0x0340
3035#define IMX355_FLL_MAX 0xffff
6368
6469/* default link frequency and external clock */
6570#define IMX355_LINK_FREQ_DEFAULT 360000000LL
66- #define IMX355_EXT_CLK 19200000
6771#define IMX355_LINK_FREQ_INDEX 0
6872
6973/* number of data lanes */
@@ -100,6 +104,33 @@ struct imx355_mode {
100104 struct imx355_reg_list reg_list ;
101105};
102106
107+ struct imx355_clk_params {
108+ u32 ext_clk ;
109+ u16 extclk_freq ; /* External clock (MHz) in 8.8 fixed point) */
110+ u16 pll_vt_mpy ; /* VT system PLL multiplier */
111+ u16 pll_op_mpy ; /* OP system PLL multiplier */
112+ };
113+
114+ /*
115+ * All modes use the same PLL dividers (PREPLLCK_VT_DIV=2, PREPLLCK_OP_DIV=2),
116+ * so the multipliers are adjusted to produce the same VCO frequencies:
117+ * VT VCO = 1152 MHz, OP VCO = 720 MHz
118+ */
119+ static const struct imx355_clk_params imx355_clk_params [] = {
120+ {
121+ .ext_clk = 19200000 ,
122+ .extclk_freq = 0x1333 , /* 19.2 MHz */
123+ .pll_vt_mpy = 120 , /* 19.2 / 2 * 120 = 1152 MHz */
124+ .pll_op_mpy = 75 , /* 19.2 / 2 * 75 = 720 MHz */
125+ },
126+ {
127+ .ext_clk = 24000000 ,
128+ .extclk_freq = 0x1800 , /* 24.0 MHz */
129+ .pll_vt_mpy = 96 , /* 24.0 / 2 * 96 = 1152 MHz */
130+ .pll_op_mpy = 60 , /* 24.0 / 2 * 60 = 720 MHz */
131+ },
132+ };
133+
103134struct imx355_hwcfg {
104135 unsigned long link_freq_bitmap ;
105136};
@@ -125,6 +156,7 @@ struct imx355 {
125156 const struct imx355_mode * cur_mode ;
126157
127158 struct imx355_hwcfg * hwcfg ;
159+ const struct imx355_clk_params * clk_params ;
128160
129161 /*
130162 * Mutex for serialized access:
@@ -144,8 +176,6 @@ static const struct regulator_bulk_data imx355_supplies[] = {
144176};
145177
146178static const struct imx355_reg imx355_global_regs [] = {
147- { 0x0136 , 0x13 },
148- { 0x0137 , 0x33 },
149179 { 0x304e , 0x03 },
150180 { 0x4348 , 0x16 },
151181 { 0x4350 , 0x19 },
@@ -231,12 +261,8 @@ static const struct imx355_reg mode_3268x2448_regs[] = {
231261 { 0x0301 , 0x05 },
232262 { 0x0303 , 0x01 },
233263 { 0x0305 , 0x02 },
234- { 0x0306 , 0x00 },
235- { 0x0307 , 0x78 },
236264 { 0x030b , 0x01 },
237265 { 0x030d , 0x02 },
238- { 0x030e , 0x00 },
239- { 0x030f , 0x4b },
240266 { 0x0310 , 0x00 },
241267 { 0x0700 , 0x00 },
242268 { 0x0701 , 0x10 },
@@ -280,12 +306,8 @@ static const struct imx355_reg mode_3264x2448_regs[] = {
280306 { 0x0301 , 0x05 },
281307 { 0x0303 , 0x01 },
282308 { 0x0305 , 0x02 },
283- { 0x0306 , 0x00 },
284- { 0x0307 , 0x78 },
285309 { 0x030b , 0x01 },
286310 { 0x030d , 0x02 },
287- { 0x030e , 0x00 },
288- { 0x030f , 0x4b },
289311 { 0x0310 , 0x00 },
290312 { 0x0700 , 0x00 },
291313 { 0x0701 , 0x10 },
@@ -329,12 +351,8 @@ static const struct imx355_reg mode_3280x2464_regs[] = {
329351 { 0x0301 , 0x05 },
330352 { 0x0303 , 0x01 },
331353 { 0x0305 , 0x02 },
332- { 0x0306 , 0x00 },
333- { 0x0307 , 0x78 },
334354 { 0x030b , 0x01 },
335355 { 0x030d , 0x02 },
336- { 0x030e , 0x00 },
337- { 0x030f , 0x4b },
338356 { 0x0310 , 0x00 },
339357 { 0x0700 , 0x00 },
340358 { 0x0701 , 0x10 },
@@ -378,12 +396,8 @@ static const struct imx355_reg mode_1940x1096_regs[] = {
378396 { 0x0301 , 0x05 },
379397 { 0x0303 , 0x01 },
380398 { 0x0305 , 0x02 },
381- { 0x0306 , 0x00 },
382- { 0x0307 , 0x78 },
383399 { 0x030b , 0x01 },
384400 { 0x030d , 0x02 },
385- { 0x030e , 0x00 },
386- { 0x030f , 0x4b },
387401 { 0x0310 , 0x00 },
388402 { 0x0700 , 0x00 },
389403 { 0x0701 , 0x10 },
@@ -427,12 +441,8 @@ static const struct imx355_reg mode_1936x1096_regs[] = {
427441 { 0x0301 , 0x05 },
428442 { 0x0303 , 0x01 },
429443 { 0x0305 , 0x02 },
430- { 0x0306 , 0x00 },
431- { 0x0307 , 0x78 },
432444 { 0x030b , 0x01 },
433445 { 0x030d , 0x02 },
434- { 0x030e , 0x00 },
435- { 0x030f , 0x4b },
436446 { 0x0310 , 0x00 },
437447 { 0x0700 , 0x00 },
438448 { 0x0701 , 0x10 },
@@ -476,12 +486,8 @@ static const struct imx355_reg mode_1924x1080_regs[] = {
476486 { 0x0301 , 0x05 },
477487 { 0x0303 , 0x01 },
478488 { 0x0305 , 0x02 },
479- { 0x0306 , 0x00 },
480- { 0x0307 , 0x78 },
481489 { 0x030b , 0x01 },
482490 { 0x030d , 0x02 },
483- { 0x030e , 0x00 },
484- { 0x030f , 0x4b },
485491 { 0x0310 , 0x00 },
486492 { 0x0700 , 0x00 },
487493 { 0x0701 , 0x10 },
@@ -525,12 +531,8 @@ static const struct imx355_reg mode_1920x1080_regs[] = {
525531 { 0x0301 , 0x05 },
526532 { 0x0303 , 0x01 },
527533 { 0x0305 , 0x02 },
528- { 0x0306 , 0x00 },
529- { 0x0307 , 0x78 },
530534 { 0x030b , 0x01 },
531535 { 0x030d , 0x02 },
532- { 0x030e , 0x00 },
533- { 0x030f , 0x4b },
534536 { 0x0310 , 0x00 },
535537 { 0x0700 , 0x00 },
536538 { 0x0701 , 0x10 },
@@ -574,12 +576,8 @@ static const struct imx355_reg mode_1640x1232_regs[] = {
574576 { 0x0301 , 0x05 },
575577 { 0x0303 , 0x01 },
576578 { 0x0305 , 0x02 },
577- { 0x0306 , 0x00 },
578- { 0x0307 , 0x78 },
579579 { 0x030b , 0x01 },
580580 { 0x030d , 0x02 },
581- { 0x030e , 0x00 },
582- { 0x030f , 0x4b },
583581 { 0x0310 , 0x00 },
584582 { 0x0700 , 0x00 },
585583 { 0x0701 , 0x10 },
@@ -623,12 +621,8 @@ static const struct imx355_reg mode_1640x922_regs[] = {
623621 { 0x0301 , 0x05 },
624622 { 0x0303 , 0x01 },
625623 { 0x0305 , 0x02 },
626- { 0x0306 , 0x00 },
627- { 0x0307 , 0x78 },
628624 { 0x030b , 0x01 },
629625 { 0x030d , 0x02 },
630- { 0x030e , 0x00 },
631- { 0x030f , 0x4b },
632626 { 0x0310 , 0x00 },
633627 { 0x0700 , 0x00 },
634628 { 0x0701 , 0x10 },
@@ -672,12 +666,8 @@ static const struct imx355_reg mode_1300x736_regs[] = {
672666 { 0x0301 , 0x05 },
673667 { 0x0303 , 0x01 },
674668 { 0x0305 , 0x02 },
675- { 0x0306 , 0x00 },
676- { 0x0307 , 0x78 },
677669 { 0x030b , 0x01 },
678670 { 0x030d , 0x02 },
679- { 0x030e , 0x00 },
680- { 0x030f , 0x4b },
681671 { 0x0310 , 0x00 },
682672 { 0x0700 , 0x00 },
683673 { 0x0701 , 0x10 },
@@ -721,12 +711,8 @@ static const struct imx355_reg mode_1296x736_regs[] = {
721711 { 0x0301 , 0x05 },
722712 { 0x0303 , 0x01 },
723713 { 0x0305 , 0x02 },
724- { 0x0306 , 0x00 },
725- { 0x0307 , 0x78 },
726714 { 0x030b , 0x01 },
727715 { 0x030d , 0x02 },
728- { 0x030e , 0x00 },
729- { 0x030f , 0x4b },
730716 { 0x0310 , 0x00 },
731717 { 0x0700 , 0x00 },
732718 { 0x0701 , 0x10 },
@@ -770,12 +756,8 @@ static const struct imx355_reg mode_1284x720_regs[] = {
770756 { 0x0301 , 0x05 },
771757 { 0x0303 , 0x01 },
772758 { 0x0305 , 0x02 },
773- { 0x0306 , 0x00 },
774- { 0x0307 , 0x78 },
775759 { 0x030b , 0x01 },
776760 { 0x030d , 0x02 },
777- { 0x030e , 0x00 },
778- { 0x030f , 0x4b },
779761 { 0x0310 , 0x00 },
780762 { 0x0700 , 0x00 },
781763 { 0x0701 , 0x10 },
@@ -819,12 +801,8 @@ static const struct imx355_reg mode_1280x720_regs[] = {
819801 { 0x0301 , 0x05 },
820802 { 0x0303 , 0x01 },
821803 { 0x0305 , 0x02 },
822- { 0x0306 , 0x00 },
823- { 0x0307 , 0x78 },
824804 { 0x030b , 0x01 },
825805 { 0x030d , 0x02 },
826- { 0x030e , 0x00 },
827- { 0x030f , 0x4b },
828806 { 0x0310 , 0x00 },
829807 { 0x0700 , 0x00 },
830808 { 0x0701 , 0x10 },
@@ -868,12 +846,8 @@ static const struct imx355_reg mode_820x616_regs[] = {
868846 { 0x0301 , 0x05 },
869847 { 0x0303 , 0x01 },
870848 { 0x0305 , 0x02 },
871- { 0x0306 , 0x00 },
872- { 0x0307 , 0x78 },
873849 { 0x030b , 0x01 },
874850 { 0x030d , 0x02 },
875- { 0x030e , 0x00 },
876- { 0x030f , 0x4b },
877851 { 0x0310 , 0x00 },
878852 { 0x0700 , 0x02 },
879853 { 0x0701 , 0x78 },
@@ -1422,6 +1396,20 @@ static int imx355_start_streaming(struct imx355 *imx355)
14221396 return ret ;
14231397 }
14241398
1399+ /* Set PLL registers for the external clock frequency */
1400+ ret = imx355_write_reg (imx355 , IMX355_REG_EXTCLK_FREQ , 2 ,
1401+ imx355 -> clk_params -> extclk_freq );
1402+ if (ret )
1403+ return ret ;
1404+ ret = imx355_write_reg (imx355 , IMX355_REG_PLL_VT_MUL , 2 ,
1405+ imx355 -> clk_params -> pll_vt_mpy );
1406+ if (ret )
1407+ return ret ;
1408+ ret = imx355_write_reg (imx355 , IMX355_REG_PLL_OP_MUL , 2 ,
1409+ imx355 -> clk_params -> pll_op_mpy );
1410+ if (ret )
1411+ return ret ;
1412+
14251413 /* set digital gain control to all color mode */
14261414 ret = imx355_write_reg (imx355 , IMX355_REG_DPGA_USE_GLOBAL_GAIN , 1 , 1 );
14271415 if (ret )
@@ -1749,7 +1737,13 @@ static int imx355_probe(struct i2c_client *client)
17491737 "failed to get clock\n" );
17501738
17511739 freq = clk_get_rate (imx355 -> clk );
1752- if (freq != IMX355_EXT_CLK )
1740+ for (unsigned int i = 0 ; i < ARRAY_SIZE (imx355_clk_params ); i ++ ) {
1741+ if (freq == imx355_clk_params [i ].ext_clk ) {
1742+ imx355 -> clk_params = & imx355_clk_params [i ];
1743+ break ;
1744+ }
1745+ }
1746+ if (!imx355 -> clk_params )
17531747 return dev_err_probe (imx355 -> dev , - EINVAL ,
17541748 "external clock %lu is not supported\n" ,
17551749 freq );
0 commit comments