]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: mt9m114: Use aptina-PLL helper to get PLL values
authorHans de Goede <johannes.goede@oss.qualcomm.com>
Tue, 30 Dec 2025 17:02:59 +0000 (18:02 +0100)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Wed, 14 Jan 2026 22:33:04 +0000 (23:33 +0100)
Before this change the driver used hardcoded PLL m, n and p values to
achieve a 48MHz pixclock when used with an external clock with a frequency
of 24 MHz.

Use aptina_pll_calculate() to allow the driver to work with different
external clock frequencies. The m, n, and p values will be unchanged
with a 24 MHz extclk and this has also been tested with a 19.2 MHz
clock where m gets increased from 32 to 40.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
[Sakari Ailus: Fix capitalisation of "MHz".]
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/i2c/Kconfig
drivers/media/i2c/mt9m114.c

index 3121c0d947cdc79dd7a065c0f10378dc87318d9c..371a08a53f7a047f9a2820a0b84e7d9047909c2c 100644 (file)
@@ -305,6 +305,7 @@ config VIDEO_MT9M111
 config VIDEO_MT9M114
        tristate "onsemi MT9M114 sensor support"
        select V4L2_CCI_I2C
+       select VIDEO_APTINA_PLL
        help
          This is a Video4Linux2 sensor-level driver for the onsemi MT9M114
          camera.
index 51ebbe7ae996950a58f8fee30029e0a060feaf3f..2867a0ce80e0c026876a9985ab13f6dc4d01a97d 100644 (file)
@@ -32,6 +32,8 @@
 #include <media/v4l2-mediabus.h>
 #include <media/v4l2-subdev.h>
 
+#include "aptina-pll.h"
+
 /* Sysctl registers */
 #define MT9M114_CHIP_ID                                        CCI_REG16(0x0000)
 #define MT9M114_COMMAND_REGISTER                       CCI_REG16(0x0080)
 #define MT9M114_CAM_SYSCTL_PLL_ENABLE_VALUE                    BIT(0)
 #define MT9M114_CAM_SYSCTL_PLL_DISABLE_VALUE                   0x00
 #define MT9M114_CAM_SYSCTL_PLL_DIVIDER_M_N             CCI_REG16(0xc980)
-#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_VALUE(m, n)             (((n) << 8) | (m))
+#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_VALUE(m, n)             ((((n) - 1) << 8) | (m))
 #define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P               CCI_REG16(0xc982)
-#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(p)              ((p) << 8)
+#define MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(p)              (((p) - 1) << 8)
 #define MT9M114_CAM_PORT_OUTPUT_CONTROL                        CCI_REG16(0xc984)
 #define MT9M114_CAM_PORT_PORT_SELECT_PARALLEL                  (0 << 0)
 #define MT9M114_CAM_PORT_PORT_SELECT_MIPI                      (1 << 0)
  * minimum values that have been seen in register lists are 303 and 38, use
  * them.
  *
- * Set the default to achieve 1280x960 at 30fps.
+ * Set the default to achieve 1280x960 at 30fps with a 48 MHz pixclock.
  */
 #define MT9M114_MIN_HBLANK                             303
 #define MT9M114_MIN_VBLANK                             38
 #define MT9M114_DEF_FRAME_RATE                         30
 #define MT9M114_MAX_FRAME_RATE                         120
 
+#define MT9M114_DEF_PIXCLOCK                           48000000
+
 #define MT9M114_PIXEL_ARRAY_WIDTH                      1296U
 #define MT9M114_PIXEL_ARRAY_HEIGHT                     976U
 
@@ -384,11 +388,7 @@ struct mt9m114 {
        struct v4l2_fwnode_endpoint bus_cfg;
        bool bypass_pll;
 
-       struct {
-               unsigned int m;
-               unsigned int n;
-               unsigned int p;
-       } pll;
+       struct aptina_pll pll;
 
        unsigned int pixrate;
        bool streaming;
@@ -758,7 +758,7 @@ static int mt9m114_initialize(struct mt9m114 *sensor)
                                                               sensor->pll.n),
                          &ret);
                cci_write(sensor->regmap, MT9M114_CAM_SYSCTL_PLL_DIVIDER_P,
-                         MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(sensor->pll.p),
+                         MT9M114_CAM_SYSCTL_PLL_DIVIDER_P_VALUE(sensor->pll.p1),
                          &ret);
        }
 
@@ -2281,14 +2281,39 @@ static int mt9m114_verify_link_frequency(struct mt9m114 *sensor,
        return 0;
 }
 
+/*
+ * Based on the docs the PLL is believed to have the following setup:
+ *
+ *         +-----+     +-----+     +-----+     +-----+     +-----+
+ * Fin --> | / N | --> | x M | --> | x 2 | --> | / P | --> | / 2 | -->
+ *         +-----+     +-----+     +-----+     +-----+     +-----+
+ *                                         fBit       fWord       fSensor
+ * ext_clock    int_clock   out_clock                             pix_clock
+ *
+ * The MT9M114 docs give a max fBit rate of 768 MHz which translates to
+ * an out_clock_max of 384 MHz.
+ */
 static int mt9m114_clk_init(struct mt9m114 *sensor)
 {
+       static const struct aptina_pll_limits limits = {
+               .ext_clock_min = 6000000,
+               .ext_clock_max = 54000000,
+               /* int_clock_* limits are not documented taken from mt9p031.c */
+               .int_clock_min = 2000000,
+               .int_clock_max = 13500000,
+               /* out_clock_min is not documented, taken from mt9p031.c */
+               .out_clock_min = 180000000,
+               .out_clock_max = 384000000,
+               .pix_clock_max = 48000000,
+               .n_min = 1,
+               .n_max = 64,
+               .m_min = 16,
+               .m_max = 192,
+               .p1_min = 8,
+               .p1_max = 8,
+       };
        unsigned int pixrate;
-
-       /* Hardcode the PLL multiplier and dividers to default settings. */
-       sensor->pll.m = 32;
-       sensor->pll.n = 1;
-       sensor->pll.p = 7;
+       int ret;
 
        /*
         * Calculate the pixel rate and link frequency. The CSI-2 bus is clocked
@@ -2308,8 +2333,15 @@ static int mt9m114_clk_init(struct mt9m114 *sensor)
        }
 
        /* Check if the PLL configuration fits the configured link frequency. */
-       pixrate = clk_get_rate(sensor->clk) * sensor->pll.m
-               / ((sensor->pll.n + 1) * (sensor->pll.p + 1));
+       sensor->pll.ext_clock = clk_get_rate(sensor->clk);
+       sensor->pll.pix_clock = MT9M114_DEF_PIXCLOCK;
+
+       ret = aptina_pll_calculate(&sensor->client->dev, &limits, &sensor->pll);
+       if (ret)
+               return ret;
+
+       pixrate = sensor->pll.ext_clock * sensor->pll.m
+               / (sensor->pll.n * sensor->pll.p1);
        if (mt9m114_verify_link_frequency(sensor, pixrate) == 0) {
                sensor->pixrate = pixrate;
                sensor->bypass_pll = false;