Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
@ 2025-11-18 11:12 Michael Riesch via B4 Relay
  2025-11-18 11:12 ` [PATCH v2 1/3] media: dt-bindings: add " Michael Riesch via B4 Relay
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Michael Riesch via B4 Relay @ 2025-11-18 11:12 UTC (permalink / raw)
  To: Michael Riesch, Mehdi Djait, Bryan O'Donoghue,
	Laurent Pinchart, Hans Verkuil, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Philipp Zabel, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus
  Cc: linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Michael Riesch

Habidere,

This series adds support for the Rockchip MIPI CSI-2 Receiver that is
integrated into recent Rockchip SoCs, such as the RK3568 and the RK3588.

These changes have been discussed and reviewed thoroughly in roughly 10
iterations of the rkcif patch series (see [0] and predecessors). Thus,
they should be ready for inclusion in mainline.

However, as has been discussed in [0], it would be beneficial to add
support for the split mode (a feature of the Rockchip CSI-2 DPHY)
before integrating the MIPI CSI-2 Receiver into the respective SoC
device tree includes. We can readily add the DT binding and the driver
as I am positive they will not need to be changed when this feature is
introduced, but there are no patches in the series that introduce the
DT nodes.

This constitutes a small step towards mainline video capture and camera
support on the Rockchip RK3588.

Looking forward to your comments!

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

[0] https://lore.kernel.org/r/20240220-rk3568-vicap-v14-0-b38b6da0fc80@collabora.com

---
Changes in v2:
- dropped one R-b by Bryan, as there were two of them on the same patch
  (Krzysztof)
- Link to v1: https://lore.kernel.org/r/20251114-rockchip-mipi-receiver-v1-0-d13086e810dd@collabora.com

---
Michael Riesch (3):
      media: dt-bindings: add rockchip mipi csi-2 receiver
      media: rockchip: add driver for the rockchip mipi csi-2 receiver
      arm64: defconfig: enable rockchip mipi csi-2 receiver

 .../bindings/media/rockchip,rk3568-mipi-csi.yaml   | 146 ++++
 MAINTAINERS                                        |   7 +
 arch/arm64/configs/defconfig                       |   1 +
 drivers/media/platform/rockchip/Kconfig            |   1 +
 drivers/media/platform/rockchip/Makefile           |   1 +
 drivers/media/platform/rockchip/rkcsi/Kconfig      |  16 +
 drivers/media/platform/rockchip/rkcsi/Makefile     |   3 +
 drivers/media/platform/rockchip/rkcsi/rkcsi.c      | 742 +++++++++++++++++++++
 8 files changed, 917 insertions(+)
---
base-commit: 1f2353f5a1af995efbf7bea44341aa0d03460b28
change-id: 20251114-rockchip-mipi-receiver-0baf244c9c8e

Best regards,
-- 
Michael Riesch <michael.riesch@collabora.com>




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

* [PATCH v2 1/3] media: dt-bindings: add rockchip mipi csi-2 receiver
  2025-11-18 11:12 [PATCH v2 0/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver Michael Riesch via B4 Relay
@ 2025-11-18 11:12 ` Michael Riesch via B4 Relay
  2025-11-18 11:12 ` [PATCH v2 2/3] media: rockchip: add driver for the " Michael Riesch via B4 Relay
  2025-11-18 11:12 ` [PATCH v2 3/3] arm64: defconfig: enable " Michael Riesch via B4 Relay
  2 siblings, 0 replies; 10+ messages in thread
From: Michael Riesch via B4 Relay @ 2025-11-18 11:12 UTC (permalink / raw)
  To: Michael Riesch, Mehdi Djait, Bryan O'Donoghue,
	Laurent Pinchart, Hans Verkuil, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Philipp Zabel, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus
  Cc: linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Michael Riesch

From: Michael Riesch <michael.riesch@collabora.com>

Add documentation for the Rockchip MIPI CSI-2 Receiver.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
---
 .../bindings/media/rockchip,rk3568-mipi-csi.yaml   | 146 +++++++++++++++++++++
 MAINTAINERS                                        |   6 +
 2 files changed, 152 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
