public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] media: synopsys: Add imx93 support
@ 2026-02-10 17:11 Frank Li
  2026-02-10 17:11 ` [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive() Frank Li
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

This 3rd time try to support DW CSI2RX support for imx93.

1st: Create new dw csi2 driver
https://lore.kernel.org/all/20250701-95_cam-v1-5-c5172bab387b@nxp.com/

2nd: Based on legacy imx6's DW CSI2 constroller.
https://lore.kernel.org/imx/20250821-95_cam-v3-0-c9286fbb34b9@nxp.com/

Now rockchip create a common DW CSI2RX driver at
drivers/media/platform/synopsys/dw-mipi-csi2rx.c

This time base on rockchip's implement.

i.MX93's version is newer than rockchip one. i.MX6's is more similar with
rockchips.

But i.MX6 is too old. So start at i.MX93 firstly even it has bigger
difference.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Frank Li (6):
      media: synopsys: use devm_reset_control_get_optional_exclusive()
      media: synopsys: only check errors from devm_clk_bulk_get_all()
      media: synopsys: implement .get_frame_desc() callback
      media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets
      media: dt-bindings: add NXP i.MX93 compatible string
      media: synopsys: add i.MX93 support

 .../bindings/media/rockchip,rk3568-mipi-csi2.yaml  |  47 +++-
 drivers/media/platform/synopsys/dw-mipi-csi2rx.c   | 280 ++++++++++++++++++---
 2 files changed, 293 insertions(+), 34 deletions(-)
---
base-commit: ada3fa02f7a95623b724dfe300fce6f49cc2d75a
change-id: 20260128-imx93-dw-csi2-b472ddcb176a

Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive()
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
@ 2026-02-10 17:11 ` Frank Li
  2026-02-13  9:25   ` Michael Riesch
  2026-02-10 17:11 ` [PATCH 2/6] media: synopsys: only check errors from devm_clk_bulk_get_all() Frank Li
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

The DW MIPI CSI-2 RX is used on different SoCs, not all of which provide a
reset controller. Switch to devm_reset_control_get_optional_exclusive()
to support such platforms.

Reset presence and numbering are validated by the DT binding.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 170346ae1a599e43bba9d19476ee4d65124303bd..0cc892f4a1b3c6ce575a5d4fca7acf7057f7b7f7 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -639,7 +639,7 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(csi2->phy),
 				     "failed to get MIPI CSI-2 PHY\n");
 
-	csi2->reset = devm_reset_control_get_exclusive(dev, NULL);
+	csi2->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
 	if (IS_ERR(csi2->reset))
 		return dev_err_probe(dev, PTR_ERR(csi2->reset),
 				     "failed to get reset\n");

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 2/6] media: synopsys: only check errors from devm_clk_bulk_get_all()
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
  2026-02-10 17:11 ` [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive() Frank Li
@ 2026-02-10 17:11 ` Frank Li
  2026-02-13  9:35   ` Michael Riesch
  2026-02-10 17:11 ` [PATCH 3/6] media: synopsys: implement .get_frame_desc() callback Frank Li
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

devm_clk_bulk_get_all() returns all clocks described in the DT, which are
already validated by the binding. Do not need enforce an expected clock
count.

Only check for error returns (< 0) to support more SoCs.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 0cc892f4a1b3c6ce575a5d4fca7acf7057f7b7f7..61cd7f491b3d5b8a37707b23ca03ce709b40a79f 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -630,7 +630,7 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
 		return PTR_ERR(csi2->base_addr);
 
 	ret = devm_clk_bulk_get_all(dev, &csi2->clks);
-	if (ret != DW_MIPI_CSI2RX_CLKS_MAX)
+	if (ret < 0)
 		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
 	csi2->clks_num = ret;
 

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 3/6] media: synopsys: implement .get_frame_desc() callback
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
  2026-02-10 17:11 ` [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive() Frank Li
  2026-02-10 17:11 ` [PATCH 2/6] media: synopsys: only check errors from devm_clk_bulk_get_all() Frank Li
