From: Dave Stevenson <dave.stevenson@raspberrypi.com>
To: Tianshu Qiu <tian.shu.qiu@intel.com>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Richard Acayan <mailingradian@gmail.com>
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
David Heidelberg <david@ixit.cz>,
Jacopo Mondi <jacopo.mondi@ideasonboard.com>,
devicetree@vger.kernel.org,
Dave Stevenson <dave.stevenson@raspberrypi.com>
Subject: [PATCH v2 01/20] media: i2c: imx355: Add support for 24 MHz external clock
Date: Tue, 07 Jul 2026 18:04:33 +0100 [thread overview]
Message-ID: <20260707-media-imx355-v2-1-1683ec07b897@raspberrypi.com> (raw)
In-Reply-To: <20260707-media-imx355-v2-0-1683ec07b897@raspberrypi.com>
From: David Heidelberg <david@ixit.cz>
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 <david@ixit.cz>
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
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 27a5c212a527..ad9a9464175b 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);
--
2.34.1
next prev parent reply other threads:[~2026-07-07 17:06 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 17:04 [PATCH v2 00/20] media/imx355: General code cleanups, and adding support for 2 lane operation Dave Stevenson
2026-07-07 17:04 ` Dave Stevenson [this message]
2026-07-07 17:04 ` [PATCH v2 02/20] dt-bindings: media: imx355: Allow 2 CSI2 data lane output Dave Stevenson
2026-07-08 7:07 ` Krzysztof Kozlowski
2026-07-07 17:04 ` [PATCH v2 03/20] media: imx355: Remove duplicated registers from the mode tables Dave Stevenson
2026-07-07 17:14 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 04/20] media: imx355: Remove setting FRM_LENGTH_LINES in the mode regs Dave Stevenson
2026-07-07 17:04 ` [PATCH v2 05/20] media: imx355: Programmatically set the crop parameters for each mode Dave Stevenson
2026-07-07 17:18 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 06/20] media: imx355: Set register LINE_LENGTH_PCK programmatically Dave Stevenson
2026-07-07 17:12 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 07/20] media: imx355: Set binning mode registers programmatically Dave Stevenson
2026-07-07 17:15 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 08/20] media: imx355: Remove link_freq_index from each mode as ununsed Dave Stevenson
2026-07-07 17:04 ` [PATCH v2 09/20] media: imx355: pixel_rate never changes, so don't recompute Dave Stevenson
2026-07-07 17:15 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 10/20] media: imx355: Remove redundant fll_min, and implement fixed offset Dave Stevenson
2026-07-07 17:18 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 11/20] media: imx355: Add support for get_selection Dave Stevenson
2026-07-07 17:18 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 12/20] media: imx355: Use pm_runtime autosuspend_delay Dave Stevenson
2026-07-07 17:21 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 13/20] media: imx355: Convert to new CCI register access helpers Dave Stevenson
2026-07-07 17:21 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 14/20] media: imx355: Set the colorspace in the format Dave Stevenson
2026-07-07 17:16 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 15/20] media: imx355: Define the exposure offset, and use that define Dave Stevenson
2026-07-07 17:04 ` [PATCH v2 16/20] media: imx355: Use NULL ctrl_ops for HBLANK as it is a read-only control Dave Stevenson
2026-07-07 17:04 ` [PATCH v2 17/20] media: imx355: Compute link frequency from PLL setup Dave Stevenson
2026-07-07 17:04 ` [PATCH v2 18/20] media: imx355: Support 2 lane readout Dave Stevenson
2026-07-07 17:04 ` [PATCH v2 19/20] media: imx355: Switch to using the subdev state Dave Stevenson
2026-07-07 19:34 ` sashiko-bot
2026-07-07 17:04 ` [PATCH v2 20/20] media: imx355: Remove storing cur_mode in the state Dave Stevenson
2026-07-07 17:37 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707-media-imx355-v2-1-1683ec07b897@raspberrypi.com \
--to=dave.stevenson@raspberrypi.com \
--cc=conor+dt@kernel.org \
--cc=david@ixit.cz \
--cc=devicetree@vger.kernel.org \
--cc=jacopo.mondi@ideasonboard.com \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mailingradian@gmail.com \
--cc=mchehab@kernel.org \
--cc=robh@kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=tian.shu.qiu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox