On Wed Jul 15 12:43:15 2026 +0100, David Heidelberg wrote:
> 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 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 <[email protected]>
> Signed-off-by: Dave Stevenson <[email protected]>
> Signed-off-by: Sakari Ailus <[email protected]>

Patch committed.

Thanks,
Sakari Ailus

 drivers/media/i2c/imx355.c | 77 +++++++++++++++++++++++++++-------------------
 1 file changed, 45 insertions(+), 32 deletions(-)

---

diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c
index ac59908f57aa..a6ee7532018f 100644
--- a/drivers/media/i2c/imx355.c
+++ b/drivers/media/i2c/imx355.c
@@ -25,6 +25,10 @@
 #define IMX355_REG_CHIP_ID             0x0016
 #define IMX355_CHIP_ID                 0x0355
 
+/* PLL registers that depend on the external clock frequency */
+#define IMX355_REG_EXTCLK_FREQ         0x0136
+#define IMX355_REG_PLL_OP_MUL          0x030e
+
 /* V_TIMING internal */
 #define IMX355_REG_FLL                 0x0340
 #define IMX355_FLL_MAX                 0xffff
@@ -63,7 +67,6 @@
 
 /* default link frequency and external clock */
 #define IMX355_LINK_FREQ_DEFAULT       360000000LL
-#define IMX355_EXT_CLK                 19200000
 #define IMX355_LINK_FREQ_INDEX         0
 
 /* number of data lanes */
@@ -100,6 +103,29 @@ struct imx355_mode {
        struct imx355_reg_list reg_list;
 };
 
+struct imx355_clk_params {
+       u32 ext_clk;
+       u16 extclk_freq; /* External clock (MHz) in 8.8 fixed point) */
+       u16 pll_op_mpy; /* OP system PLL multiplier */
+};
+
+/*
+ * The clock tree is in single PLL mode, so PREDIV_VT and MPY_IVT do nothing.
+ * All modes use the same PLL setup for OP, with IOPCK being 720MHz.
+ */
+static const struct imx355_clk_params imx355_clk_params[] = {
+       {
+               .ext_clk = 19200000,
+               .extclk_freq = 0x1333,  /* 19.2 MHz */
+               .pll_op_mpy = 75,       /* 19.2 / 2 * 75  = 720 MHz */
+       },
+       {
+               .ext_clk = 24000000,
+               .extclk_freq = 0x1800,  /* 24.0 MHz */
+               .pll_op_mpy = 60,       /* 24.0 / 2 * 60  = 720 MHz */
+       },
+};
+
 struct imx355_hwcfg {
        unsigned long link_freq_bitmap;
 };
@@ -125,6 +151,7 @@ struct imx355 {
        const struct imx355_mode *cur_mode;
 
        struct imx355_hwcfg *hwcfg;
+       const struct imx355_clk_params *clk_params;
 
        /*
         * Mutex for serialized access:
@@ -144,8 +171,6 @@ static const struct regulator_bulk_data imx355_supplies[] = 
{
 };
 
 static const struct imx355_reg imx355_global_regs[] = {
-       { 0x0136, 0x13 },
-       { 0x0137, 0x33 },
        { 0x304e, 0x03 },
        { 0x4348, 0x16 },
        { 0x4350, 0x19 },
@@ -235,8 +260,6 @@ static const struct imx355_reg mode_3268x2448_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -284,8 +307,6 @@ static const struct imx355_reg mode_3264x2448_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -333,8 +354,6 @@ static const struct imx355_reg mode_3280x2464_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -382,8 +401,6 @@ static const struct imx355_reg mode_1940x1096_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -431,8 +448,6 @@ static const struct imx355_reg mode_1936x1096_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -480,8 +495,6 @@ static const struct imx355_reg mode_1924x1080_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -529,8 +542,6 @@ static const struct imx355_reg mode_1920x1080_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -578,8 +589,6 @@ static const struct imx355_reg mode_1640x1232_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -627,8 +636,6 @@ static const struct imx355_reg mode_1640x922_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -676,8 +683,6 @@ static const struct imx355_reg mode_1300x736_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -725,8 +730,6 @@ static const struct imx355_reg mode_1296x736_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -774,8 +777,6 @@ static const struct imx355_reg mode_1284x720_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -823,8 +824,6 @@ static const struct imx355_reg mode_1280x720_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x00 },
        { 0x0701, 0x10 },
@@ -872,8 +871,6 @@ static const struct imx355_reg mode_820x616_regs[] = {
        { 0x0307, 0x78 },
        { 0x030b, 0x01 },
        { 0x030d, 0x02 },
-       { 0x030e, 0x00 },
-       { 0x030f, 0x4b },
        { 0x0310, 0x00 },
        { 0x0700, 0x02 },
        { 0x0701, 0x78 },
@@ -1422,6 +1419,16 @@ static int imx355_start_streaming(struct imx355 *imx355)
                return ret;
        }
 
+       /* Set PLL registers for the external clock frequency */
+       ret = imx355_write_reg(imx355, IMX355_REG_EXTCLK_FREQ, 2,
+                              imx355->clk_params->extclk_freq);
+       if (ret)
+               return ret;
+       ret = imx355_write_reg(imx355, IMX355_REG_PLL_OP_MUL, 2,
+                              imx355->clk_params->pll_op_mpy);
+       if (ret)
+               return ret;
+
        /* set digital gain control to all color mode */
        ret = imx355_write_reg(imx355, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);
        if (ret)
@@ -1749,7 +1756,13 @@ static int imx355_probe(struct i2c_client *client)
                                     "failed to get clock\n");
 
        freq = clk_get_rate(imx355->clk);
-       if (freq != IMX355_EXT_CLK)
+       for (unsigned int i = 0; i < ARRAY_SIZE(imx355_clk_params); i++) {
+               if (freq == imx355_clk_params[i].ext_clk) {
+                       imx355->clk_params = &imx355_clk_params[i];
+                       break;
+               }
+       }
+       if (!imx355->clk_params)
                return dev_err_probe(imx355->dev, -EINVAL,
                                     "external clock %lu is not supported\n",
                                     freq);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to