@ 2026-02-10 17:11 ` Frank Li
  2026-03-24  8:02   ` Sakari Ailus
  2026-02-10 17:11 ` [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets Frank Li
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

Implement the .get_frame_desc() callback to fetch information from the
remote endpoint.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 25 ++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 61cd7f491b3d5b8a37707b23ca03ce709b40a79f..4ad4e3b23448affeeaa932a706653818ba4019ba 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -70,6 +70,8 @@ struct dw_mipi_csi2rx_device {
 	struct v4l2_async_notifier notifier;
 	struct v4l2_subdev sd;
 
+	struct v4l2_subdev *remote_source;
+
 	enum v4l2_mbus_type bus_type;
 	u32 lanes_num;
 };
@@ -431,10 +433,31 @@ static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
 	return ret;
 }
 
+static int
+dw_mipi_csi2rx_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+			      struct v4l2_mbus_frame_desc *fd)
+{
+	struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
+	struct media_pad *remote_pad;
+
+	if (!csi2->remote_source)
+		return -ENODEV;
+
+	remote_pad = media_pad_remote_pad_unique(&csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
+	if (IS_ERR(remote_pad)) {
+		dev_err(csi2->dev, "can't get source pad of %s (%pe)\n",
+			csi2->remote_source->name, remote_pad);
+		return PTR_ERR(remote_pad);
+	}
+	return v4l2_subdev_call(csi2->remote_source, pad, get_frame_desc,
+				remote_pad->index, fd);
+}
+
 static const struct v4l2_subdev_pad_ops dw_mipi_csi2rx_pad_ops = {
 	.enum_mbus_code = dw_mipi_csi2rx_enum_mbus_code,
 	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = dw_mipi_csi2rx_set_fmt,
+	.get_frame_desc = dw_mipi_csi2rx_get_frame_desc,
 	.set_routing = dw_mipi_csi2rx_set_routing,
 	.enable_streams = dw_mipi_csi2rx_enable_streams,
 	.disable_streams = dw_mipi_csi2rx_disable_streams,
@@ -487,6 +510,8 @@ static int dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier *notifier,
 		return ret;
 	}
 
+	csi2->remote_source = sd;
+
 	return 0;
 }
 

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
                   ` (2 preceding siblings ...)
  2026-02-10 17:11 ` [PATCH 3/6] media: synopsys: implement .get_frame_desc() callback Frank Li
@ 2026-02-10 17:11 ` Frank Li
  2026-02-13 10:02   ` Michael Riesch
  2026-03-24  8:16   ` Sakari Ailus
  2026-02-10 17:11 ` [PATCH 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

Use struct dw_mipi_csi2rx_regs to describe register offsets and support
new IP versions with differing register layouts.

Add rk3568_regs, matching the previous macro definitions, and pass it as
driver data retrieved during probe.

No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 96 +++++++++++++++++-------
 1 file changed, 69 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 4ad4e3b23448affeeaa932a706653818ba4019ba..6a2966c9e3a2eac661fa1f8610c9f021d6e26cf8 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -24,14 +24,39 @@
 #include <media/v4l2-mc.h>
 #include <media/v4l2-subdev.h>
 
-#define DW_MIPI_CSI2RX_N_LANES		0x04
-#define DW_MIPI_CSI2RX_RESETN		0x10
-#define DW_MIPI_CSI2RX_PHY_STATE	0x14
-#define DW_MIPI_CSI2RX_ERR1		0x20
-#define DW_MIPI_CSI2RX_ERR2		0x24
-#define DW_MIPI_CSI2RX_MSK1		0x28
-#define DW_MIPI_CSI2RX_MSK2		0x2c
-#define DW_MIPI_CSI2RX_CONTROL		0x40
+struct dw_mipi_csi2rx_regs {
+	u32 n_lanes;
+	u32 resetn;
+	u32 phy_state;
+	u32 err1;
+	u32 err2;
+	u32 msk1;
+	u32 msk2;
+	u32 control;
+};
+
+struct dw_mipi_csi2rx_drvdata {
+	const struct dw_mipi_csi2rx_regs *regs;
+};
+
+/* Help check wrong access unexisted register at difference IP version */
+#define DW_REG_EXIST	BIT(31)
+#define DW_REG(x)	(DW_REG_EXIST | (x))
+
+static const struct dw_mipi_csi2rx_regs rk3568_regs = {
+	.n_lanes = DW_REG(0x4),
+	.resetn = DW_REG(0x10),
+	.phy_state = DW_REG(0x14),
+	.err1 = DW_REG(0x20),
+	.err2 = DW_REG(0x24),
+	.msk1 = DW_REG(0x28),
+	.msk2 = DW_REG(0x2c),
+	.control = DW_REG(0x40),
+};
+
+static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {
+	.regs = &rk3568_regs,
+};
 
 #define SW_CPHY_EN(x)		((x) << 0)
 #define SW_DSI_EN(x)		((x) << 4)
@@ -74,8 +99,35 @@ struct dw_mipi_csi2rx_device {
 
 	enum v4l2_mbus_type bus_type;
 	u32 lanes_num;
+
+	const struct dw_mipi_csi2rx_drvdata *drvdata;
 };
 
+static int
+dw_mipi_csi2rx_reg_err(struct dw_mipi_csi2rx_device *csi2, const char *name)
+{
+	dev_err_once(csi2->dev, "access to non-existent register: %s\n", name);
+	return 0;
+}
+
+#define __dw_reg_exist(offset) ((offset) & DW_REG_EXIST)
+
+#define dw_reg_exist(csi2, __name) __dw_reg_exist((csi2)->drvdata->regs->__name)
+
+#define dw_mipi_csi2rx_write(csi2, __name, value)		\
+({	auto __csi2 = csi2;					\
+	u32 offset = __csi2->drvdata->regs->__name;		\
+	__dw_reg_exist(offset) ?					\
+		writel(value, __csi2->base_addr + (offset & ~DW_REG_EXIST)) : \
+		dw_mipi_csi2rx_reg_err(__csi2, #__name); })
+
+#define dw_mipi_csi2rx_read(csi2, __name)			\
+({	auto __csi2 = csi2;					\
+	u32 offset = __csi2->drvdata->regs->__name;		\
+	__dw_reg_exist(offset) ?					\
+		readl(__csi2->base_addr + (offset & ~DW_REG_EXIST)) : \
+		dw_mipi_csi2rx_reg_err(__csi2, #__name); })
+
 static const struct v4l2_mbus_framefmt default_format = {
 	.width = 3840,
 	.height = 2160,
@@ -188,18 +240,6 @@ static inline struct dw_mipi_csi2rx_device *to_csi2(struct v4l2_subdev *sd)
 	return container_of(sd, struct dw_mipi_csi2rx_device, sd);
 }
 
-static inline void dw_mipi_csi2rx_write(struct dw_mipi_csi2rx_device *csi2,
-					unsigned int addr, u32 val)
-{
-	writel(val, csi2->base_addr + addr);
-}
-
-static inline u32 dw_mipi_csi2rx_read(struct dw_mipi_csi2rx_device *csi2,
-				      unsigned int addr)
-{
-	return readl(csi2->base_addr + addr);
-}
-
 static const struct dw_mipi_csi2rx_format *
 dw_mipi_csi2rx_find_format(struct dw_mipi_csi2rx_device *csi2, u32 mbus_code)
 {
@@ -265,9 +305,9 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
 	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
 		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
 
-	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_N_LANES, lanes - 1);
-	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_CONTROL, control);
-	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 1);
+	dw_mipi_csi2rx_write(csi2, n_lanes, lanes - 1);
+	dw_mipi_csi2rx_write(csi2, control, control);
+	dw_mipi_csi2rx_write(csi2, resetn, 1);
 
 	return phy_power_on(csi2->phy);
 }
@@ -276,9 +316,9 @@ static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
 {
 	phy_power_off(csi2->phy);
 
-	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 0);
-	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
-	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK2, ~0);
+	dw_mipi_csi2rx_write(csi2, resetn, 0);
+	dw_mipi_csi2rx_write(csi2, msk1, ~0);
+	dw_mipi_csi2rx_write(csi2, msk2, ~0);
 }
 
 static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
@@ -632,7 +672,7 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
 
 static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
 	{
-		.compatible = "rockchip,rk3568-mipi-csi2",
+		.compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata,
 	},
 	{}
 };
@@ -654,6 +694,8 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
 	if (IS_ERR(csi2->base_addr))
 		return PTR_ERR(csi2->base_addr);
 
+	csi2->drvdata = device_get_match_data(dev);
+
 	ret = devm_clk_bulk_get_all(dev, &csi2->clks);
 	if (ret < 0)
 		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 5/6] media: dt-bindings: add NXP i.MX93 compatible string
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
                   ` (3 preceding siblings ...)
  2026-02-10 17:11 ` [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets Frank Li
@ 2026-02-10 17:11 ` Frank Li
  2026-02-11  6:47   ` Krzysztof Kozlowski
  2026-02-10 17:11 ` [PATCH 6/6] media: synopsys: add i.MX93 support Frank Li
  2026-03-23 19:10 ` [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
  6 siblings, 1 reply; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

The i.MX93 uses the DW CSI-2 RX controller, which is similar to the
Rockchip RK3568 implementation.

The i.MX93 variant provides one IRQ, two clocks, and no resets. Add the
"fsl,imx93-mipi-csi2" compatible string and keep the same constraints for
rk3568.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 .../bindings/media/rockchip,rk3568-mipi-csi2.yaml  | 47 +++++++++++++++++++++-
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml
index 2c2bd87582eb8bfdd13720edd62a5f00dda958ba..4ac4a3b6f406408b9524c795e6cdeb117d3353da 100644
--- a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi2.yaml
@@ -17,6 +17,7 @@ description:
 properties:
   compatible:
     enum:
+      - fsl,imx93-mipi-csi2
       - rockchip,rk3568-mipi-csi2
 
   reg:
@@ -26,14 +27,23 @@ properties:
     items:
       - description: Interrupt that signals changes in CSI2HOST_ERR1.
       - description: Interrupt that signals changes in CSI2HOST_ERR2.
+    minItems: 1
 
   interrupt-names:
     items:
       - const: err1
       - const: err2
+    minItems: 1
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: per
+      - const: pixel
+    minItems: 1
 
   phys:
     maxItems: 1
@@ -88,10 +98,43 @@ required:
   - phys
   - ports
   - power-domains
-  - resets
 
 additionalProperties: false
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: rockchip,rk3568-mipi-csi2
+    then:
+      properties:
+        interrupts:
+          minItems: 2
+        interrupt-names:
+          minItems: 2
+        clocks:
+          maxItems: 1
+        clock-names:
+          maxItems: 1
+      required:
+        - resets
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,imx93-mipi-csi2
+    then:
+      properties:
+        interrupts:
+          maxItems: 1
+        interrupt-names: false
+        clocks:
+          minItems: 2
+        clock-names:
+          minItems: 2
+
 examples:
   - |
     #include <dt-bindings/clock/rk3568-cru.h>

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 6/6] media: synopsys: add i.MX93 support
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
                   ` (4 preceding siblings ...)
  2026-02-10 17:11 ` [PATCH 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
@ 2026-02-10 17:11 ` Frank Li
  2026-02-13 10:22   ` Michael Riesch
  2026-03-23 19:10 ` [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
  6 siblings, 1 reply; 19+ messages in thread
From: Frank Li @ 2026-02-10 17:11 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx, Frank Li

The i.MX93 uses a newer version of the DW CSI-2 controller with a changed
register layout and an added IPI block.

The reset flow also differs, so add the .assert_reset(), .deassert_reset(),
and .ipi_enable() callbacks to support it.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 163 ++++++++++++++++++++++-
 1 file changed, 156 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
index 6a2966c9e3a2eac661fa1f8610c9f021d6e26cf8..5dc55b59d6aeed4b6cb207c8e2ebe0fb3c462644 100644
--- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
+++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
@@ -33,10 +33,24 @@ struct dw_mipi_csi2rx_regs {
 	u32 msk1;
 	u32 msk2;
 	u32 control;
+	u32 phy_tst_ctrl0;
+	u32 phy_tst_ctrl1;
+	u32 dphy_rstz;
+	u32 phy_shutdownz;
+	u32 ipi_softrstn;
+	u32 ipi_datatype;
+	u32 ipi_vcid;
+	u32 ipi_mode;
+	u32 ipi_mem_flush;
 };
 
+struct dw_mipi_csi2rx_device;
+
 struct dw_mipi_csi2rx_drvdata {
 	const struct dw_mipi_csi2rx_regs *regs;
+	void (*dphy_assert_reset)(struct dw_mipi_csi2rx_device *csi2);
+	void (*dphy_deassert_reset)(struct dw_mipi_csi2rx_device *csi2);
+	void (*ipi_enable)(struct dw_mipi_csi2rx_device *csi2);
 };
 
 /* Help check wrong access unexisted register at difference IP version */
@@ -54,6 +68,21 @@ static const struct dw_mipi_csi2rx_regs rk3568_regs = {
 	.control = DW_REG(0x40),
 };
 
+static const struct dw_mipi_csi2rx_regs imx93_regs = {
+	.n_lanes = DW_REG(0x4),
+	.resetn = DW_REG(0x8),
+	.phy_shutdownz = DW_REG(0x40),
+	.dphy_rstz = DW_REG(0x44),
+	.phy_state = DW_REG(0x48),
+	.phy_tst_ctrl0 = DW_REG(0x50),
+	.phy_tst_ctrl1 = DW_REG(0x54),
+	.ipi_mode = DW_REG(0x80),
+	.ipi_vcid = DW_REG(0x84),
+	.ipi_datatype = DW_REG(0x88),
+	.ipi_mem_flush = DW_REG(0x8c),
+	.ipi_softrstn = DW_REG(0xa0),
+};
+
 static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {
 	.regs = &rk3568_regs,
 };
@@ -302,14 +331,30 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
 		return -EINVAL;
 	}
 
