Skip to content

Commit 2250e3d

Browse files
okias6by9
authored andcommitted
media: i2c: imx355: Add support for 24 MHz external clock
The IMX355 sensor supports multiple external clock frequencies, including 19.2 MHz and 24 MHz. The driver currently supports only fixed 19.2 MHz input clock. Refactor the clock handling to make the PLL configuration dependent on the external clock frequency and add support for 24 MHz. Introduce a table of clock parameter sets and program the corresponding EXTCLK frequency and PLL multipliers to maintain consistent internal VCO frequencies across supported inputs. The PLL settings are adjusted so that: - VT VCO remains at 1152 MHz - OP VCO remains at 720 MHz This preserves existing timing characteristics while allowing systems using a 24 MHz clock to operate correctly. No functional change for existing 19.2 MHz users. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: David Heidelberg <david@ixit.cz>
1 parent 32d3fc5 commit 2250e3d

1 file changed

Lines changed: 54 additions & 60 deletions

File tree

drivers/media/i2c/imx355.c

Lines changed: 54 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
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
@@ -63,7 +68,6 @@
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+
103134
struct 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

146178
static 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

Comments
 (0)