From 1df58b9ddaac468154083af6e1d7ddaf8769e964 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 30 Dec 2025 18:02:59 +0100 Subject: [PATCH] media: mt9m114: Use aptina-PLL helper to get PLL values 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 Reviewed-by: Laurent Pinchart Signed-off-by: Hans de Goede [Sakari Ailus: Fix capitalisation of "MHz".] Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/Kconfig | 1 + drivers/media/i2c/mt9m114.c | 64 +++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 3121c0d947cdc..371a08a53f7a0 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -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. diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c index 51ebbe7ae9969..2867a0ce80e0c 100644 --- a/drivers/media/i2c/mt9m114.c +++ b/drivers/media/i2c/mt9m114.c @@ -32,6 +32,8 @@ #include #include +#include "aptina-pll.h" + /* Sysctl registers */ #define MT9M114_CHIP_ID CCI_REG16(0x0000) #define MT9M114_COMMAND_REGISTER CCI_REG16(0x0080) @@ -267,9 +269,9 @@ #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) @@ -330,7 +332,7 @@ * 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 @@ -340,6 +342,8 @@ #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; -- 2.47.3