+	dw_mipi_csi2rx_write(csi2, resetn, 0);
+
+	if (csi2->drvdata->dphy_assert_reset)
+		csi2->drvdata->dphy_assert_reset(csi2);
+
 	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
 		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
 
 	dw_mipi_csi2rx_write(csi2, n_lanes, lanes - 1);
-	dw_mipi_csi2rx_write(csi2, control, control);
+
+	if (dw_reg_exist(csi2, control))
+		dw_mipi_csi2rx_write(csi2, control, control);
+
+	ret = phy_power_on(csi2->phy);
+
+	if (csi2->drvdata->dphy_deassert_reset)
+		csi2->drvdata->dphy_deassert_reset(csi2);
+
 	dw_mipi_csi2rx_write(csi2, resetn, 1);
 
-	return phy_power_on(csi2->phy);
+	if (csi2->drvdata->ipi_enable)
+		csi2->drvdata->ipi_enable(csi2);
+
+	return ret;
 }
 
 static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
@@ -317,8 +362,12 @@ static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
 	phy_power_off(csi2->phy);
 
 	dw_mipi_csi2rx_write(csi2, resetn, 0);
-	dw_mipi_csi2rx_write(csi2, msk1, ~0);
-	dw_mipi_csi2rx_write(csi2, msk2, ~0);
+
+	if (dw_reg_exist(csi2, msk1))
+		dw_mipi_csi2rx_write(csi2, msk1, ~0);
+
+	if (dw_reg_exist(csi2, msk2))
+		dw_mipi_csi2rx_write(csi2, msk2, ~0);
 }
 
 static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
@@ -670,10 +719,110 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
 	v4l2_async_nf_cleanup(&csi2->notifier);
 }
 
+#define DPHY_TEST_CTRL0_TEST_CLR	BIT(0)
+
+static void imx93_csi2rx_dphy_assert_reset(struct dw_mipi_csi2rx_device *csi2)
+{
+	u32 val;
+
+	/* Release synopsis DPHY test codes from reset */
+	dw_mipi_csi2rx_write(csi2, dphy_rstz, 0);
+	dw_mipi_csi2rx_write(csi2, phy_shutdownz, 0);
+
+	val = dw_mipi_csi2rx_read(csi2, phy_tst_ctrl0);
+	val &= ~DPHY_TEST_CTRL0_TEST_CLR;
+	dw_mipi_csi2rx_write(csi2, phy_tst_ctrl0, val);
+
+	/*
+	 * ndelay is not necessary have MMIO operation, need dummy read to make
+	 * sure above write reach target.
+	 */
+	val = dw_mipi_csi2rx_read(csi2, phy_tst_ctrl0);
+	/* Wait for at least 15ns */
+	ndelay(15);
+	val |= DPHY_TEST_CTRL0_TEST_CLR;
+	dw_mipi_csi2rx_write(csi2, phy_tst_ctrl0, val);
+}
+
+#define CSI2RX_DPHY_STOPSTATE_CLK_LANE BIT(16)
+
+static void imx93_csi2rx_dphy_deassert_reset(struct dw_mipi_csi2rx_device *csi2)
+{
+	/* Release PHY from reset */
+	dw_mipi_csi2rx_write(csi2, phy_shutdownz, 0x1);
+	/*
+	 * ndelay is not necessary have MMIO operation, need dummy read to make
+	 * sure above write reach target.
+	 */
+	dw_mipi_csi2rx_read(csi2, phy_shutdownz);
+	ndelay(5);
+	dw_mipi_csi2rx_write(csi2, dphy_rstz, 0x1);
+
+	dw_mipi_csi2rx_read(csi2, dphy_rstz);
+	ndelay(5);
+}
+
+#define IPI_VCID_VC(x)			FIELD_PREP(GENMASK(1, 0), (x))
+#define IPI_VCID_VC_0_1(x)		FIELD_PREP(GENMASK(3, 2), (x))
+#define IPI_VCID_VC_2			BIT(4)
+
+#define IPI_DATA_TYPE_DT(x)		FIELD_PREP(GENMASK(5, 0), (x))
+#define IPI_DATA_TYPE_EMB_DATA_EN	BIT(8)
+
+#define IPI_MODE_CONTROLLER		BIT(1)
+#define IPI_MODE_COLOR_MODE16		BIT(8)
+#define IPI_MODE_CUT_THROUGH		BIT(16)
+#define IPI_MODE_ENABLE			BIT(24)
+
+#define IPI_MEM_FLUSH_AUTO		BIT(8)
+
+static void imx93_csi2rx_dphy_ipi_enable(struct dw_mipi_csi2rx_device *csi2)
+{
+	int dt = csi2->formats->csi_dt;
+	u32 val;
+
+	/* Do IPI soft reset */
+	dw_mipi_csi2rx_write(csi2, ipi_softrstn, 0x0);
+	dw_mipi_csi2rx_write(csi2, ipi_softrstn, 0x1);
+
+	/* Select virtual channel and data type to be processed by IPI */
+	val = IPI_DATA_TYPE_DT(dt);
+	dw_mipi_csi2rx_write(csi2, ipi_datatype, val);
+
+	/* Set virtual channel 0 as default */
+	val  = IPI_VCID_VC(0);
+	dw_mipi_csi2rx_write(csi2, ipi_vcid, val);
+
+	/*
+	 * Select IPI camera timing mode and allow the pixel stream
+	 * to be non-continuous when pixel interface FIFO is empty
+	 */
+	val = dw_mipi_csi2rx_read(csi2, ipi_mode);
+	val &= ~IPI_MODE_CONTROLLER;
+	val &= ~IPI_MODE_COLOR_MODE16;
+	val |= IPI_MODE_CUT_THROUGH;
+	dw_mipi_csi2rx_write(csi2, ipi_mode, val);
+
+	/* Memory is automatically flushed at each Frame Start */
+	val = IPI_MEM_FLUSH_AUTO;
+	dw_mipi_csi2rx_write(csi2, ipi_mem_flush, val);
+
+	/* Enable IPI */
+	val = dw_mipi_csi2rx_read(csi2, ipi_mode);
+	val |= IPI_MODE_ENABLE;
+	dw_mipi_csi2rx_write(csi2, ipi_mode, val);
+}
+
+static const struct dw_mipi_csi2rx_drvdata imx93_drvdata = {
+	.regs = &imx93_regs,
+	.dphy_assert_reset = imx93_csi2rx_dphy_assert_reset,
+	.dphy_deassert_reset = imx93_csi2rx_dphy_deassert_reset,
+	.ipi_enable = imx93_csi2rx_dphy_ipi_enable,
+};
+
 static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