new file mode 100644
index 000000000000..52fe959af8f9
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
@@ -0,0 +1,146 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/rockchip,rk3568-mipi-csi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip MIPI CSI-2 Receiver
+
+maintainers:
+  - Michael Riesch <michael.riesch@collabora.com>
+
+description:
+  The Rockchip MIPI CSI-2 Receiver is a CSI-2 bridge with one input port and
+  one output port. It receives the data with the help of an external MIPI PHY
+  (C-PHY or D-PHY) and passes it to the Rockchip RK3568 Video Capture (VICAP)
+  block.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - rockchip,rk3588-mipi-csi
+          - const: rockchip,rk3568-mipi-csi
+      - const: rockchip,rk3568-mipi-csi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    items:
+      - description: Interrupt that signals changes in CSI2HOST_ERR1.
+      - description: Interrupt that signals changes in CSI2HOST_ERR2.
+
+  interrupt-names:
+    items:
+      - const: err1
+      - const: err2
+
+  clocks:
+    maxItems: 1
+
+  phys:
+    maxItems: 1
+    description: MIPI C-PHY or D-PHY.
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: Input port node. Connect to e.g., a MIPI CSI-2 image sensor.
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              bus-type:
+                enum:
+                  - 1 # MEDIA_BUS_TYPE_CSI2_CPHY
+                  - 4 # MEDIA_BUS_TYPE_CSI2_DPHY
+
+              data-lanes:
+                minItems: 1
+                maxItems: 4
+
+            required:
+              - bus-type
+              - data-lanes
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Output port connected to a RK3568 VICAP port.
+
+    required:
+      - port@0
+      - port@1
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - phys
+  - ports
+  - power-domains
+  - resets
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/media/video-interfaces.h>
+    #include <dt-bindings/power/rk3568-power.h>
+
+    soc {
+        interrupt-parent = <&gic>;
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        csi: csi@fdfb0000 {
+            compatible = "rockchip,rk3568-mipi-csi";
+            reg = <0x0 0xfdfb0000 0x0 0x10000>;
+            interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "err1", "err2";
+            clocks = <&cru PCLK_CSI2HOST1>;
+            phys = <&csi_dphy>;
+            power-domains = <&power RK3568_PD_VI>;
+            resets = <&cru SRST_P_CSI2HOST1>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                csi_in: port@0 {
+                    reg = <0>;
+
+                    csi_input: endpoint {
+                        bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+                        data-lanes = <1 2 3 4>;
+                        remote-endpoint = <&imx415_output>;
+                    };
+                };
+
+                csi_out: port@1 {
+                    reg = <1>;
+
+                    csi_output: endpoint {
+                        remote-endpoint = <&vicap_mipi_input>;
+                    };
+                };
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 4205ca007e07..145473671a4a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22299,6 +22299,12 @@ F:	Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst
 F:	drivers/media/platform/rockchip/rkisp1
 F:	include/uapi/linux/rkisp1-config.h
 
+ROCKCHIP MIPI CSI-2 RECEIVER DRIVER
+M:	Michael Riesch <michael.riesch@collabora.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
+
 ROCKCHIP RK3568 RANDOM NUMBER GENERATOR SUPPORT
 M:	Daniel Golle <daniel@makrotopia.org>
 M:	Aurelien Jarno <aurelien@aurel32.net>

-- 
2.39.5




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

* [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-11-18 11:12 [PATCH v2 0/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver Michael Riesch via B4 Relay
  2025-11-18 11:12 ` [PATCH v2 1/3] media: dt-bindings: add " Michael Riesch via B4 Relay
@ 2025-11-18 11:12 ` Michael Riesch via B4 Relay
  2025-11-18 17:15   ` Frank Li
  2025-11-18 11:12 ` [PATCH v2 3/3] arm64: defconfig: enable " Michael Riesch via B4 Relay
  2 siblings, 1 reply; 10+ messages in thread
From: Michael Riesch via B4 Relay @ 2025-11-18 11:12 UTC (permalink / raw)
  To: Michael Riesch, Mehdi Djait, Bryan O'Donoghue,
	Laurent Pinchart, Hans Verkuil, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Philipp Zabel, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus
  Cc: linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, Michael Riesch

From: Michael Riesch <michael.riesch@collabora.com>

The Rockchip MIPI CSI-2 Receiver is a CSI-2 bridge with one input
port and one output port. It receives the data with the help of an
external MIPI PHY (C-PHY or D-PHY) and passes it to the Rockchip
Video Capture (VICAP) block.

Add a V4L2 subdevice driver for this unit.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>
Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
---
 MAINTAINERS                                    |   1 +
 drivers/media/platform/rockchip/Kconfig        |   1 +
 drivers/media/platform/rockchip/Makefile       |   1 +
 drivers/media/platform/rockchip/rkcsi/Kconfig  |  16 +
 drivers/media/platform/rockchip/rkcsi/Makefile |   3 +
 drivers/media/platform/rockchip/rkcsi/rkcsi.c  | 742 +++++++++++++++++++++++++
 6 files changed, 764 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 145473671a4a..b389f2e631ce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22304,6 +22304,7 @@ M:	Michael Riesch <michael.riesch@collabora.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
+F:	drivers/media/platform/rockchip/rkcsi/
 
 ROCKCHIP RK3568 RANDOM NUMBER GENERATOR SUPPORT
 M:	Daniel Golle <daniel@makrotopia.org>
diff --git a/drivers/media/platform/rockchip/Kconfig b/drivers/media/platform/rockchip/Kconfig
index ba401d32f01b..54b698c4cd2c 100644
--- a/drivers/media/platform/rockchip/Kconfig
+++ b/drivers/media/platform/rockchip/Kconfig
@@ -4,5 +4,6 @@ comment "Rockchip media platform drivers"
 
 source "drivers/media/platform/rockchip/rga/Kconfig"
 source "drivers/media/platform/rockchip/rkcif/Kconfig"
+source "drivers/media/platform/rockchip/rkcsi/Kconfig"
 source "drivers/media/platform/rockchip/rkisp1/Kconfig"
 source "drivers/media/platform/rockchip/rkvdec/Kconfig"
diff --git a/drivers/media/platform/rockchip/Makefile b/drivers/media/platform/rockchip/Makefile
index 0e0b2cbbd4bd..522a7d3e30b0 100644
--- a/drivers/media/platform/rockchip/Makefile
+++ b/drivers/media/platform/rockchip/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y += rga/
 obj-y += rkcif/
+obj-y += rkcsi/
 obj-y += rkisp1/
 obj-y += rkvdec/
diff --git a/drivers/media/platform/rockchip/rkcsi/Kconfig b/drivers/media/platform/rockchip/rkcsi/Kconfig
new file mode 100644
index 000000000000..d8004198c386
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcsi/Kconfig
@@ -0,0 +1,16 @@
+config VIDEO_ROCKCHIP_CSI
+	tristate "Rockchip MIPI CSI-2 Receiver"
+	depends on VIDEO_DEV
+	depends on ARCH_ROCKCHIP || COMPILE_TEST
+	depends on V4L_PLATFORM_DRIVERS
+	depends on PM && COMMON_CLK
+	select MEDIA_CONTROLLER
+	select V4L2_FWNODE
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  This is a driver for Rockchip MIPI CSI-2 Receiver. It is featured
+	  in various Rockchips SoCs, usually in combination with a Video
+	  Capture (VICAP) unit (see Rockchip Camera Interface (CIF) driver).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called rockchip-mipi-csi.
diff --git a/drivers/media/platform/rockchip/rkcsi/Makefile b/drivers/media/platform/rockchip/rkcsi/Makefile
new file mode 100644
index 000000000000..147712cbb68a
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcsi/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_ROCKCHIP_CSI) += rockchip-mipi-csi.o
+rockchip-mipi-csi-objs += rkcsi.o
diff --git a/drivers/media/platform/rockchip/rkcsi/rkcsi.c b/drivers/media/platform/rockchip/rkcsi/rkcsi.c
new file mode 100644
index 000000000000..d4108ce5bbf9
--- /dev/null
+++ b/drivers/media/platform/rockchip/rkcsi/rkcsi.c
@@ -0,0 +1,742 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Rockchip MIPI CSI-2 Receiver Driver
+ *
+ * Copyright (C) 2019 Rockchip Electronics Co., Ltd.
+ * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
+ * Copyright (C) 2025 Collabora, Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define CSI2HOST_N_LANES     0x04
+#define CSI2HOST_CSI2_RESETN 0x10
+#define CSI2HOST_PHY_STATE   0x14
+#define CSI2HOST_ERR1	     0x20
+#define CSI2HOST_ERR2	     0x24
+#define CSI2HOST_MSK1	     0x28
+#define CSI2HOST_MSK2	     0x2c
+#define CSI2HOST_CONTROL     0x40
+
+#define SW_CPHY_EN(x)	     ((x) << 0)
+#define SW_DSI_EN(x)	     ((x) << 4)
+#define SW_DATATYPE_FS(x)    ((x) << 8)
+#define SW_DATATYPE_FE(x)    ((x) << 14)
+#define SW_DATATYPE_LS(x)    ((x) << 20)
+#define SW_DATATYPE_LE(x)    ((x) << 26)
+
+#define RKCSI_CLKS_MAX	     1
+
+enum {
+	RKCSI_PAD_SINK,
+	RKCSI_PAD_SRC,
+	RKCSI_PAD_MAX,
+};
+
+struct rkcsi_format {
+	u32 code;
+	u8 depth;
+	u8 csi_dt;
+};
+
+struct rkcsi_device {
+	struct device *dev;
+
+	void __iomem *base_addr;
+	struct clk_bulk_data *clks;
+	unsigned int clks_num;
+	struct phy *phy;
+	struct reset_control *reset;
+
+	const struct rkcsi_format *formats;
+	unsigned int formats_num;
+
+	struct media_pad pads[RKCSI_PAD_MAX];
+	struct v4l2_async_notifier notifier;
+	struct v4l2_fwnode_endpoint vep;
+	struct v4l2_subdev sd;
+
+	struct v4l2_subdev *source_sd;
+	u32 source_pad;
+};
+
+static const struct v4l2_mbus_framefmt default_format = {
+	.width = 3840,
+	.height = 2160,
+	.code = MEDIA_BUS_FMT_SRGGB10_1X10,
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_RAW,
+	.ycbcr_enc = V4L2_YCBCR_ENC_601,
+	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
+	.xfer_func = V4L2_XFER_FUNC_NONE,
+};
+
+static const struct rkcsi_format formats[] = {
+	/* YUV formats */
+	{
+		.code = MEDIA_BUS_FMT_YUYV8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	{
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	{
+		.code = MEDIA_BUS_FMT_YVYU8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	{
+		.code = MEDIA_BUS_FMT_VYUY8_1X16,
+		.depth = 16,
+		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
+	},
+	/* RGB formats */
+	{
+		.code = MEDIA_BUS_FMT_RGB888_1X24,
+		.depth = 24,
+		.csi_dt = MIPI_CSI2_DT_RGB888,
+	},
+	{
+		.code = MEDIA_BUS_FMT_BGR888_1X24,
+		.depth = 24,
+		.csi_dt = MIPI_CSI2_DT_RGB888,
+	},
+	/* Bayer formats */
+	{
+		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
+		.depth = 8,
+		.csi_dt = MIPI_CSI2_DT_RAW8,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
+		.depth = 10,
+		.csi_dt = MIPI_CSI2_DT_RAW10,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+	{
+		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
+		.depth = 12,
+		.csi_dt = MIPI_CSI2_DT_RAW12,
+	},
+};
+
+static inline struct rkcsi_device *to_rkcsi(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct rkcsi_device, sd);
+}
+
+static inline __maybe_unused void rkcsi_write(struct rkcsi_device *csi_dev,
+					      unsigned int addr, u32 val)
+{
+	writel(val, csi_dev->base_addr + addr);
+}
+
+static inline __maybe_unused u32 rkcsi_read(struct rkcsi_device *csi_dev,
+					    unsigned int addr)
+{
+	return readl(csi_dev->base_addr + addr);
+}
+
+static const struct rkcsi_format *
+rkcsi_find_format(struct rkcsi_device *csi_dev, u32 mbus_code)
+{
+	const struct rkcsi_format *format;
+
+	WARN_ON(csi_dev->formats_num == 0);
+
+	for (int i = 0; i < csi_dev->formats_num; i++) {
+		format = &csi_dev->formats[i];
+		if (format->code == mbus_code)
+			return format;
+	}
+
+	return NULL;
+}
+
+static int rkcsi_start(struct rkcsi_device *csi_dev)
+{
+	struct media_pad *source_pad =
+		&csi_dev->source_sd->entity.pads[csi_dev->source_pad];
+	enum v4l2_mbus_type bus_type = csi_dev->vep.bus_type;
+	union phy_configure_opts opts;
+	s64 link_freq;
+	u32 lanes = csi_dev->vep.bus.mipi_csi2.num_data_lanes;
+	u32 control = 0;
+	int ret;
+
+	if (lanes < 1 || lanes > 4)
+		return -EINVAL;
+
+	/* set mult and div to 0, thus completely rely on V4L2_CID_LINK_FREQ */
+	link_freq = v4l2_get_link_freq(source_pad, 0, 0);
+	if (link_freq <= 0)
+		return -EINVAL;
+
+	if (bus_type == V4L2_MBUS_CSI2_DPHY) {
+		struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
+
+		ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq * 2,
+								 lanes, cfg);
+		if (ret)
+			return ret;
+
+		ret = phy_set_mode(csi_dev->phy, PHY_MODE_MIPI_DPHY);
+		if (ret)
+			return ret;
+
+		ret = phy_configure(csi_dev->phy, &opts);
+		if (ret)
+			return ret;
+
+		control |= SW_CPHY_EN(0);
+
+	} else if (bus_type == V4L2_MBUS_CSI2_CPHY) {
+		/* TODO: implement CPHY configuration */
+		return -EOPNOTSUPP;
+	} else {
+		return -EINVAL;
+	}
+
+	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
+		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
+
+	rkcsi_write(csi_dev, CSI2HOST_N_LANES, lanes - 1);
+	rkcsi_write(csi_dev, CSI2HOST_CONTROL, control);
+	rkcsi_write(csi_dev, CSI2HOST_CSI2_RESETN, 1);
+
+	ret = phy_power_on(csi_dev->phy);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void rkcsi_stop(struct rkcsi_device *csi_dev)
+{
+	phy_power_off(csi_dev->phy);
+
+	rkcsi_write(csi_dev, CSI2HOST_CSI2_RESETN, 0);
+	rkcsi_write(csi_dev, CSI2HOST_MSK1, ~0);
+	rkcsi_write(csi_dev, CSI2HOST_MSK2, ~0);
+}
+
+static const struct media_entity_operations rkcsi_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int rkcsi_enum_mbus_code(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *sd_state,
+				struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct rkcsi_device *csi_dev = to_rkcsi(sd);
+
+	if (code->pad == RKCSI_PAD_SRC) {
+		const struct v4l2_mbus_framefmt *sink_fmt;
+
+		if (code->index)
+			return -EINVAL;
+
+		sink_fmt = v4l2_subdev_state_get_format(sd_state,
+							RKCSI_PAD_SINK);
+		code->code = sink_fmt->code;
+
+		return 0;
+	} else if (code->pad == RKCSI_PAD_SINK) {
+		if (code->index > csi_dev->formats_num)
+			return -EINVAL;
+
+		code->code = csi_dev->formats[code->index].code;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int rkcsi_set_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_subdev_state *state,
+			 struct v4l2_subdev_format *format)
+{
+	struct rkcsi_device *csi_dev = to_rkcsi(sd);
+	const struct rkcsi_format *fmt;
+	struct v4l2_mbus_framefmt *sink, *src;
+
+	/* the format on the source pad always matches the sink pad */
+	if (format->pad == RKCSI_PAD_SRC)
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
+	if (!sink)
+		return -EINVAL;
+
+	fmt = rkcsi_find_format(csi_dev, format->format.code);
+	if (!fmt)
+		format->format = default_format;
+
+	*sink = format->format;
+
+	/* propagate the format to the source pad */
+	src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!src)
+		return -EINVAL;
+
+	*src = *sink;
+
+	return 0;
+}
+
+static int rkcsi_set_routing(struct v4l2_subdev *sd,
+			     struct v4l2_subdev_state *state,
+			     enum v4l2_subdev_format_whence which,
+			     struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing,
+					       &default_format);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int rkcsi_enable_streams(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *state, u32 pad,
+				u64 streams_mask)
+{
+	struct rkcsi_device *csi_dev = to_rkcsi(sd);
+	struct v4l2_subdev *remote_sd;
+	struct media_pad *sink_pad, *remote_pad;
+	struct device *dev = csi_dev->dev;
+	u64 mask;
+	int ret;
+
+	sink_pad = &sd->entity.pads[RKCSI_PAD_SINK];
+	remote_pad = media_pad_remote_pad_first(sink_pad);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	mask = v4l2_subdev_state_xlate_streams(state, RKCSI_PAD_SINK,
+					       RKCSI_PAD_SRC, &streams_mask);
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret)
+		goto err;
+
+	ret = rkcsi_start(csi_dev);
+	if (ret) {
+		dev_err(dev, "failed to enable CSI hardware\n");
+		goto err_pm_runtime_put;
+	}
+
+	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
+	if (ret)
+		goto err_csi_stop;
+
+	return 0;
+
+err_csi_stop:
+	rkcsi_stop(csi_dev);
+err_pm_runtime_put:
+	pm_runtime_put_sync(dev);
+err:
+	return ret;
+}
+
+static int rkcsi_disable_streams(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state, u32 pad,
+				 u64 streams_mask)
+{
+	struct rkcsi_device *csi_dev = to_rkcsi(sd);
+	struct v4l2_subdev *remote_sd;
+	struct media_pad *sink_pad, *remote_pad;
+	struct device *dev = csi_dev->dev;
+	u64 mask;
+	int ret;
+
+	sink_pad = &sd->entity.pads[RKCSI_PAD_SINK];
+	remote_pad = media_pad_remote_pad_first(sink_pad);
+	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
+
+	mask = v4l2_subdev_state_xlate_streams(state, RKCSI_PAD_SINK,
+					       RKCSI_PAD_SRC, &streams_mask);
+
+	ret = v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
+
+	rkcsi_stop(csi_dev);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_pad_ops rkcsi_pad_ops = {
+	.enum_mbus_code = rkcsi_enum_mbus_code,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = rkcsi_set_fmt,
+	.set_routing = rkcsi_set_routing,
+	.enable_streams = rkcsi_enable_streams,
+	.disable_streams = rkcsi_disable_streams,
+};
+
+static const struct v4l2_subdev_ops rkcsi_ops = {
+	.pad = &rkcsi_pad_ops,
+};
+
+static int rkcsi_init_state(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = RKCSI_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = RKCSI_PAD_SRC,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+	struct v4l2_subdev_krouting routing = {
+		.len_routes = ARRAY_SIZE(routes),
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+	int ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
+					       &default_format);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops rkcsi_internal_ops = {
+	.init_state = rkcsi_init_state,
+};
+
+static int rkcsi_notifier_bound(struct v4l2_async_notifier *notifier,
+				struct v4l2_subdev *sd,
+				struct v4l2_async_connection *asd)
+{
+	struct rkcsi_device *csi_dev =
+		container_of(notifier, struct rkcsi_device, notifier);
+	int source_pad;
+
+	source_pad = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode,
+						 MEDIA_PAD_FL_SOURCE);
+	if (source_pad < 0) {
+		dev_err(csi_dev->dev, "failed to find source pad for %s\n",
+			sd->name);
+		return source_pad;
+	}
+
+	csi_dev->source_sd = sd;
+	csi_dev->source_pad = source_pad;
+
+	return media_create_pad_link(&sd->entity, source_pad,
+				     &csi_dev->sd.entity, RKCSI_PAD_SINK,
+				     MEDIA_LNK_FL_ENABLED);
+}
+
+static const struct v4l2_async_notifier_operations rkcsi_notifier_ops = {
+	.bound = rkcsi_notifier_bound,
+};
+
+static int rkcsi_register_notifier(struct rkcsi_device *csi_dev)
+{
+	struct v4l2_async_connection *asd;
+	struct v4l2_async_notifier *ntf = &csi_dev->notifier;
+	struct v4l2_fwnode_endpoint *vep = &csi_dev->vep;
+	struct v4l2_subdev *sd = &csi_dev->sd;
+	struct device *dev = csi_dev->dev;
+	struct fwnode_handle *ep;
+	int ret = 0;
+
+	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
+	if (!ep)
+		return dev_err_probe(dev, -ENODEV, "failed to get endpoint\n");
+
+	vep->bus_type = V4L2_MBUS_UNKNOWN;
+	ret = v4l2_fwnode_endpoint_parse(ep, vep);
+	if (ret) {
+		ret = dev_err_probe(dev, ret, "failed to parse endpoint\n");
+		goto out;
+	}
+
+	if (vep->bus_type != V4L2_MBUS_CSI2_DPHY &&
+	    vep->bus_type != V4L2_MBUS_CSI2_CPHY) {
+		ret = dev_err_probe(dev, -EINVAL,
+				    "invalid bus type of endpoint\n");
+		goto out;
+	}
+
+	v4l2_async_subdev_nf_init(ntf, sd);
+	ntf->ops = &rkcsi_notifier_ops;
+
+	asd = v4l2_async_nf_add_fwnode_remote(ntf, ep,
+					      struct v4l2_async_connection);
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
+		goto err_nf_cleanup;
+	}
+
+	ret = v4l2_async_nf_register(ntf);
+	if (ret) {
+		ret = dev_err_probe(dev, ret, "failed to register notifier\n");
+		goto err_nf_cleanup;
+	}
+
+	goto out;
+
+err_nf_cleanup:
+	v4l2_async_nf_cleanup(ntf);
+out:
+	fwnode_handle_put(ep);
+	return ret;
+}
+
+static int rkcsi_register(struct rkcsi_device *csi_dev)
+{
+	struct media_pad *pads = csi_dev->pads;
+	struct v4l2_subdev *sd = &csi_dev->sd;
+	int ret;
+
+	ret = rkcsi_register_notifier(csi_dev);
+	if (ret)
+		goto err;
+
+	v4l2_subdev_init(sd, &rkcsi_ops);
+	sd->dev = csi_dev->dev;
+	sd->entity.ops = &rkcsi_media_ops;
+	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+	sd->internal_ops = &rkcsi_internal_ops;
+	sd->owner = THIS_MODULE;
+	snprintf(sd->name, sizeof(sd->name), "rockchip-mipi-csi %s",
+		 dev_name(csi_dev->dev));
+
+	pads[RKCSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
+				     MEDIA_PAD_FL_MUST_CONNECT;
+	pads[RKCSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_pads_init(&sd->entity, RKCSI_PAD_MAX, pads);
+	if (ret)
+		goto err_notifier_unregister;
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret)
+		goto err_entity_cleanup;
+
+	ret = v4l2_async_register_subdev(sd);
+	if (ret) {
+		dev_err(sd->dev, "failed to register CSI subdev\n");
+		goto err_subdev_cleanup;
+	}
+
+	return 0;
+
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(sd);
+err_entity_cleanup:
+	media_entity_cleanup(&sd->entity);
+err_notifier_unregister:
+	v4l2_async_nf_unregister(&csi_dev->notifier);
+	v4l2_async_nf_cleanup(&csi_dev->notifier);
+err:
+	return ret;
+}
+
+static void rkcsi_unregister(struct rkcsi_device *csi_dev)
+{
+	struct v4l2_subdev *sd = &csi_dev->sd;
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_subdev_cleanup(sd);
+	media_entity_cleanup(&sd->entity);
+	v4l2_async_nf_unregister(&csi_dev->notifier);
+	v4l2_async_nf_cleanup(&csi_dev->notifier);
+}
+
+static const struct of_device_id rkcsi_of_match[] = {
+	{
+		.compatible = "rockchip,rk3568-mipi-csi",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, rkcsi_of_match);
+
+static int rkcsi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rkcsi_device *csi_dev;
+	int ret;
+
+	csi_dev = devm_kzalloc(dev, sizeof(*csi_dev), GFP_KERNEL);
+	if (!csi_dev)
+		return -ENOMEM;
+	csi_dev->dev = dev;
+	dev_set_drvdata(dev, csi_dev);
+
+	csi_dev->base_addr = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(csi_dev->base_addr))
+		return PTR_ERR(csi_dev->base_addr);
+
+	ret = devm_clk_bulk_get_all(dev, &csi_dev->clks);
+	if (ret != RKCSI_CLKS_MAX)
+		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
+	csi_dev->clks_num = ret;
+
+	csi_dev->phy = devm_phy_get(dev, NULL);
+	if (IS_ERR(csi_dev->phy))
+		return dev_err_probe(dev, PTR_ERR(csi_dev->phy),
+				     "failed to get MIPI CSI PHY\n");
+
+	csi_dev->reset = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(csi_dev->reset))
+		return dev_err_probe(dev, PTR_ERR(csi_dev->reset),
+				     "failed to get reset\n");
+
+	csi_dev->formats = formats;
+	csi_dev->formats_num = ARRAY_SIZE(formats);
+
+	pm_runtime_enable(dev);
+
+	ret = phy_init(csi_dev->phy);
+	if (ret) {
+		ret = dev_err_probe(dev, ret,
+				    "failed to initialize MIPI CSI PHY\n");
+		goto err_pm_runtime_disable;
+	}
+
+	ret = rkcsi_register(csi_dev);
+	if (ret)
+		goto err_phy_exit;
+
+	return 0;
+
+err_phy_exit:
+	phy_exit(csi_dev->phy);
+err_pm_runtime_disable:
+	pm_runtime_disable(dev);
+	return ret;
+}
+
+static void rkcsi_remove(struct platform_device *pdev)
+{
+	struct rkcsi_device *csi_dev = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	rkcsi_unregister(csi_dev);
+	phy_exit(csi_dev->phy);
+	pm_runtime_disable(dev);
+}
+
+static int rkcsi_runtime_suspend(struct device *dev)
+{
+	struct rkcsi_device *csi_dev = dev_get_drvdata(dev);
+
+	clk_bulk_disable_unprepare(csi_dev->clks_num, csi_dev->clks);
+
+	return 0;
+}
+
+static int rkcsi_runtime_resume(struct device *dev)
+{
+	struct rkcsi_device *csi_dev = dev_get_drvdata(dev);
+	int ret;
+
+	reset_control_assert(csi_dev->reset);
+	udelay(5);
+	reset_control_deassert(csi_dev->reset);
+
+	ret = clk_bulk_prepare_enable(csi_dev->clks_num, csi_dev->clks);
+	if (ret) {
+		dev_err(dev, "failed to enable clocks\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops rkcsi_pm_ops = {
+	.runtime_suspend = rkcsi_runtime_suspend,
+	.runtime_resume = rkcsi_runtime_resume,
+};
+
+static struct platform_driver rkcsi_drv = {
+	.driver = {
+		   .name = "rockchip-mipi-csi",
+		   .of_match_table = rkcsi_of_match,
+		   .pm = &rkcsi_pm_ops,
+	},
+	.probe = rkcsi_probe,
+	.remove = rkcsi_remove,
+};
+module_platform_driver(rkcsi_drv);
+
+MODULE_DESCRIPTION("Rockchip MIPI CSI-2 Receiver platform driver");
+MODULE_LICENSE("GPL");

-- 
2.39.5




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

* [PATCH v2 3/3] arm64: defconfig: enable rockchip mipi csi-2 receiver
  2025-11-18 11:12 [PATCH v2 0/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver Michael Riesch via B4 Relay
  2025-11-18 11:12 ` [PATCH v2 1/3] media: dt-bindings: add " Michael Riesch via B4 Relay
  2025-11-18 11:12 ` [PATCH v2 2/3] media: rockchip: add driver for the " Michael Riesch via B4 Relay
@ 2025-11-18 11:12 ` Michael Riesch via B4 Relay
  2 siblings, 0 replies; 10+ messages in thread
From: Michael Riesch via B4 Relay @ 2025-11-18 11:12 UTC (permalink / raw)
  To: Michael Riesch, Mehdi Djait, Bryan O'Donoghue,
	Laurent Pinchart, Hans Verkuil, Mauro Carvalho Chehab,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	Philipp Zabel, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus
  Cc: linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

From: Michael Riesch <michael.riesch@collabora.com>

The Rockchip MIPI CSI-2 Receiver is integrated into recent Rockchip
SoCs, such as the RK3568 and the RK3588.
Enable the driver for it in the default configuration.

Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index e3a2d37bd104..a161666f2894 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -883,6 +883,7 @@ CONFIG_VIDEO_RENESAS_FCP=m
 CONFIG_VIDEO_RENESAS_FDP1=m
 CONFIG_VIDEO_RENESAS_VSP1=m
 CONFIG_VIDEO_RCAR_DRIF=m
+CONFIG_VIDEO_ROCKCHIP_CSI=m
 CONFIG_VIDEO_ROCKCHIP_RGA=m
 CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m

-- 
2.39.5




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

* Re: [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-11-18 11:12 ` [PATCH v2 2/3] media: rockchip: add driver for the " Michael Riesch via B4 Relay
@ 2025-11-18 17:15   ` Frank Li
  2025-11-18 18:59     ` Michael Riesch
  0 siblings, 1 reply; 10+ messages in thread
From: Frank Li @ 2025-11-18 17:15 UTC (permalink / raw)
  To: michael.riesch
  Cc: Mehdi Djait, Bryan O'Donoghue, Laurent Pinchart, Hans Verkuil,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Philipp Zabel, Sebastian Reichel,
	Nicolas Dufresne, Collabora Kernel Team, Sakari Ailus,
	linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

On Tue, Nov 18, 2025 at 12:12:26PM +0100, Michael Riesch via B4 Relay wrote:
> From: Michael Riesch <michael.riesch@collabora.com>
>
> The Rockchip MIPI CSI-2 Receiver is a CSI-2 bridge with one input
> port and one output port. It receives the data with the help of an
> external MIPI PHY (C-PHY or D-PHY) and passes it to the Rockchip
> Video Capture (VICAP) block.
>
> Add a V4L2 subdevice driver for this unit.
>
> Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>
> Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
> ---
>  MAINTAINERS                                    |   1 +
>  drivers/media/platform/rockchip/Kconfig        |   1 +
>  drivers/media/platform/rockchip/Makefile       |   1 +
>  drivers/media/platform/rockchip/rkcsi/Kconfig  |  16 +
>  drivers/media/platform/rockchip/rkcsi/Makefile |   3 +
>  drivers/media/platform/rockchip/rkcsi/rkcsi.c  | 742 +++++++++++++++++++++++++
>  6 files changed, 764 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 145473671a4a..b389f2e631ce 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22304,6 +22304,7 @@ M:	Michael Riesch <michael.riesch@collabora.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/media/rockchip,rk3568-mipi-csi.yaml
> +F:	drivers/media/platform/rockchip/rkcsi/
>
>  ROCKCHIP RK3568 RANDOM NUMBER GENERATOR SUPPORT
>  M:	Daniel Golle <daniel@makrotopia.org>
> diff --git a/drivers/media/platform/rockchip/Kconfig b/drivers/media/platform/rockchip/Kconfig
> index ba401d32f01b..54b698c4cd2c 100644
> --- a/drivers/media/platform/rockchip/Kconfig
> +++ b/drivers/media/platform/rockchip/Kconfig
> @@ -4,5 +4,6 @@ comment "Rockchip media platform drivers"
>
>  source "drivers/media/platform/rockchip/rga/Kconfig"
>  source "drivers/media/platform/rockchip/rkcif/Kconfig"
> +source "drivers/media/platform/rockchip/rkcsi/Kconfig"
>  source "drivers/media/platform/rockchip/rkisp1/Kconfig"
>  source "drivers/media/platform/rockchip/rkvdec/Kconfig"
> diff --git a/drivers/media/platform/rockchip/Makefile b/drivers/media/platform/rockchip/Makefile
> index 0e0b2cbbd4bd..522a7d3e30b0 100644
> --- a/drivers/media/platform/rockchip/Makefile
> +++ b/drivers/media/platform/rockchip/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-y += rga/
>  obj-y += rkcif/
> +obj-y += rkcsi/
>  obj-y += rkisp1/
>  obj-y += rkvdec/
> diff --git a/drivers/media/platform/rockchip/rkcsi/Kconfig b/drivers/media/platform/rockchip/rkcsi/Kconfig
> new file mode 100644
> index 000000000000..d8004198c386
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rkcsi/Kconfig
> @@ -0,0 +1,16 @@
> +config VIDEO_ROCKCHIP_CSI
> +	tristate "Rockchip MIPI CSI-2 Receiver"
> +	depends on VIDEO_DEV
> +	depends on ARCH_ROCKCHIP || COMPILE_TEST
> +	depends on V4L_PLATFORM_DRIVERS
> +	depends on PM && COMMON_CLK
> +	select MEDIA_CONTROLLER
> +	select V4L2_FWNODE
> +	select VIDEO_V4L2_SUBDEV_API
> +	help
> +	  This is a driver for Rockchip MIPI CSI-2 Receiver. It is featured
> +	  in various Rockchips SoCs, usually in combination with a Video
> +	  Capture (VICAP) unit (see Rockchip Camera Interface (CIF) driver).
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called rockchip-mipi-csi.
> diff --git a/drivers/media/platform/rockchip/rkcsi/Makefile b/drivers/media/platform/rockchip/rkcsi/Makefile
> new file mode 100644
> index 000000000000..147712cbb68a
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rkcsi/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_VIDEO_ROCKCHIP_CSI) += rockchip-mipi-csi.o
> +rockchip-mipi-csi-objs += rkcsi.o
> diff --git a/drivers/media/platform/rockchip/rkcsi/rkcsi.c b/drivers/media/platform/rockchip/rkcsi/rkcsi.c
> new file mode 100644
> index 000000000000..d4108ce5bbf9
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/rkcsi/rkcsi.c
> @@ -0,0 +1,742 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Rockchip MIPI CSI-2 Receiver Driver
> + *
> + * Copyright (C) 2019 Rockchip Electronics Co., Ltd.
> + * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
> + * Copyright (C) 2025 Collabora, Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/of_platform.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reset.h>
> +
> +#include <media/mipi-csi2.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-fwnode.h>
> +#include <media/v4l2-subdev.h>
> +
> +#define CSI2HOST_N_LANES     0x04
> +#define CSI2HOST_CSI2_RESETN 0x10
> +#define CSI2HOST_PHY_STATE   0x14
> +#define CSI2HOST_ERR1	     0x20
> +#define CSI2HOST_ERR2	     0x24
> +#define CSI2HOST_MSK1	     0x28
> +#define CSI2HOST_MSK2	     0x2c
> +#define CSI2HOST_CONTROL     0x40

Look like that is designware CSI2 controller, can we build common library
for all dwc csi2 controller, instead of every vendor create individual one.

First try at
https://lore.kernel.org/linux-media/20250821-95_cam-v3-21-c9286fbb34b9@nxp.com/

Toshiba have similar patch
https://lore.kernel.org/linux-media/aPZd39riAxqfw3mT@lizhi-Precision-Tower-5810/

Frank

> +
> +#define SW_CPHY_EN(x)	     ((x) << 0)
> +#define SW_DSI_EN(x)	     ((x) << 4)
> +#define SW_DATATYPE_FS(x)    ((x) << 8)
> +#define SW_DATATYPE_FE(x)    ((x) << 14)
> +#define SW_DATATYPE_LS(x)    ((x) << 20)
> +#define SW_DATATYPE_LE(x)    ((x) << 26)
> +
> +#define RKCSI_CLKS_MAX	     1
> +
> +enum {
> +	RKCSI_PAD_SINK,
> +	RKCSI_PAD_SRC,
> +	RKCSI_PAD_MAX,
> +};
> +
> +struct rkcsi_format {
> +	u32 code;
> +	u8 depth;
> +	u8 csi_dt;
> +};
> +
> +struct rkcsi_device {
> +	struct device *dev;
> +
> +	void __iomem *base_addr;
> +	struct clk_bulk_data *clks;
> +	unsigned int clks_num;
> +	struct phy *phy;
> +	struct reset_control *reset;
> +
> +	const struct rkcsi_format *formats;
> +	unsigned int formats_num;
> +
> +	struct media_pad pads[RKCSI_PAD_MAX];
> +	struct v4l2_async_notifier notifier;
> +	struct v4l2_fwnode_endpoint vep;
> +	struct v4l2_subdev sd;
> +
> +	struct v4l2_subdev *source_sd;
> +	u32 source_pad;
> +};
> +
> +static const struct v4l2_mbus_framefmt default_format = {
> +	.width = 3840,
> +	.height = 2160,
> +	.code = MEDIA_BUS_FMT_SRGGB10_1X10,
> +	.field = V4L2_FIELD_NONE,
> +	.colorspace = V4L2_COLORSPACE_RAW,
> +	.ycbcr_enc = V4L2_YCBCR_ENC_601,
> +	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
> +	.xfer_func = V4L2_XFER_FUNC_NONE,
> +};
> +
> +static const struct rkcsi_format formats[] = {
> +	/* YUV formats */
> +	{
> +		.code = MEDIA_BUS_FMT_YUYV8_1X16,
> +		.depth = 16,
> +		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_UYVY8_1X16,
> +		.depth = 16,
> +		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_YVYU8_1X16,
> +		.depth = 16,
> +		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_VYUY8_1X16,
> +		.depth = 16,
> +		.csi_dt = MIPI_CSI2_DT_YUV422_8B,
> +	},
> +	/* RGB formats */
> +	{
> +		.code = MEDIA_BUS_FMT_RGB888_1X24,
> +		.depth = 24,
> +		.csi_dt = MIPI_CSI2_DT_RGB888,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_BGR888_1X24,
> +		.depth = 24,
> +		.csi_dt = MIPI_CSI2_DT_RGB888,
> +	},
> +	/* Bayer formats */
> +	{
> +		.code = MEDIA_BUS_FMT_SBGGR8_1X8,
> +		.depth = 8,
> +		.csi_dt = MIPI_CSI2_DT_RAW8,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SGBRG8_1X8,
> +		.depth = 8,
> +		.csi_dt = MIPI_CSI2_DT_RAW8,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SGRBG8_1X8,
> +		.depth = 8,
> +		.csi_dt = MIPI_CSI2_DT_RAW8,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SRGGB8_1X8,
> +		.depth = 8,
> +		.csi_dt = MIPI_CSI2_DT_RAW8,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SBGGR10_1X10,
> +		.depth = 10,
> +		.csi_dt = MIPI_CSI2_DT_RAW10,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SGBRG10_1X10,
> +		.depth = 10,
> +		.csi_dt = MIPI_CSI2_DT_RAW10,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
> +		.depth = 10,
> +		.csi_dt = MIPI_CSI2_DT_RAW10,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SRGGB10_1X10,
> +		.depth = 10,
> +		.csi_dt = MIPI_CSI2_DT_RAW10,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SBGGR12_1X12,
> +		.depth = 12,
> +		.csi_dt = MIPI_CSI2_DT_RAW12,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SGBRG12_1X12,
> +		.depth = 12,
> +		.csi_dt = MIPI_CSI2_DT_RAW12,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SGRBG12_1X12,
> +		.depth = 12,
> +		.csi_dt = MIPI_CSI2_DT_RAW12,
> +	},
> +	{
> +		.code = MEDIA_BUS_FMT_SRGGB12_1X12,
> +		.depth = 12,
> +		.csi_dt = MIPI_CSI2_DT_RAW12,
> +	},
> +};
> +
> +static inline struct rkcsi_device *to_rkcsi(struct v4l2_subdev *sd)
> +{
> +	return container_of(sd, struct rkcsi_device, sd);
> +}
> +
> +static inline __maybe_unused void rkcsi_write(struct rkcsi_device *csi_dev,
> +					      unsigned int addr, u32 val)
> +{
> +	writel(val, csi_dev->base_addr + addr);
> +}
> +
> +static inline __maybe_unused u32 rkcsi_read(struct rkcsi_device *csi_dev,
> +					    unsigned int addr)
> +{
> +	return readl(csi_dev->base_addr + addr);
> +}
> +
> +static const struct rkcsi_format *
> +rkcsi_find_format(struct rkcsi_device *csi_dev, u32 mbus_code)
> +{
> +	const struct rkcsi_format *format;
> +
> +	WARN_ON(csi_dev->formats_num == 0);
> +
> +	for (int i = 0; i < csi_dev->formats_num; i++) {
> +		format = &csi_dev->formats[i];
> +		if (format->code == mbus_code)
> +			return format;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int rkcsi_start(struct rkcsi_device *csi_dev)
> +{
> +	struct media_pad *source_pad =
> +		&csi_dev->source_sd->entity.pads[csi_dev->source_pad];
> +	enum v4l2_mbus_type bus_type = csi_dev->vep.bus_type;
> +	union phy_configure_opts opts;
> +	s64 link_freq;
> +	u32 lanes = csi_dev->vep.bus.mipi_csi2.num_data_lanes;
> +	u32 control = 0;
> +	int ret;
> +
> +	if (lanes < 1 || lanes > 4)
> +		return -EINVAL;
> +
> +	/* set mult and div to 0, thus completely rely on V4L2_CID_LINK_FREQ */
> +	link_freq = v4l2_get_link_freq(source_pad, 0, 0);
> +	if (link_freq <= 0)
> +		return -EINVAL;
> +
> +	if (bus_type == V4L2_MBUS_CSI2_DPHY) {
> +		struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
> +
> +		ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq * 2,
> +								 lanes, cfg);
> +		if (ret)
> +			return ret;
> +
> +		ret = phy_set_mode(csi_dev->phy, PHY_MODE_MIPI_DPHY);
> +		if (ret)
> +			return ret;
> +
> +		ret = phy_configure(csi_dev->phy, &opts);
> +		if (ret)
> +			return ret;
> +
> +		control |= SW_CPHY_EN(0);
> +
> +	} else if (bus_type == V4L2_MBUS_CSI2_CPHY) {
> +		/* TODO: implement CPHY configuration */
> +		return -EOPNOTSUPP;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	control |= SW_DATATYPE_FS(0x00) | SW_DATATYPE_FE(0x01) |
> +		   SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03);
> +
> +	rkcsi_write(csi_dev, CSI2HOST_N_LANES, lanes - 1);
> +	rkcsi_write(csi_dev, CSI2HOST_CONTROL, control);
> +	rkcsi_write(csi_dev, CSI2HOST_CSI2_RESETN, 1);
> +
> +	ret = phy_power_on(csi_dev->phy);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static void rkcsi_stop(struct rkcsi_device *csi_dev)
> +{
> +	phy_power_off(csi_dev->phy);
> +
> +	rkcsi_write(csi_dev, CSI2HOST_CSI2_RESETN, 0);
> +	rkcsi_write(csi_dev, CSI2HOST_MSK1, ~0);
> +	rkcsi_write(csi_dev, CSI2HOST_MSK2, ~0);
> +}
> +
> +static const struct media_entity_operations rkcsi_media_ops = {
> +	.link_validate = v4l2_subdev_link_validate,
> +};
> +
> +static int rkcsi_enum_mbus_code(struct v4l2_subdev *sd,
> +				struct v4l2_subdev_state *sd_state,
> +				struct v4l2_subdev_mbus_code_enum *code)
> +{
> +	struct rkcsi_device *csi_dev = to_rkcsi(sd);
> +
> +	if (code->pad == RKCSI_PAD_SRC) {
> +		const struct v4l2_mbus_framefmt *sink_fmt;
> +
> +		if (code->index)
> +			return -EINVAL;
> +
> +		sink_fmt = v4l2_subdev_state_get_format(sd_state,
> +							RKCSI_PAD_SINK);
> +		code->code = sink_fmt->code;
> +
> +		return 0;
> +	} else if (code->pad == RKCSI_PAD_SINK) {
> +		if (code->index > csi_dev->formats_num)
> +			return -EINVAL;
> +
> +		code->code = csi_dev->formats[code->index].code;
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int rkcsi_set_fmt(struct v4l2_subdev *sd,
> +			 struct v4l2_subdev_state *state,
> +			 struct v4l2_subdev_format *format)
> +{
> +	struct rkcsi_device *csi_dev = to_rkcsi(sd);
> +	const struct rkcsi_format *fmt;
> +	struct v4l2_mbus_framefmt *sink, *src;
> +
> +	/* the format on the source pad always matches the sink pad */
> +	if (format->pad == RKCSI_PAD_SRC)
> +		return v4l2_subdev_get_fmt(sd, state, format);
> +
> +	sink = v4l2_subdev_state_get_format(state, format->pad, format->stream);
> +	if (!sink)
> +		return -EINVAL;
> +
> +	fmt = rkcsi_find_format(csi_dev, format->format.code);
> +	if (!fmt)
> +		format->format = default_format;
> +
> +	*sink = format->format;
> +
> +	/* propagate the format to the source pad */
> +	src = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
> +							   format->stream);
> +	if (!src)
> +		return -EINVAL;
> +
> +	*src = *sink;
> +
> +	return 0;
> +}
> +
> +static int rkcsi_set_routing(struct v4l2_subdev *sd,
> +			     struct v4l2_subdev_state *state,
> +			     enum v4l2_subdev_format_whence which,
> +			     struct v4l2_subdev_krouting *routing)
> +{
> +	int ret;
> +
> +	ret = v4l2_subdev_routing_validate(sd, routing,
> +					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
> +	if (ret)
> +		return ret;
> +
> +	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing,
> +					       &default_format);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int rkcsi_enable_streams(struct v4l2_subdev *sd,
> +				struct v4l2_subdev_state *state, u32 pad,
> +				u64 streams_mask)
> +{
> +	struct rkcsi_device *csi_dev = to_rkcsi(sd);
> +	struct v4l2_subdev *remote_sd;
> +	struct media_pad *sink_pad, *remote_pad;
> +	struct device *dev = csi_dev->dev;
> +	u64 mask;
> +	int ret;
> +
> +	sink_pad = &sd->entity.pads[RKCSI_PAD_SINK];
> +	remote_pad = media_pad_remote_pad_first(sink_pad);
> +	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
> +
> +	mask = v4l2_subdev_state_xlate_streams(state, RKCSI_PAD_SINK,
> +					       RKCSI_PAD_SRC, &streams_mask);
> +
> +	ret = pm_runtime_resume_and_get(dev);
> +	if (ret)
> +		goto err;
> +
> +	ret = rkcsi_start(csi_dev);
> +	if (ret) {
> +		dev_err(dev, "failed to enable CSI hardware\n");
> +		goto err_pm_runtime_put;
> +	}
> +
> +	ret = v4l2_subdev_enable_streams(remote_sd, remote_pad->index, mask);
> +	if (ret)
> +		goto err_csi_stop;
> +
> +	return 0;
> +
> +err_csi_stop:
> +	rkcsi_stop(csi_dev);
> +err_pm_runtime_put:
> +	pm_runtime_put_sync(dev);
> +err:
> +	return ret;
> +}
> +
> +static int rkcsi_disable_streams(struct v4l2_subdev *sd,
> +				 struct v4l2_subdev_state *state, u32 pad,
> +				 u64 streams_mask)
> +{
> +	struct rkcsi_device *csi_dev = to_rkcsi(sd);
> +	struct v4l2_subdev *remote_sd;
> +	struct media_pad *sink_pad, *remote_pad;
> +	struct device *dev = csi_dev->dev;
> +	u64 mask;
> +	int ret;
> +
> +	sink_pad = &sd->entity.pads[RKCSI_PAD_SINK];
> +	remote_pad = media_pad_remote_pad_first(sink_pad);
> +	remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity);
> +
> +	mask = v4l2_subdev_state_xlate_streams(state, RKCSI_PAD_SINK,
> +					       RKCSI_PAD_SRC, &streams_mask);
> +
> +	ret = v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
> +
> +	rkcsi_stop(csi_dev);
> +
> +	pm_runtime_mark_last_busy(dev);
> +	pm_runtime_put_autosuspend(dev);
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_subdev_pad_ops rkcsi_pad_ops = {
> +	.enum_mbus_code = rkcsi_enum_mbus_code,
> +	.get_fmt = v4l2_subdev_get_fmt,
> +	.set_fmt = rkcsi_set_fmt,
> +	.set_routing = rkcsi_set_routing,
> +	.enable_streams = rkcsi_enable_streams,
> +	.disable_streams = rkcsi_disable_streams,
> +};
> +
> +static const struct v4l2_subdev_ops rkcsi_ops = {
> +	.pad = &rkcsi_pad_ops,
> +};
> +
> +static int rkcsi_init_state(struct v4l2_subdev *sd,
> +			    struct v4l2_subdev_state *state)
> +{
> +	struct v4l2_subdev_route routes[] = {
> +		{
> +			.sink_pad = RKCSI_PAD_SINK,
> +			.sink_stream = 0,
> +			.source_pad = RKCSI_PAD_SRC,
> +			.source_stream = 0,
> +			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
> +		},
> +	};
> +	struct v4l2_subdev_krouting routing = {
> +		.len_routes = ARRAY_SIZE(routes),
> +		.num_routes = ARRAY_SIZE(routes),
> +		.routes = routes,
> +	};
> +	int ret;
> +
> +	ret = v4l2_subdev_set_routing_with_fmt(sd, state, &routing,
> +					       &default_format);
> +
> +	return ret;
> +}
> +
> +static const struct v4l2_subdev_internal_ops rkcsi_internal_ops = {
> +	.init_state = rkcsi_init_state,
> +};
> +
> +static int rkcsi_notifier_bound(struct v4l2_async_notifier *notifier,
> +				struct v4l2_subdev *sd,
> +				struct v4l2_async_connection *asd)
> +{
> +	struct rkcsi_device *csi_dev =
> +		container_of(notifier, struct rkcsi_device, notifier);
> +	int source_pad;
> +
> +	source_pad = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode,
> +						 MEDIA_PAD_FL_SOURCE);
> +	if (source_pad < 0) {
> +		dev_err(csi_dev->dev, "failed to find source pad for %s\n",
> +			sd->name);
> +		return source_pad;
> +	}
> +
> +	csi_dev->source_sd = sd;
> +	csi_dev->source_pad = source_pad;
> +
> +	return media_create_pad_link(&sd->entity, source_pad,
> +				     &csi_dev->sd.entity, RKCSI_PAD_SINK,
> +				     MEDIA_LNK_FL_ENABLED);
> +}
> +
> +static const struct v4l2_async_notifier_operations rkcsi_notifier_ops = {
> +	.bound = rkcsi_notifier_bound,
> +};
> +
> +static int rkcsi_register_notifier(struct rkcsi_device *csi_dev)
> +{
> +	struct v4l2_async_connection *asd;
> +	struct v4l2_async_notifier *ntf = &csi_dev->notifier;
> +	struct v4l2_fwnode_endpoint *vep = &csi_dev->vep;
> +	struct v4l2_subdev *sd = &csi_dev->sd;
> +	struct device *dev = csi_dev->dev;
> +	struct fwnode_handle *ep;
> +	int ret = 0;
> +
> +	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
> +	if (!ep)
> +		return dev_err_probe(dev, -ENODEV, "failed to get endpoint\n");
> +
> +	vep->bus_type = V4L2_MBUS_UNKNOWN;
> +	ret = v4l2_fwnode_endpoint_parse(ep, vep);
> +	if (ret) {
> +		ret = dev_err_probe(dev, ret, "failed to parse endpoint\n");
> +		goto out;
> +	}
> +
> +	if (vep->bus_type != V4L2_MBUS_CSI2_DPHY &&
> +	    vep->bus_type != V4L2_MBUS_CSI2_CPHY) {
> +		ret = dev_err_probe(dev, -EINVAL,
> +				    "invalid bus type of endpoint\n");
> +		goto out;
> +	}
> +
> +	v4l2_async_subdev_nf_init(ntf, sd);
> +	ntf->ops = &rkcsi_notifier_ops;
> +
> +	asd = v4l2_async_nf_add_fwnode_remote(ntf, ep,
> +					      struct v4l2_async_connection);
> +	if (IS_ERR(asd)) {
> +		ret = PTR_ERR(asd);
> +		goto err_nf_cleanup;
> +	}
> +
> +	ret = v4l2_async_nf_register(ntf);
> +	if (ret) {
> +		ret = dev_err_probe(dev, ret, "failed to register notifier\n");
> +		goto err_nf_cleanup;
> +	}
> +
> +	goto out;
> +
> +err_nf_cleanup:
> +	v4l2_async_nf_cleanup(ntf);
> +out:
> +	fwnode_handle_put(ep);
> +	return ret;
> +}
> +
> +static int rkcsi_register(struct rkcsi_device *csi_dev)
> +{
> +	struct media_pad *pads = csi_dev->pads;
> +	struct v4l2_subdev *sd = &csi_dev->sd;
> +	int ret;
> +
> +	ret = rkcsi_register_notifier(csi_dev);
> +	if (ret)
> +		goto err;
> +
> +	v4l2_subdev_init(sd, &rkcsi_ops);
> +	sd->dev = csi_dev->dev;
> +	sd->entity.ops = &rkcsi_media_ops;
> +	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
> +	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
> +	sd->internal_ops = &rkcsi_internal_ops;
> +	sd->owner = THIS_MODULE;
> +	snprintf(sd->name, sizeof(sd->name), "rockchip-mipi-csi %s",
> +		 dev_name(csi_dev->dev));
> +
> +	pads[RKCSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK |
> +				     MEDIA_PAD_FL_MUST_CONNECT;
> +	pads[RKCSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
> +	ret = media_entity_pads_init(&sd->entity, RKCSI_PAD_MAX, pads);
> +	if (ret)
> +		goto err_notifier_unregister;
> +
> +	ret = v4l2_subdev_init_finalize(sd);
> +	if (ret)
> +		goto err_entity_cleanup;
> +
> +	ret = v4l2_async_register_subdev(sd);
> +	if (ret) {
> +		dev_err(sd->dev, "failed to register CSI subdev\n");
> +		goto err_subdev_cleanup;
> +	}
> +
> +	return 0;
> +
> +err_subdev_cleanup:
> +	v4l2_subdev_cleanup(sd);
> +err_entity_cleanup:
> +	media_entity_cleanup(&sd->entity);
> +err_notifier_unregister:
> +	v4l2_async_nf_unregister(&csi_dev->notifier);
> +	v4l2_async_nf_cleanup(&csi_dev->notifier);
> +err:
> +	return ret;
> +}
> +
> +static void rkcsi_unregister(struct rkcsi_device *csi_dev)
> +{
> +	struct v4l2_subdev *sd = &csi_dev->sd;
> +
> +	v4l2_async_unregister_subdev(sd);
> +	v4l2_subdev_cleanup(sd);
> +	media_entity_cleanup(&sd->entity);
> +	v4l2_async_nf_unregister(&csi_dev->notifier);
> +	v4l2_async_nf_cleanup(&csi_dev->notifier);
> +}
> +
> +static const struct of_device_id rkcsi_of_match[] = {
> +	{
> +		.compatible = "rockchip,rk3568-mipi-csi",
> +	},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, rkcsi_of_match);
> +
> +static int rkcsi_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct rkcsi_device *csi_dev;
> +	int ret;
> +
> +	csi_dev = devm_kzalloc(dev, sizeof(*csi_dev), GFP_KERNEL);
> +	if (!csi_dev)
> +		return -ENOMEM;
> +	csi_dev->dev = dev;
> +	dev_set_drvdata(dev, csi_dev);
> +
> +	csi_dev->base_addr = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(csi_dev->base_addr))
> +		return PTR_ERR(csi_dev->base_addr);
> +
> +	ret = devm_clk_bulk_get_all(dev, &csi_dev->clks);
> +	if (ret != RKCSI_CLKS_MAX)
> +		return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
> +	csi_dev->clks_num = ret;
> +
> +	csi_dev->phy = devm_phy_get(dev, NULL);
> +	if (IS_ERR(csi_dev->phy))
> +		return dev_err_probe(dev, PTR_ERR(csi_dev->phy),
> +				     "failed to get MIPI CSI PHY\n");
> +
> +	csi_dev->reset = devm_reset_control_get_exclusive(dev, NULL);
> +	if (IS_ERR(csi_dev->reset))
> +		return dev_err_probe(dev, PTR_ERR(csi_dev->reset),
> +				     "failed to get reset\n");
> +
> +	csi_dev->formats = formats;
> +	csi_dev->formats_num = ARRAY_SIZE(formats);
> +
> +	pm_runtime_enable(dev);
> +
> +	ret = phy_init(csi_dev->phy);
> +	if (ret) {
> +		ret = dev_err_probe(dev, ret,
> +				    "failed to initialize MIPI CSI PHY\n");
> +		goto err_pm_runtime_disable;
> +	}
> +
> +	ret = rkcsi_register(csi_dev);
> +	if (ret)
> +		goto err_phy_exit;
> +
> +	return 0;
> +
> +err_phy_exit:
> +	phy_exit(csi_dev->phy);
> +err_pm_runtime_disable:
> +	pm_runtime_disable(dev);
> +	return ret;
> +}
> +
> +static void rkcsi_remove(struct platform_device *pdev)
> +{
> +	struct rkcsi_device *csi_dev = platform_get_drvdata(pdev);
> +	struct device *dev = &pdev->dev;
> +
> +	rkcsi_unregister(csi_dev);
> +	phy_exit(csi_dev->phy);
> +	pm_runtime_disable(dev);
> +}
> +
> +static int rkcsi_runtime_suspend(struct device *dev)
> +{
> +	struct rkcsi_device *csi_dev = dev_get_drvdata(dev);
> +
> +	clk_bulk_disable_unprepare(csi_dev->clks_num, csi_dev->clks);
> +
> +	return 0;
> +}
> +
> +static int rkcsi_runtime_resume(struct device *dev)
> +{
> +	struct rkcsi_device *csi_dev = dev_get_drvdata(dev);
> +	int ret;
> +
> +	reset_control_assert(csi_dev->reset);
> +	udelay(5);
> +	reset_control_deassert(csi_dev->reset);
> +
> +	ret = clk_bulk_prepare_enable(csi_dev->clks_num, csi_dev->clks);
> +	if (ret) {
> +		dev_err(dev, "failed to enable clocks\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops rkcsi_pm_ops = {
> +	.runtime_suspend = rkcsi_runtime_suspend,
> +	.runtime_resume = rkcsi_runtime_resume,
> +};
> +
> +static struct platform_driver rkcsi_drv = {
> +	.driver = {
> +		   .name = "rockchip-mipi-csi",
> +		   .of_match_table = rkcsi_of_match,
> +		   .pm = &rkcsi_pm_ops,
> +	},
> +	.probe = rkcsi_probe,
> +	.remove = rkcsi_remove,
> +};
> +module_platform_driver(rkcsi_drv);
> +
> +MODULE_DESCRIPTION("Rockchip MIPI CSI-2 Receiver platform driver");
> +MODULE_LICENSE("GPL");
>
> --
> 2.39.5
>
>


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

* Re: [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-11-18 17:15   ` Frank Li
@ 2025-11-18 18:59     ` Michael Riesch
  2025-11-18 22:08       ` Frank Li
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Riesch @ 2025-11-18 18:59 UTC (permalink / raw)
  To: Frank Li
  Cc: Mehdi Djait, Bryan O'Donoghue, Laurent Pinchart, Hans Verkuil,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Philipp Zabel, Sebastian Reichel,
	Nicolas Dufresne, Collabora Kernel Team, Sakari Ailus,
	linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

Hi Frank,

On 11/18/25 18:15, Frank Li wrote:
> On Tue, Nov 18, 2025 at 12:12:26PM +0100, Michael Riesch via B4 Relay wrote:
>> From: Michael Riesch <michael.riesch@collabora.com>
>>
>>[...]
>> +#define CSI2HOST_N_LANES     0x04
>> +#define CSI2HOST_CSI2_RESETN 0x10
>> +#define CSI2HOST_PHY_STATE   0x14
>> +#define CSI2HOST_ERR1	     0x20
>> +#define CSI2HOST_ERR2	     0x24
>> +#define CSI2HOST_MSK1	     0x28
>> +#define CSI2HOST_MSK2	     0x2c
>> +#define CSI2HOST_CONTROL     0x40
> 
> Look like that is designware CSI2 controller, can we build common library
> for all dwc csi2 controller, instead of every vendor create individual one.
> 
> First try at
> https://lore.kernel.org/linux-media/20250821-95_cam-v3-21-c9286fbb34b9@nxp.com/
> 
> Toshiba have similar patch
> https://lore.kernel.org/linux-media/aPZd39riAxqfw3mT@lizhi-Precision-Tower-5810/
> 
> Frank

This has been discussed already a while ago:
https://lore.kernel.org/all/20250507083837.GA11152@pendragon.ideasonboard.com/

Bottom line from Laurent:

"Let's keep this driver Rockchip-specific then. Thanks for checking."

>  [...]
Best regards,
Michael


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

* Re: [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-11-18 18:59     ` Michael Riesch
@ 2025-11-18 22:08       ` Frank Li
  2025-11-26 20:57         ` Michael Riesch
  0 siblings, 1 reply; 10+ messages in thread
From: Frank Li @ 2025-11-18 22:08 UTC (permalink / raw)
  To: Michael Riesch
  Cc: Mehdi Djait, Bryan O'Donoghue, Laurent Pinchart, Hans Verkuil,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Philipp Zabel, Sebastian Reichel,
	Nicolas Dufresne, Collabora Kernel Team, Sakari Ailus,
	linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

On Tue, Nov 18, 2025 at 07:59:14PM +0100, Michael Riesch wrote:
> Hi Frank,
>
> On 11/18/25 18:15, Frank Li wrote:
> > On Tue, Nov 18, 2025 at 12:12:26PM +0100, Michael Riesch via B4 Relay wrote:
> >> From: Michael Riesch <michael.riesch@collabora.com>
> >>
> >>[...]
> >> +#define CSI2HOST_N_LANES     0x04
> >> +#define CSI2HOST_CSI2_RESETN 0x10
> >> +#define CSI2HOST_PHY_STATE   0x14
> >> +#define CSI2HOST_ERR1	     0x20
> >> +#define CSI2HOST_ERR2	     0x24
> >> +#define CSI2HOST_MSK1	     0x28
> >> +#define CSI2HOST_MSK2	     0x2c
> >> +#define CSI2HOST_CONTROL     0x40
> >
> > Look like that is designware CSI2 controller, can we build common library
> > for all dwc csi2 controller, instead of every vendor create individual one.
> >
> > First try at
> > https://lore.kernel.org/linux-media/20250821-95_cam-v3-21-c9286fbb34b9@nxp.com/
> >
> > Toshiba have similar patch
> > https://lore.kernel.org/linux-media/aPZd39riAxqfw3mT@lizhi-Precision-Tower-5810/
> >
> > Frank
>
> This has been discussed already a while ago:
> https://lore.kernel.org/all/20250507083837.GA11152@pendragon.ideasonboard.com/

https://lore.kernel.org/all/20250702093806.GF16835@pendragon.ideasonboard.com/

Laurent Pinchart prevent imx93 DWC CSI2 driver at Jul, your discussion at
May, I think Laurent Pinchart change the mind.

We can choose not base on imx6, but we should create a standard dwc2 under
drivers/media/platform/synopsys/

Laurent Pinchart:

	Can you provide direction?

Frank

>
> Bottom line from Laurent:
>
> "Let's keep this driver Rockchip-specific then. Thanks for checking."
>
> >  [...]
> Best regards,
> Michael


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

* Re: [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-11-18 22:08       ` Frank Li
@ 2025-11-26 20:57         ` Michael Riesch
  2025-12-01  3:37           ` Laurent Pinchart
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Riesch @ 2025-11-26 20:57 UTC (permalink / raw)
  To: Frank Li
  Cc: Mehdi Djait, Bryan O'Donoghue, Laurent Pinchart, Hans Verkuil,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Philipp Zabel, Sebastian Reichel,
	Nicolas Dufresne, Collabora Kernel Team, Sakari Ailus,
	linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

Hi Frank,

On 11/18/25 23:08, Frank Li wrote:
> On Tue, Nov 18, 2025 at 07:59:14PM +0100, Michael Riesch wrote:
>> Hi Frank,
>>
>> On 11/18/25 18:15, Frank Li wrote:
>>> On Tue, Nov 18, 2025 at 12:12:26PM +0100, Michael Riesch via B4 Relay wrote:
>>>> From: Michael Riesch <michael.riesch@collabora.com>
>>>>
>>>> [...]
>>>> +#define CSI2HOST_N_LANES     0x04
>>>> +#define CSI2HOST_CSI2_RESETN 0x10
>>>> +#define CSI2HOST_PHY_STATE   0x14
>>>> +#define CSI2HOST_ERR1	     0x20
>>>> +#define CSI2HOST_ERR2	     0x24
>>>> +#define CSI2HOST_MSK1	     0x28
>>>> +#define CSI2HOST_MSK2	     0x2c
>>>> +#define CSI2HOST_CONTROL     0x40
>>>
>>> Look like that is designware CSI2 controller, can we build common library
>>> for all dwc csi2 controller, instead of every vendor create individual one.
>>>
>>> First try at
>>> https://lore.kernel.org/linux-media/20250821-95_cam-v3-21-c9286fbb34b9@nxp.com/
>>>
>>> Toshiba have similar patch
>>> https://lore.kernel.org/linux-media/aPZd39riAxqfw3mT@lizhi-Precision-Tower-5810/
>>>
>>> Frank
>>
>> This has been discussed already a while ago:
>> https://lore.kernel.org/all/20250507083837.GA11152@pendragon.ideasonboard.com/
> 
> https://lore.kernel.org/all/20250702093806.GF16835@pendragon.ideasonboard.com/
> 
> Laurent Pinchart prevent imx93 DWC CSI2 driver at Jul, your discussion at
> May, I think Laurent Pinchart change the mind.
> 
> We can choose not base on imx6, but we should create a standard dwc2 under
> drivers/media/platform/synopsys/

In principle, I agree with refactoring out common code. However, I am
not sure how similar these IP cores really are. Again, the answer I
received from Rockchip states that this is *not* a Synopsys IP core.

Can you maybe test whether the Rockchip MIPI CSI-2 Receiver driver in
this series works on your hardware? Then we will know if (and what)
parts can be shared.

Best regards,
Michael


> 
> Laurent Pinchart:
> 
> 	Can you provide direction?
> 
> Frank
> 
>>
>> Bottom line from Laurent:
>>
>> "Let's keep this driver Rockchip-specific then. Thanks for checking."
>>
>>>  [...]
>> Best regards,
>> Michael



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

* Re: [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-11-26 20:57         ` Michael Riesch
@ 2025-12-01  3:37           ` Laurent Pinchart
  2025-12-01 17:59             ` Frank Li
  0 siblings, 1 reply; 10+ messages in thread
From: Laurent Pinchart @ 2025-12-01  3:37 UTC (permalink / raw)
  To: Michael Riesch
  Cc: Frank Li, Mehdi Djait, Bryan O'Donoghue, Hans Verkuil,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Philipp Zabel, Sebastian Reichel,
	Nicolas Dufresne, Collabora Kernel Team, Sakari Ailus,
	linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

Hello,

On Wed, Nov 26, 2025 at 09:57:31PM +0100, Michael Riesch wrote:
> On 11/18/25 23:08, Frank Li wrote:
> > On Tue, Nov 18, 2025 at 07:59:14PM +0100, Michael Riesch wrote:
> >> On 11/18/25 18:15, Frank Li wrote:
> >>> On Tue, Nov 18, 2025 at 12:12:26PM +0100, Michael Riesch via B4 Relay wrote:
> >>>> From: Michael Riesch <michael.riesch@collabora.com>
> >>>>
> >>>> [...]
> >>>> +#define CSI2HOST_N_LANES     0x04
> >>>> +#define CSI2HOST_CSI2_RESETN 0x10
> >>>> +#define CSI2HOST_PHY_STATE   0x14
> >>>> +#define CSI2HOST_ERR1	     0x20
> >>>> +#define CSI2HOST_ERR2	     0x24
> >>>> +#define CSI2HOST_MSK1	     0x28
> >>>> +#define CSI2HOST_MSK2	     0x2c
> >>>> +#define CSI2HOST_CONTROL     0x40
> >>>
> >>> Look like that is designware CSI2 controller, can we build common library
> >>> for all dwc csi2 controller, instead of every vendor create individual one.
> >>>
> >>> First try at
> >>> https://lore.kernel.org/linux-media/20250821-95_cam-v3-21-c9286fbb34b9@nxp.com/
> >>>
> >>> Toshiba have similar patch
> >>> https://lore.kernel.org/linux-media/aPZd39riAxqfw3mT@lizhi-Precision-Tower-5810/
> >>>
> >>> Frank
> >>
> >> This has been discussed already a while ago:
> >> https://lore.kernel.org/all/20250507083837.GA11152@pendragon.ideasonboard.com/
> > 
> > https://lore.kernel.org/all/20250702093806.GF16835@pendragon.ideasonboard.com/
> > 
> > Laurent Pinchart prevent imx93 DWC CSI2 driver at Jul, your discussion at
> > May, I think Laurent Pinchart change the mind.
> > 
> > We can choose not base on imx6, but we should create a standard dwc2 under
> > drivers/media/platform/synopsys/
> 
> In principle, I agree with refactoring out common code. However, I am
> not sure how similar these IP cores really are. Again, the answer I
> received from Rockchip states that this is *not* a Synopsys IP core.

That's what I based my opinion on. If we're dealing with different IP
cores from different vendors, we can have separate drivers. Even within
the family of CSI-2 receivers from Synopsys, I'm fine having different
drivers if the version differ significantly enough that using a single
driver would cause more pain than gain.

To explain this differently, for Synopsys CSI-2 receivers, I would like
to try and support multiple IP cores integrated in different SoCs in a
single driver. If, during that development, we find good reasons to use
separate drivers, then we can do so.

> Can you maybe test whether the Rockchip MIPI CSI-2 Receiver driver in
> this series works on your hardware? Then we will know if (and what)
> parts can be shared.
> 
> > Laurent Pinchart:
> > 
> > 	Can you provide direction?
> > 
> >> Bottom line from Laurent:
> >>
> >> "Let's keep this driver Rockchip-specific then. Thanks for checking."
> >>
> >>>  [...]

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH v2 2/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver
  2025-12-01  3:37           ` Laurent Pinchart
@ 2025-12-01 17:59             ` Frank Li
  0 siblings, 0 replies; 10+ messages in thread
From: Frank Li @ 2025-12-01 17:59 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Michael Riesch, Mehdi Djait, Bryan O'Donoghue, Hans Verkuil,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Heiko Stuebner, Philipp Zabel, Sebastian Reichel,
	Nicolas Dufresne, Collabora Kernel Team, Sakari Ailus,
	linux-media, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel

On Mon, Dec 01, 2025 at 12:37:00PM +0900, Laurent Pinchart wrote:
> Hello,
>
> On Wed, Nov 26, 2025 at 09:57:31PM +0100, Michael Riesch wrote:
> > On 11/18/25 23:08, Frank Li wrote:
> > > On Tue, Nov 18, 2025 at 07:59:14PM +0100, Michael Riesch wrote:
> > >> On 11/18/25 18:15, Frank Li wrote:
> > >>> On Tue, Nov 18, 2025 at 12:12:26PM +0100, Michael Riesch via B4 Relay wrote:
> > >>>> From: Michael Riesch <michael.riesch@collabora.com>
> > >>>>
> > >>>> [...]
> > >>>> +#define CSI2HOST_N_LANES     0x04
> > >>>> +#define CSI2HOST_CSI2_RESETN 0x10
> > >>>> +#define CSI2HOST_PHY_STATE   0x14
> > >>>> +#define CSI2HOST_ERR1	     0x20
> > >>>> +#define CSI2HOST_ERR2	     0x24
> > >>>> +#define CSI2HOST_MSK1	     0x28
> > >>>> +#define CSI2HOST_MSK2	     0x2c
> > >>>> +#define CSI2HOST_CONTROL     0x40
> > >>>
> > >>> Look like that is designware CSI2 controller, can we build common library
> > >>> for all dwc csi2 controller, instead of every vendor create individual one.
> > >>>
> > >>> First try at
> > >>> https://lore.kernel.org/linux-media/20250821-95_cam-v3-21-c9286fbb34b9@nxp.com/
> > >>>
> > >>> Toshiba have similar patch
> > >>> https://lore.kernel.org/linux-media/aPZd39riAxqfw3mT@lizhi-Precision-Tower-5810/
> > >>>
> > >>> Frank
> > >>
> > >> This has been discussed already a while ago:
> > >> https://lore.kernel.org/all/20250507083837.GA11152@pendragon.ideasonboard.com/
> > >
> > > https://lore.kernel.org/all/20250702093806.GF16835@pendragon.ideasonboard.com/
> > >
> > > Laurent Pinchart prevent imx93 DWC CSI2 driver at Jul, your discussion at
> > > May, I think Laurent Pinchart change the mind.
> > >
> > > We can choose not base on imx6, but we should create a standard dwc2 under
> > > drivers/media/platform/synopsys/
> >
> > In principle, I agree with refactoring out common code. However, I am
> > not sure how similar these IP cores really are. Again, the answer I
> > received from Rockchip states that this is *not* a Synopsys IP core.
>
> That's what I based my opinion on. If we're dealing with different IP
> cores from different vendors, we can have separate drivers. Even within
> the family of CSI-2 receivers from Synopsys, I'm fine having different
> drivers if the version differ significantly enough that using a single
> driver would cause more pain than gain.

Laurent Pinchart:

	We need use unified standard for every one. In the patch below patch
is enough show the difference between Sysnopsys version.

media: synopsys: csi2: Add basic v150* version register
https://lore.kernel.org/imx/20250821-95_cam-v3-20-c9286fbb34b9@nxp.com/

	The register layout is differense, most field defination are the
same and some changed.

	I know it is hard to define how much pain and gain.

	But I think this one is closer to imx6's version even though they
claim NOT DWC CSI2 IP than imx93 v150 dwc CSI2 version. (for example, many
iio sensor/gpio expandor use the same set of register define for difference
vendor, but still use one driver for these).

https://lore.kernel.org/all/20250702093806.GF16835@pendragon.ideasonboard.com/#t

"This seems to be at least the third instance of a driver for the CSI-2
receiver, the first two being
drivers/media/platform/raspberrypi/rp1-cfe/dphy.c and the second one
drivers/media/platform/renesas/rcar-csi2.c (the latter seems to support
multiple CSI-2 receivers). drivers/staging/media/imx/imx6-mipi-csi2.c
seem related too, likely for an old version of the IP.

Could we please try to avoid code duplication ?
"

	Or do you think I should go through this ways (direct create one
dwc for v150) instead base on imx6 one to enable imx93's dwc CSI2?

>
> To explain this differently, for Synopsys CSI-2 receivers, I would like
> to try and support multiple IP cores integrated in different SoCs in a
> single driver. If, during that development, we find good reasons to use
> separate drivers, then we can do so.

I think if reviewing and landing process could go through smooth, imx6 can
support this device with a little bit modify. There are not technology's
bar so far.

I split to more simple patches from big 32 patch serises.

https://lore.kernel.org/imx/20251111-stage-csi2-cleanup-v2-0-371bb951776f@nxp.com/

Only comments change

https://lore.kernel.org/linux-media/20251105195808.297645-1-Frank.Li@nxp.com/

Frank

>
> > Can you maybe test whether the Rockchip MIPI CSI-2 Receiver driver in
> > this series works on your hardware? Then we will know if (and what)
> > parts can be shared.
> >
> > > Laurent Pinchart:
> > >
> > > 	Can you provide direction?
> > >
> > >> Bottom line from Laurent:
> > >>
> > >> "Let's keep this driver Rockchip-specific then. Thanks for checking."
> > >>
> > >>>  [...]
>
> --
> Regards,
>
> Laurent Pinchart


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

end of thread, other threads:[~2025-12-01 17:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-18 11:12 [PATCH v2 0/3] media: rockchip: add driver for the rockchip mipi csi-2 receiver Michael Riesch via B4 Relay
2025-11-18 11:12 ` [PATCH v2 1/3] media: dt-bindings: add " Michael Riesch via B4 Relay
2025-11-18 11:12 ` [PATCH v2 2/3] media: rockchip: add driver for the " Michael Riesch via B4 Relay
2025-11-18 17:15   ` Frank Li
2025-11-18 18:59     ` Michael Riesch
2025-11-18 22:08       ` Frank Li
2025-11-26 20:57         ` Michael Riesch
2025-12-01  3:37           ` Laurent Pinchart
2025-12-01 17:59             ` Frank Li
2025-11-18 11:12 ` [PATCH v2 3/3] arm64: defconfig: enable " Michael Riesch via B4 Relay

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