-	{
-		.compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata,
-	},
+	{ .compatible = "fsl,imx93-mipi-csi2", .data = &imx93_drvdata, },
+	{ .compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata, },
 	{}
 };
 MODULE_DEVICE_TABLE(of, dw_mipi_csi2rx_of_match);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/6] media: dt-bindings: add NXP i.MX93 compatible string
  2026-02-10 17:11 ` [PATCH 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
@ 2026-02-11  6:47   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 19+ messages in thread
From: Krzysztof Kozlowski @ 2026-02-11  6:47 UTC (permalink / raw)
  To: Frank Li
  Cc: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, linux-media,
	linux-kernel, devicetree, linux-arm-kernel, linux-rockchip,
	Guoniu Zhou, Laurent Pinchart, imx

On Tue, Feb 10, 2026 at 12:11:12PM -0500, Frank Li wrote:
> The i.MX93 uses the DW CSI-2 RX controller, which is similar to the
> Rockchip RK3568 implementation.
> 
> The i.MX93 variant provides one IRQ, two clocks, and no resets. Add the
> "fsl,imx93-mipi-csi2" compatible string and keep the same constraints for
> rk3568.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  .../bindings/media/rockchip,rk3568-mipi-csi2.yaml  | 47 +++++++++++++++++++++-
>  1 file changed, 45 insertions(+), 2 deletions(-)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive()
  2026-02-10 17:11 ` [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive() Frank Li
@ 2026-02-13  9:25   ` Michael Riesch
  0 siblings, 0 replies; 19+ messages in thread
From: Michael Riesch @ 2026-02-13  9:25 UTC (permalink / raw)
  To: Frank Li, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx

Hi Frank,

Thanks for the patch series.

Could you use "media: synopsys: csi2rx: " as prefix for your commit
messages?

On 2/10/26 18:11, Frank Li wrote:
> The DW MIPI CSI-2 RX is used on different SoCs, not all of which provide a
> reset controller. Switch to devm_reset_control_get_optional_exclusive()
> to support such platforms.
> 
> Reset presence and numbering are validated by the DT binding.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>

With that change,

Reviewed-by: Michael Riesch <michael.riesch@collabora.com>

Best regards,
Michael

> ---
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index 170346ae1a599e43bba9d19476ee4d65124303bd..0cc892f4a1b3c6ce575a5d4fca7acf7057f7b7f7 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -639,7 +639,7 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
>  		return dev_err_probe(dev, PTR_ERR(csi2->phy),
>  				     "failed to get MIPI CSI-2 PHY\n");
>  
> -	csi2->reset = devm_reset_control_get_exclusive(dev, NULL);
> +	csi2->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
>  	if (IS_ERR(csi2->reset))
>  		return dev_err_probe(dev, PTR_ERR(csi2->reset),
>  				     "failed to get reset\n");
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/6] media: synopsys: only check errors from devm_clk_bulk_get_all()
  2026-02-10 17:11 ` [PATCH 2/6] media: synopsys: only check errors from devm_clk_bulk_get_all() Frank Li
@ 2026-02-13  9:35   ` Michael Riesch
  0 siblings, 0 replies; 19+ messages in thread
From: Michael Riesch @ 2026-02-13  9:35 UTC (permalink / raw)
  To: Frank Li, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx

Hi Frank,

Thanks for your patch.

The remark w.r.t. the "media: synopsys: csi2rx: " prefix holds for this
and all the other patches in this series as well, of course.

On 2/10/26 18:11, Frank Li wrote:
> devm_clk_bulk_get_all() returns all clocks described in the DT, which are
> already validated by the binding. Do not need enforce an expected clock
> count.
> 
> Only check for error returns (< 0) to support more SoCs.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index 0cc892f4a1b3c6ce575a5d4fca7acf7057f7b7f7..61cd7f491b3d5b8a37707b23ca03ce709b40a79f 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -630,7 +630,7 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
>  		return PTR_ERR(csi2->base_addr);
>  
>  	ret = devm_clk_bulk_get_all(dev, &csi2->clks);
> -	if (ret != DW_MIPI_CSI2RX_CLKS_MAX)

DW_MIPI_CSI2RX_CLKS_MAX is not used anymore, please remove.

With that change,

Reviewed-by: Michael Riesch <michael.riesch@collabora.com>

Best regards,
Michael


> +	if (ret < 0)
>  		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
>  	csi2->clks_num = ret;
>  
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets
  2026-02-10 17:11 ` [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets Frank Li
@ 2026-02-13 10:02   ` Michael Riesch
  2026-03-24  8:16   ` Sakari Ailus
  1 sibling, 0 replies; 19+ messages in thread
From: Michael Riesch @ 2026-02-13 10:02 UTC (permalink / raw)
  To: Frank Li, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx

Hi Frank,

Thanks for the patch.

Please keep the order:
 - #includes
 - #defines
 - enum and struct definitions
 - the rest

On 2/10/26 18:11, Frank Li wrote:
> Use struct dw_mipi_csi2rx_regs to describe register offsets and support
> new IP versions with differing register layouts.
> 
> Add rk3568_regs, matching the previous macro definitions, and pass it as
> driver data retrieved during probe.
> 
> No functional change.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 96 +++++++++++++++++-------
>  1 file changed, 69 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index 4ad4e3b23448affeeaa932a706653818ba4019ba..6a2966c9e3a2eac661fa1f8610c9f021d6e26cf8 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -24,14 +24,39 @@
>  #include <media/v4l2-mc.h>
>  #include <media/v4l2-subdev.h>
>  
> -#define DW_MIPI_CSI2RX_N_LANES		0x04
> -#define DW_MIPI_CSI2RX_RESETN		0x10
> -#define DW_MIPI_CSI2RX_PHY_STATE	0x14
> -#define DW_MIPI_CSI2RX_ERR1		0x20
> -#define DW_MIPI_CSI2RX_ERR2		0x24
> -#define DW_MIPI_CSI2RX_MSK1		0x28
> -#define DW_MIPI_CSI2RX_MSK2		0x2c
> -#define DW_MIPI_CSI2RX_CONTROL		0x40
> +struct dw_mipi_csi2rx_regs {
> +	u32 n_lanes;
> +	u32 resetn;
> +	u32 phy_state;
> +	u32 err1;
> +	u32 err2;
> +	u32 msk1;
> +	u32 msk2;
> +	u32 control;
> +};
> +
> +struct dw_mipi_csi2rx_drvdata {
> +	const struct dw_mipi_csi2rx_regs *regs;
> +};
> +
> +/* Help check wrong access unexisted register at difference IP version */
> +#define DW_REG_EXIST	BIT(31)
> +#define DW_REG(x)	(DW_REG_EXIST | (x))
> +
> +static const struct dw_mipi_csi2rx_regs rk3568_regs = {
> +	.n_lanes = DW_REG(0x4),
> +	.resetn = DW_REG(0x10),
> +	.phy_state = DW_REG(0x14),
> +	.err1 = DW_REG(0x20),
> +	.err2 = DW_REG(0x24),
> +	.msk1 = DW_REG(0x28),
> +	.msk2 = DW_REG(0x2c),
> +	.control = DW_REG(0x40),
> +};
> +
> +static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {
> +	.regs = &rk3568_regs,
> +};
>  
>  #define SW_CPHY_EN(x)		((x) << 0)
>  #define SW_DSI_EN(x)		((x) << 4)
> @@ -74,8 +99,35 @@ struct dw_mipi_csi2rx_device {
>  
>  	enum v4l2_mbus_type bus_type;
>  	u32 lanes_num;
> +
> +	const struct dw_mipi_csi2rx_drvdata *drvdata;
>  };
>  
> +static int
> +dw_mipi_csi2rx_reg_err(struct dw_mipi_csi2rx_device *csi2, const char *name)
> +{
> +	dev_err_once(csi2->dev, "access to non-existent register: %s\n", name);
> +	return 0;
> +}
> +
> +#define __dw_reg_exist(offset) ((offset) & DW_REG_EXIST)
> +
> +#define dw_reg_exist(csi2, __name) __dw_reg_exist((csi2)->drvdata->regs->__name)
> +
> +#define dw_mipi_csi2rx_write(csi2, __name, value)		\
> +({	auto __csi2 = csi2;					\
> +	u32 offset = __csi2->drvdata->regs->__name;		\
> +	__dw_reg_exist(offset) ?					\
> +		writel(value, __csi2->base_addr + (offset & ~DW_REG_EXIST)) : \
> +		dw_mipi_csi2rx_reg_err(__csi2, #__name); })
> +
> +#define dw_mipi_csi2rx_read(csi2, __name)			\
> +({	auto __csi2 = csi2;					\
> +	u32 offset = __csi2->drvdata->regs->__name;		\
> +	__dw_reg_exist(offset) ?					\
> +		readl(__csi2->base_addr + (offset & ~DW_REG_EXIST)) : \
> +		dw_mipi_csi2rx_reg_err(__csi2, #__name); })

Please use an

enum {
	DW_MIPI_CSI2RX_N_LANES,
	DW_MIPI_CSI2RX_RESETN,
	...,
	DW_MIPI_CSI2RX_MAX
};

a member regs[DW_MIPI_CSI2RX_MAX] in dw_mipi_csi2rx_drvdata, and adjust
the dw_mipi_csi2rx_{read,write} accordingly. This is cleaner IMHO and
integrates better with the existing code.

> +
>  static const struct v4l2_mbus_framefmt default_format = {
>  	.width = 3840,
>  	.height = 2160,
> @@ -188,18 +240,6 @@ static inline struct dw_mipi_csi2rx_device *to_csi2(struct v4l2_subdev *sd)
>  	return container_of(sd, struct dw_mipi_csi2rx_device, sd);
>  }
>  
> -static inline void dw_mipi_csi2rx_write(struct dw_mipi_csi2rx_device *csi2,
> -					unsigned int addr, u32 val)
> -{
> -	writel(val, csi2->base_addr + addr);
> -}
> -
> -static inline u32 dw_mipi_csi2rx_read(struct dw_mipi_csi2rx_device *csi2,
> -				      unsigned int addr)
> -{
> -	return readl(csi2->base_addr + addr);
> -}
> -
>  static const struct dw_mipi_csi2rx_format *
>  dw_mipi_csi2rx_find_format(struct dw_mipi_csi2rx_device *csi2, u32 mbus_code)
>  {
> @@ -265,9 +305,9 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
>  	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
>  		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
>  
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_N_LANES, lanes - 1);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_CONTROL, control);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 1);
> +	dw_mipi_csi2rx_write(csi2, n_lanes, lanes - 1);
> +	dw_mipi_csi2rx_write(csi2, control, control);
> +	dw_mipi_csi2rx_write(csi2, resetn, 1);
>  
>  	return phy_power_on(csi2->phy);
>  }
> @@ -276,9 +316,9 @@ static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
>  {
>  	phy_power_off(csi2->phy);
>  
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 0);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK2, ~0);
> +	dw_mipi_csi2rx_write(csi2, resetn, 0);
> +	dw_mipi_csi2rx_write(csi2, msk1, ~0);
> +	dw_mipi_csi2rx_write(csi2, msk2, ~0);
>  }
>  
>  static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
> @@ -632,7 +672,7 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
>  
>  static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
>  	{
> -		.compatible = "rockchip,rk3568-mipi-csi2",
> +		.compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata,

		.compatible = "rockchip,rk3568-mipi-csi2",
		.data = &rk3568_drvdata,

for minimal diff and cleanliness.

Please make sure that the last patch of this series is adjusted
accordingly and continues this formatting.


>  	},
>  	{}
>  };
> @@ -654,6 +694,8 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
>  	if (IS_ERR(csi2->base_addr))
>  		return PTR_ERR(csi2->base_addr);
>  
> +	csi2->drvdata = device_get_match_data(dev);

Check for (!csi2->drvdata)

> +
>  	ret = devm_clk_bulk_get_all(dev, &csi2->clks);
>  	if (ret < 0)
>  		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
> 

Best regards,
Michael


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 6/6] media: synopsys: add i.MX93 support
  2026-02-10 17:11 ` [PATCH 6/6] media: synopsys: add i.MX93 support Frank Li
@ 2026-02-13 10:22   ` Michael Riesch
  0 siblings, 0 replies; 19+ messages in thread
From: Michael Riesch @ 2026-02-13 10:22 UTC (permalink / raw)
  To: Frank Li, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx

Hi Frank,

On 2/10/26 18:11, Frank Li wrote:
> The i.MX93 uses a newer version of the DW CSI-2 controller with a changed
> register layout and an added IPI block.

What does this IPI block do? Please add a short description.

> 
> The reset flow also differs, so add the .assert_reset(), .deassert_reset(),
> and .ipi_enable() callbacks to support it.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 163 ++++++++++++++++++++++-
>  1 file changed, 156 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index 6a2966c9e3a2eac661fa1f8610c9f021d6e26cf8..5dc55b59d6aeed4b6cb207c8e2ebe0fb3c462644 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -33,10 +33,24 @@ struct dw_mipi_csi2rx_regs {
>  	u32 msk1;
>  	u32 msk2;
>  	u32 control;
> +	u32 phy_tst_ctrl0;
> +	u32 phy_tst_ctrl1;
> +	u32 dphy_rstz;
> +	u32 phy_shutdownz;
> +	u32 ipi_softrstn;
> +	u32 ipi_datatype;
> +	u32 ipi_vcid;
> +	u32 ipi_mode;
> +	u32 ipi_mem_flush;
>  };
>  
> +struct dw_mipi_csi2rx_device;
> +
>  struct dw_mipi_csi2rx_drvdata {
>  	const struct dw_mipi_csi2rx_regs *regs;
> +	void (*dphy_assert_reset)(struct dw_mipi_csi2rx_device *csi2);
> +	void (*dphy_deassert_reset)(struct dw_mipi_csi2rx_device *csi2);
> +	void (*ipi_enable)(struct dw_mipi_csi2rx_device *csi2);
>  };
>  
>  /* Help check wrong access unexisted register at difference IP version */
> @@ -54,6 +68,21 @@ static const struct dw_mipi_csi2rx_regs rk3568_regs = {
>  	.control = DW_REG(0x40),
>  };
>  
> +static const struct dw_mipi_csi2rx_regs imx93_regs = {
> +	.n_lanes = DW_REG(0x4),
> +	.resetn = DW_REG(0x8),
> +	.phy_shutdownz = DW_REG(0x40),
> +	.dphy_rstz = DW_REG(0x44),
> +	.phy_state = DW_REG(0x48),
> +	.phy_tst_ctrl0 = DW_REG(0x50),
> +	.phy_tst_ctrl1 = DW_REG(0x54),
> +	.ipi_mode = DW_REG(0x80),
> +	.ipi_vcid = DW_REG(0x84),
> +	.ipi_datatype = DW_REG(0x88),
> +	.ipi_mem_flush = DW_REG(0x8c),
> +	.ipi_softrstn = DW_REG(0xa0),
> +};
> +
>  static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {
>  	.regs = &rk3568_regs,
>  };
> @@ -302,14 +331,30 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
>  		return -EINVAL;
>  	}
>  
> +	dw_mipi_csi2rx_write(csi2, resetn, 0);
> +
> +	if (csi2->drvdata->dphy_assert_reset)
> +		csi2->drvdata->dphy_assert_reset(csi2);
> +
>  	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
>  		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
>  
>  	dw_mipi_csi2rx_write(csi2, n_lanes, lanes - 1);
> -	dw_mipi_csi2rx_write(csi2, control, control);
> +
> +	if (dw_reg_exist(csi2, control))

Why? The _write functions check for existance anyway, right?

> +		dw_mipi_csi2rx_write(csi2, control, control);
> +
> +	ret = phy_power_on(csi2->phy);

Does it make sense to continue if phy_power_on fails? Check the return
value and return early.

> +
> +	if (csi2->drvdata->dphy_deassert_reset)
> +		csi2->drvdata->dphy_deassert_reset(csi2);
> +
>  	dw_mipi_csi2rx_write(csi2, resetn, 1);
>  
> -	return phy_power_on(csi2->phy);
> +	if (csi2->drvdata->ipi_enable)
> +		csi2->drvdata->ipi_enable(csi2);
> +
> +	return ret;
>  }
>  
>  static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
> @@ -317,8 +362,12 @@ static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
>  	phy_power_off(csi2->phy);
>  
>  	dw_mipi_csi2rx_write(csi2, resetn, 0);
> -	dw_mipi_csi2rx_write(csi2, msk1, ~0);
> -	dw_mipi_csi2rx_write(csi2, msk2, ~0);
> +
> +	if (dw_reg_exist(csi2, msk1))
> +		dw_mipi_csi2rx_write(csi2, msk1, ~0);
> +
> +	if (dw_reg_exist(csi2, msk2))
> +		dw_mipi_csi2rx_write(csi2, msk2, ~0);

Again, the dw_reg_exist checks seem superfluous.

>  }
>  
>  static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
> @@ -670,10 +719,110 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
>  	v4l2_async_nf_cleanup(&csi2->notifier);
>  }
>  
> +#define DPHY_TEST_CTRL0_TEST_CLR	BIT(0)

All #defines at the top, as already pointed out before. Holds for all
other bit defines, too.

> +
> +static void imx93_csi2rx_dphy_assert_reset(struct dw_mipi_csi2rx_device *csi2)
> +{
> +	u32 val;
> +
> +	/* Release synopsis DPHY test codes from reset */
> +	dw_mipi_csi2rx_write(csi2, dphy_rstz, 0);
> +	dw_mipi_csi2rx_write(csi2, phy_shutdownz, 0);
> +
> +	val = dw_mipi_csi2rx_read(csi2, phy_tst_ctrl0);
> +	val &= ~DPHY_TEST_CTRL0_TEST_CLR;
> +	dw_mipi_csi2rx_write(csi2, phy_tst_ctrl0, val);
> +
> +	/*
> +	 * ndelay is not necessary have MMIO operation, need dummy read to make
> +	 * sure above write reach target.
> +	 */
> +	val = dw_mipi_csi2rx_read(csi2, phy_tst_ctrl0);
> +	/* Wait for at least 15ns */
> +	ndelay(15);
> +	val |= DPHY_TEST_CTRL0_TEST_CLR;
> +	dw_mipi_csi2rx_write(csi2, phy_tst_ctrl0, val);
> +}
> +
> +#define CSI2RX_DPHY_STOPSTATE_CLK_LANE BIT(16)
> +
> +static void imx93_csi2rx_dphy_deassert_reset(struct dw_mipi_csi2rx_device *csi2)
> +{
> +	/* Release PHY from reset */
> +	dw_mipi_csi2rx_write(csi2, phy_shutdownz, 0x1);
> +	/*
> +	 * ndelay is not necessary have MMIO operation, need dummy read to make
> +	 * sure above write reach target.
> +	 */
> +	dw_mipi_csi2rx_read(csi2, phy_shutdownz);
> +	ndelay(5);
> +	dw_mipi_csi2rx_write(csi2, dphy_rstz, 0x1);
> +
> +	dw_mipi_csi2rx_read(csi2, dphy_rstz);
> +	ndelay(5);
> +}
> +
> +#define IPI_VCID_VC(x)			FIELD_PREP(GENMASK(1, 0), (x))
> +#define IPI_VCID_VC_0_1(x)		FIELD_PREP(GENMASK(3, 2), (x))
> +#define IPI_VCID_VC_2			BIT(4)
> +
> +#define IPI_DATA_TYPE_DT(x)		FIELD_PREP(GENMASK(5, 0), (x))
> +#define IPI_DATA_TYPE_EMB_DATA_EN	BIT(8)
> +
> +#define IPI_MODE_CONTROLLER		BIT(1)
> +#define IPI_MODE_COLOR_MODE16		BIT(8)
> +#define IPI_MODE_CUT_THROUGH		BIT(16)
> +#define IPI_MODE_ENABLE			BIT(24)
> +
> +#define IPI_MEM_FLUSH_AUTO		BIT(8)
> +
> +static void imx93_csi2rx_dphy_ipi_enable(struct dw_mipi_csi2rx_device *csi2)
> +{
> +	int dt = csi2->formats->csi_dt;
> +	u32 val;
> +
> +	/* Do IPI soft reset */
> +	dw_mipi_csi2rx_write(csi2, ipi_softrstn, 0x0);
> +	dw_mipi_csi2rx_write(csi2, ipi_softrstn, 0x1);
> +
> +	/* Select virtual channel and data type to be processed by IPI */
> +	val = IPI_DATA_TYPE_DT(dt);
> +	dw_mipi_csi2rx_write(csi2, ipi_datatype, val);
> +
> +	/* Set virtual channel 0 as default */
> +	val  = IPI_VCID_VC(0);
> +	dw_mipi_csi2rx_write(csi2, ipi_vcid, val);
> +
> +	/*
> +	 * Select IPI camera timing mode and allow the pixel stream
> +	 * to be non-continuous when pixel interface FIFO is empty
> +	 */
> +	val = dw_mipi_csi2rx_read(csi2, ipi_mode);
> +	val &= ~IPI_MODE_CONTROLLER;
> +	val &= ~IPI_MODE_COLOR_MODE16;
> +	val |= IPI_MODE_CUT_THROUGH;
> +	dw_mipi_csi2rx_write(csi2, ipi_mode, val);
> +
> +	/* Memory is automatically flushed at each Frame Start */
> +	val = IPI_MEM_FLUSH_AUTO;
> +	dw_mipi_csi2rx_write(csi2, ipi_mem_flush, val);
> +
> +	/* Enable IPI */
> +	val = dw_mipi_csi2rx_read(csi2, ipi_mode);
> +	val |= IPI_MODE_ENABLE;
> +	dw_mipi_csi2rx_write(csi2, ipi_mode, val);
> +}
> +
> +static const struct dw_mipi_csi2rx_drvdata imx93_drvdata = {
> +	.regs = &imx93_regs,
> +	.dphy_assert_reset = imx93_csi2rx_dphy_assert_reset,
> +	.dphy_deassert_reset = imx93_csi2rx_dphy_deassert_reset,
> +	.ipi_enable = imx93_csi2rx_dphy_ipi_enable,
> +};
> +
>  static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
> -	{
> -		.compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata,
> -	},
> +	{ .compatible = "fsl,imx93-mipi-csi2", .data = &imx93_drvdata, },

As pointed out before,
	{
		.compatible = "fsl,imx93-mipi-csi2",
		.data = &imx93_drvdata,
	},

Best regards,
Michael

> +	{ .compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata, },
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, dw_mipi_csi2rx_of_match);
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/6] media: synopsys: Add imx93 support
  2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
                   ` (5 preceding siblings ...)
  2026-02-10 17:11 ` [PATCH 6/6] media: synopsys: add i.MX93 support Frank Li
@ 2026-03-23 19:10 ` Frank Li
  2026-03-24  8:01   ` Sakari Ailus
  2026-03-24  8:18   ` Sakari Ailus
  6 siblings, 2 replies; 19+ messages in thread
From: Frank Li @ 2026-03-23 19:10 UTC (permalink / raw)
  To: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Laurent Pinchart, Sakari Ailus
  Cc: linux-media, linux-kernel, devicetree, linux-arm-kernel,
	linux-rockchip, Guoniu Zhou, Laurent Pinchart, imx

On Tue, Feb 10, 2026 at 12:11:07PM -0500, Frank Li wrote:
> This 3rd time try to support DW CSI2RX support for imx93.
>

Laurent Pinchart and Sakari Ailus:

	I am not who will take care this patch?
	original drivers/media/platform/synopsys/dw-mipi-csi2rx.c picked
by Sakari Ailus

Frank

> 1st: Create new dw csi2 driver
> https://lore.kernel.org/all/20250701-95_cam-v1-5-c5172bab387b@nxp.com/
>
> 2nd: Based on legacy imx6's DW CSI2 constroller.
> https://lore.kernel.org/imx/20250821-95_cam-v3-0-c9286fbb34b9@nxp.com/
>
> Now rockchip create a common DW CSI2RX driver at
> drivers/media/platform/synopsys/dw-mipi-csi2rx.c
>
> This time base on rockchip's implement.
>
> i.MX93's version is newer than rockchip one. i.MX6's is more similar with
> rockchips.
>
> But i.MX6 is too old. So start at i.MX93 firstly even it has bigger
> difference.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Frank Li (6):
>       media: synopsys: use devm_reset_control_get_optional_exclusive()
>       media: synopsys: only check errors from devm_clk_bulk_get_all()
>       media: synopsys: implement .get_frame_desc() callback
>       media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets
>       media: dt-bindings: add NXP i.MX93 compatible string
>       media: synopsys: add i.MX93 support
>
>  .../bindings/media/rockchip,rk3568-mipi-csi2.yaml  |  47 +++-
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c   | 280 ++++++++++++++++++---
>  2 files changed, 293 insertions(+), 34 deletions(-)
> ---
> base-commit: ada3fa02f7a95623b724dfe300fce6f49cc2d75a
> change-id: 20260128-imx93-dw-csi2-b472ddcb176a
>
> Best regards,
> --
> Frank Li <Frank.Li@nxp.com>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/6] media: synopsys: Add imx93 support
  2026-03-23 19:10 ` [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
@ 2026-03-24  8:01   ` Sakari Ailus
  2026-03-24  8:18   ` Sakari Ailus
  1 sibling, 0 replies; 19+ messages in thread
From: Sakari Ailus @ 2026-03-24  8:01 UTC (permalink / raw)
  To: Frank Li
  Cc: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Laurent Pinchart, linux-media, linux-kernel, devicetree,
	linux-arm-kernel, linux-rockchip, Guoniu Zhou, imx

Hi Frank,

On Mon, Mar 23, 2026 at 03:10:44PM -0400, Frank Li wrote:
> On Tue, Feb 10, 2026 at 12:11:07PM -0500, Frank Li wrote:
> > This 3rd time try to support DW CSI2RX support for imx93.
> >
> 
> Laurent Pinchart and Sakari Ailus:
> 
> 	I am not who will take care this patch?
> 	original drivers/media/platform/synopsys/dw-mipi-csi2rx.c picked
> by Sakari Ailus

I'll review them soonish; please cc me in the future.

Thanks.

-- 
Sakari Ailus

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 3/6] media: synopsys: implement .get_frame_desc() callback
  2026-02-10 17:11 ` [PATCH 3/6] media: synopsys: implement .get_frame_desc() callback Frank Li
@ 2026-03-24  8:02   ` Sakari Ailus
  0 siblings, 0 replies; 19+ messages in thread
From: Sakari Ailus @ 2026-03-24  8:02 UTC (permalink / raw)
  To: Frank Li
  Cc: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, linux-media,
	linux-kernel, devicetree, linux-arm-kernel, linux-rockchip,
	Guoniu Zhou, Laurent Pinchart, imx

Hi Frank,

On Tue, Feb 10, 2026 at 12:11:10PM -0500, Frank Li wrote:
> Implement the .get_frame_desc() callback to fetch information from the
> remote endpoint.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 25 ++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index 61cd7f491b3d5b8a37707b23ca03ce709b40a79f..4ad4e3b23448affeeaa932a706653818ba4019ba 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -70,6 +70,8 @@ struct dw_mipi_csi2rx_device {
>  	struct v4l2_async_notifier notifier;
>  	struct v4l2_subdev sd;
>  
> +	struct v4l2_subdev *remote_source;
> +
>  	enum v4l2_mbus_type bus_type;
>  	u32 lanes_num;
>  };
> @@ -431,10 +433,31 @@ static int dw_mipi_csi2rx_disable_streams(struct v4l2_subdev *sd,
>  	return ret;
>  }
>  
> +static int
> +dw_mipi_csi2rx_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
> +			      struct v4l2_mbus_frame_desc *fd)
> +{
> +	struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
> +	struct media_pad *remote_pad;
> +
> +	if (!csi2->remote_source)
> +		return -ENODEV;
> +
> +	remote_pad = media_pad_remote_pad_unique(&csi2->pads[DW_MIPI_CSI2RX_PAD_SINK]);
> +	if (IS_ERR(remote_pad)) {
> +		dev_err(csi2->dev, "can't get source pad of %s (%pe)\n",
> +			csi2->remote_source->name, remote_pad);
> +		return PTR_ERR(remote_pad);
> +	}
> +	return v4l2_subdev_call(csi2->remote_source, pad, get_frame_desc,
> +				remote_pad->index, fd);
> +}

Can you use v4l2_subdev_get_frame_desc_passthrough()?

> +
>  static const struct v4l2_subdev_pad_ops dw_mipi_csi2rx_pad_ops = {
>  	.enum_mbus_code = dw_mipi_csi2rx_enum_mbus_code,
>  	.get_fmt = v4l2_subdev_get_fmt,
>  	.set_fmt = dw_mipi_csi2rx_set_fmt,
> +	.get_frame_desc = dw_mipi_csi2rx_get_frame_desc,
>  	.set_routing = dw_mipi_csi2rx_set_routing,
>  	.enable_streams = dw_mipi_csi2rx_enable_streams,
>  	.disable_streams = dw_mipi_csi2rx_disable_streams,
> @@ -487,6 +510,8 @@ static int dw_mipi_csi2rx_notifier_bound(struct v4l2_async_notifier *notifier,
>  		return ret;
>  	}
>  
> +	csi2->remote_source = sd;
> +
>  	return 0;
>  }
>  
> 

-- 
Regards,

Sakari Ailus

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets
  2026-02-10 17:11 ` [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets Frank Li
  2026-02-13 10:02   ` Michael Riesch
@ 2026-03-24  8:16   ` Sakari Ailus
  1 sibling, 0 replies; 19+ messages in thread
From: Sakari Ailus @ 2026-03-24  8:16 UTC (permalink / raw)
  To: Frank Li
  Cc: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, linux-media,
	linux-kernel, devicetree, linux-arm-kernel, linux-rockchip,
	Guoniu Zhou, Laurent Pinchart, imx

Hi Frank,

On Tue, Feb 10, 2026 at 12:11:11PM -0500, Frank Li wrote:
> Use struct dw_mipi_csi2rx_regs to describe register offsets and support
> new IP versions with differing register layouts.
> 
> Add rk3568_regs, matching the previous macro definitions, and pass it as
> driver data retrieved during probe.
> 
> No functional change.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 96 +++++++++++++++++-------
>  1 file changed, 69 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> index 4ad4e3b23448affeeaa932a706653818ba4019ba..6a2966c9e3a2eac661fa1f8610c9f021d6e26cf8 100644
> --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> @@ -24,14 +24,39 @@
>  #include <media/v4l2-mc.h>
>  #include <media/v4l2-subdev.h>
>  
> -#define DW_MIPI_CSI2RX_N_LANES		0x04
> -#define DW_MIPI_CSI2RX_RESETN		0x10
> -#define DW_MIPI_CSI2RX_PHY_STATE	0x14
> -#define DW_MIPI_CSI2RX_ERR1		0x20
> -#define DW_MIPI_CSI2RX_ERR2		0x24
> -#define DW_MIPI_CSI2RX_MSK1		0x28
> -#define DW_MIPI_CSI2RX_MSK2		0x2c
> -#define DW_MIPI_CSI2RX_CONTROL		0x40
> +struct dw_mipi_csi2rx_regs {
> +	u32 n_lanes;
> +	u32 resetn;
> +	u32 phy_state;
> +	u32 err1;
> +	u32 err2;
> +	u32 msk1;
> +	u32 msk2;
> +	u32 control;
> +};
> +
> +struct dw_mipi_csi2rx_drvdata {
> +	const struct dw_mipi_csi2rx_regs *regs;
> +};
> +
> +/* Help check wrong access unexisted register at difference IP version */
> +#define DW_REG_EXIST	BIT(31)
> +#define DW_REG(x)	(DW_REG_EXIST | (x))
> +
> +static const struct dw_mipi_csi2rx_regs rk3568_regs = {
> +	.n_lanes = DW_REG(0x4),
> +	.resetn = DW_REG(0x10),
> +	.phy_state = DW_REG(0x14),
> +	.err1 = DW_REG(0x20),
> +	.err2 = DW_REG(0x24),
> +	.msk1 = DW_REG(0x28),
> +	.msk2 = DW_REG(0x2c),
> +	.control = DW_REG(0x40),
> +};
> +
> +static const struct dw_mipi_csi2rx_drvdata rk3568_drvdata = {

"drvdata" is typically used of driver's context struct related to a given
device. This is something else. How about calling it rk3568_devinfo for
instance?

> +	.regs = &rk3568_regs,
> +};
>  
>  #define SW_CPHY_EN(x)		((x) << 0)
>  #define SW_DSI_EN(x)		((x) << 4)
> @@ -74,8 +99,35 @@ struct dw_mipi_csi2rx_device {
>  
>  	enum v4l2_mbus_type bus_type;
>  	u32 lanes_num;
> +
> +	const struct dw_mipi_csi2rx_drvdata *drvdata;
>  };
>  
> +static int
> +dw_mipi_csi2rx_reg_err(struct dw_mipi_csi2rx_device *csi2, const char *name)
> +{
> +	dev_err_once(csi2->dev, "access to non-existent register: %s\n", name);
> +	return 0;
> +}
> +
> +#define __dw_reg_exist(offset) ((offset) & DW_REG_EXIST)
> +
> +#define dw_reg_exist(csi2, __name) __dw_reg_exist((csi2)->drvdata->regs->__name)

Can you use the same dw_mipi_csi2rx prefix here?

> +
> +#define dw_mipi_csi2rx_write(csi2, __name, value)		\
> +({	auto __csi2 = csi2;					\

Are there different types being used for csi2? As this there's a single
driver here I'd suppose no?

> +	u32 offset = __csi2->drvdata->regs->__name;		\
> +	__dw_reg_exist(offset) ?					\
> +		writel(value, __csi2->base_addr + (offset & ~DW_REG_EXIST)) : \
> +		dw_mipi_csi2rx_reg_err(__csi2, #__name); })
> +
> +#define dw_mipi_csi2rx_read(csi2, __name)			\
> +({	auto __csi2 = csi2;					\
> +	u32 offset = __csi2->drvdata->regs->__name;		\
> +	__dw_reg_exist(offset) ?					\
> +		readl(__csi2->base_addr + (offset & ~DW_REG_EXIST)) : \
> +		dw_mipi_csi2rx_reg_err(__csi2, #__name); })
> +
>  static const struct v4l2_mbus_framefmt default_format = {
>  	.width = 3840,
>  	.height = 2160,
> @@ -188,18 +240,6 @@ static inline struct dw_mipi_csi2rx_device *to_csi2(struct v4l2_subdev *sd)
>  	return container_of(sd, struct dw_mipi_csi2rx_device, sd);
>  }
>  
> -static inline void dw_mipi_csi2rx_write(struct dw_mipi_csi2rx_device *csi2,
> -					unsigned int addr, u32 val)
> -{
> -	writel(val, csi2->base_addr + addr);
> -}
> -
> -static inline u32 dw_mipi_csi2rx_read(struct dw_mipi_csi2rx_device *csi2,
> -				      unsigned int addr)
> -{
> -	return readl(csi2->base_addr + addr);
> -}
> -
>  static const struct dw_mipi_csi2rx_format *
>  dw_mipi_csi2rx_find_format(struct dw_mipi_csi2rx_device *csi2, u32 mbus_code)
>  {
> @@ -265,9 +305,9 @@ static int dw_mipi_csi2rx_start(struct dw_mipi_csi2rx_device *csi2)
>  	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
>  		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
>  
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_N_LANES, lanes - 1);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_CONTROL, control);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 1);
> +	dw_mipi_csi2rx_write(csi2, n_lanes, lanes - 1);
> +	dw_mipi_csi2rx_write(csi2, control, control);
> +	dw_mipi_csi2rx_write(csi2, resetn, 1);
>  
>  	return phy_power_on(csi2->phy);
>  }
> @@ -276,9 +316,9 @@ static void dw_mipi_csi2rx_stop(struct dw_mipi_csi2rx_device *csi2)
>  {
>  	phy_power_off(csi2->phy);
>  
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_RESETN, 0);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK1, ~0);
> -	dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_MSK2, ~0);
> +	dw_mipi_csi2rx_write(csi2, resetn, 0);
> +	dw_mipi_csi2rx_write(csi2, msk1, ~0);
> +	dw_mipi_csi2rx_write(csi2, msk2, ~0);
>  }
>  
>  static const struct media_entity_operations dw_mipi_csi2rx_media_ops = {
> @@ -632,7 +672,7 @@ static void dw_mipi_csi2rx_unregister(struct dw_mipi_csi2rx_device *csi2)
>  
>  static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
>  	{
> -		.compatible = "rockchip,rk3568-mipi-csi2",
> +		.compatible = "rockchip,rk3568-mipi-csi2", .data = &rk3568_drvdata,
>  	},
>  	{}
>  };
> @@ -654,6 +694,8 @@ static int dw_mipi_csi2rx_probe(struct platform_device *pdev)
>  	if (IS_ERR(csi2->base_addr))
>  		return PTR_ERR(csi2->base_addr);
>  
> +	csi2->drvdata = device_get_match_data(dev);
> +
>  	ret = devm_clk_bulk_get_all(dev, &csi2->clks);
>  	if (ret < 0)
>  		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
> 

-- 
Regards,

Sakari Ailus

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/6] media: synopsys: Add imx93 support
  2026-03-23 19:10 ` [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
  2026-03-24  8:01   ` Sakari Ailus
@ 2026-03-24  8:18   ` Sakari Ailus
  2026-03-24  9:46     ` Michael Riesch
  1 sibling, 1 reply; 19+ messages in thread
From: Sakari Ailus @ 2026-03-24  8:18 UTC (permalink / raw)
  To: Frank Li
  Cc: Michael Riesch, Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Laurent Pinchart, Sakari Ailus, linux-media, linux-kernel,
	devicetree, linux-arm-kernel, linux-rockchip, Guoniu Zhou, imx

On Mon, Mar 23, 2026 at 03:10:44PM -0400, Frank Li wrote:
> On Tue, Feb 10, 2026 at 12:11:07PM -0500, Frank Li wrote:
> > This 3rd time try to support DW CSI2RX support for imx93.
> >
> 
> Laurent Pinchart and Sakari Ailus:
> 
> 	I am not who will take care this patch?
> 	original drivers/media/platform/synopsys/dw-mipi-csi2rx.c picked
> by Sakari Ailus

Michael seems to have questions on the last patch, too.

-- 
Sakari Ailus

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/6] media: synopsys: Add imx93 support
  2026-03-24  8:18   ` Sakari Ailus
@ 2026-03-24  9:46     ` Michael Riesch
  2026-03-24 10:35       ` Sakari Ailus
  0 siblings, 1 reply; 19+ messages in thread
From: Michael Riesch @ 2026-03-24  9:46 UTC (permalink / raw)
  To: Sakari Ailus, Frank Li
  Cc: Mauro Carvalho Chehab, Philipp Zabel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Laurent Pinchart, Sakari Ailus, linux-media, linux-kernel,
	devicetree, linux-arm-kernel, linux-rockchip, Guoniu Zhou, imx

Hi all,

On 3/24/26 09:18, Sakari Ailus wrote:
> On Mon, Mar 23, 2026 at 03:10:44PM -0400, Frank Li wrote:
>> On Tue, Feb 10, 2026 at 12:11:07PM -0500, Frank Li wrote:
>>> This 3rd time try to support DW CSI2RX support for imx93.
>>>
>>
>> Laurent Pinchart and Sakari Ailus:
>>
>> 	I am not who will take care this patch?
>> 	original drivers/media/platform/synopsys/dw-mipi-csi2rx.c picked
>> by Sakari Ailus
> 
> Michael seems to have questions on the last patch, too.

I.. don't.. think so. After digging a bit in my memory and lore, I found
a v3 of that series with my Reviewed-by [0]

[0]
https://lore.kernel.org/all/20260216-imx93-dw-csi2-v3-0-aabafee10923@nxp.com/

Best regards,
Michael


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/6] media: synopsys: Add imx93 support
  2026-03-24  9:46     ` Michael Riesch
@ 2026-03-24 10:35       ` Sakari Ailus
  0 siblings, 0 replies; 19+ messages in thread
From: Sakari Ailus @ 2026-03-24 10:35 UTC (permalink / raw)
  To: Michael Riesch
  Cc: Sakari Ailus, Frank Li, Mauro Carvalho Chehab, Philipp Zabel,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Laurent Pinchart, linux-media, linux-kernel, devicetree,
	linux-arm-kernel, linux-rockchip, Guoniu Zhou, imx

Hi Michael,

On Tue, Mar 24, 2026 at 10:46:49AM +0100, Michael Riesch wrote:
> Hi all,
> 
> On 3/24/26 09:18, Sakari Ailus wrote:
> > On Mon, Mar 23, 2026 at 03:10:44PM -0400, Frank Li wrote:
> >> On Tue, Feb 10, 2026 at 12:11:07PM -0500, Frank Li wrote:
> >>> This 3rd time try to support DW CSI2RX support for imx93.
> >>>
> >>
> >> Laurent Pinchart and Sakari Ailus:
> >>
> >> 	I am not who will take care this patch?
> >> 	original drivers/media/platform/synopsys/dw-mipi-csi2rx.c picked
> >> by Sakari Ailus
> > 
> > Michael seems to have questions on the last patch, too.
> 
> I.. don't.. think so. After digging a bit in my memory and lore, I found
> a v3 of that series with my Reviewed-by [0]
> 
> [0]
> https://lore.kernel.org/all/20260216-imx93-dw-csi2-v3-0-aabafee10923@nxp.com/

Message-Id <9e14d605-9419-441e-a554-432d435191b3@collabora.com>.

-- 
Sakari Ailus

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2026-03-24 10:35 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-10 17:11 [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
2026-02-10 17:11 ` [PATCH 1/6] media: synopsys: use devm_reset_control_get_optional_exclusive() Frank Li
2026-02-13  9:25   ` Michael Riesch
2026-02-10 17:11 ` [PATCH 2/6] media: synopsys: only check errors from devm_clk_bulk_get_all() Frank Li
2026-02-13  9:35   ` Michael Riesch
2026-02-10 17:11 ` [PATCH 3/6] media: synopsys: implement .get_frame_desc() callback Frank Li
2026-03-24  8:02   ` Sakari Ailus
2026-02-10 17:11 ` [PATCH 4/6] media: synopsys: use struct dw_mipi_csi2rx_regs to describe register offsets Frank Li
2026-02-13 10:02   ` Michael Riesch
2026-03-24  8:16   ` Sakari Ailus
2026-02-10 17:11 ` [PATCH 5/6] media: dt-bindings: add NXP i.MX93 compatible string Frank Li
2026-02-11  6:47   ` Krzysztof Kozlowski
2026-02-10 17:11 ` [PATCH 6/6] media: synopsys: add i.MX93 support Frank Li
2026-02-13 10:22   ` Michael Riesch
2026-03-23 19:10 ` [PATCH 0/6] media: synopsys: Add imx93 support Frank Li
2026-03-24  8:01   ` Sakari Ailus
2026-03-24  8:18   ` Sakari Ailus
2026-03-24  9:46     ` Michael Riesch
2026-03-24 10:35       ` Sakari Ailus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox