imx.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/32] media: add imx93 mipi/controller csi support
@ 2025-08-08 22:39 Frank Li
  2025-08-08 22:39 ` [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support Frank Li
                   ` (32 more replies)
  0 siblings, 33 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li, Luis Oliveira

Totally rewrite CSI part driver compared to V1.

This only includes CSI related patches.

DTS part: see https://lore.kernel.org/imx/20250701-95_cam-v1-6-c5172bab387b@nxp.com/
PHY part: see https://lore.kernel.org/imx/20250701-95_cam-v1-4-c5172bab387b@nxp.com/
AP1302 part: see https://lore.kernel.org/imx/20250701-95_cam-v1-7-c5172bab387b@nxp.com/
	upstream: https://lore.kernel.org/imx/20250623-ap1302-v3-0-c9ca5b791494@nxp.com/

First 3 patches add some common helper function to simple code and remove
duplicated code in difference CSI2 drivers.

Clean up stage imx6 old version csi2 driver, and prepare create common
dw csi2 library for difference IP version.

Move stage driver under driver/media/synosis.

Create simple platform driver for common dw csi2 use case.

TODO:
	1. create bus, to probe phy driver under "test_if" interface for
specific phys under CSI2.
	2. support to combine phy, (which connect to both dw CSI and DSI's
test_if). Need use DSI's test_if to config combo phy to switch to RX mode.
and also need config RX part's phy register by use CSI's testif.
	3. move other vendor's csi driver to use this common DWC CSI
library.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v2:
- totally rewrite, see above section
- Link to v1: https://lore.kernel.org/r/20250701-95_cam-v1-0-c5172bab387b@nxp.com

---
Eugen Hristev (1):
      dt-bindings: media: add DW MIPI CSI-2 Host support

Frank Li (31):
      media: v4l2-common: Add helper function v4l_get_required_align_by_bpp()
      media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp()
      media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt()
      media: staging: media: imx6-mipi-csi2: replace space with tab for alignment
      media: staging: media: imx6-mipi-csi2: use devm_add_action_or_reset() to simplify code
      media: staging: media: imx6-mipi-csi2: use devm_clk_bulk_get_all() to fetch clocks
      media: staging: media: imx6-mipi-csi2: use devm_mutex_init() to simplify code
      media: staging: media: imx6-mipi-csi2: use guard() to simplify code
      media: staging: media: imx6-mipi-csi2: use register structure to match hardware
      media: staging: media: imx6-mipi-csi2: use devm_platform_ioremap_resource() simplify code
      media: staging: media: imx6-mipi-csi2: move probe part to imx6-csi2.c
      media: staging: media: imx6-mipi-csi2: move sd imx6's specific initialization into imx6-sci2.c
      media: staging: media: imx6-mipi-csi2: move csi2ipu_gasket_init() to imx6-csi2.c
      media: staging: media: imx6-mipi-csi2: move number pad macro define into imx6-csi2.c
      media: staging: media: imx6-mipi-csi2: move dphy init part to imx6-csi2.c
      media: staging: media: imx6-mipi-csi2: use runtime_pm frame to control clks
      media: synopsys: move imx6-mipi-csi2.c to synopsys/mipi-csi2.c
      media: synopsys: csi2: Remove deprecated s_stream and use v4l2_subdev_pad_ops
      media: synopsys: csi2: Add phy interface support
      media: synopsys: csi2: Add basic v150* version register
      media: synopsys: csi2: Add irq support to record error count
      media: synopsys: csi2: Handle alignment requirement for width
      media: synopsys: csi2: Add register prefix to register field definitions
      media: synopsys: csi2: Add need_dphy_reset in config
      media: synopsys: csi2: Add default simple dw_csi2_subdev_init_state
      media: synopsys: csi2: Add v150 lane stop state register bit define
      media: synopsys: csi2: use standard v4l2_subdev_get_fmt() function
      media: synopsys: csi2: Add customize get_frame_desc() callback
      media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150
      media: synopsys: csi2: Remove source pad connected check at dw_csi2_enable_streams()
      media: synopsys: csi2: Add simple synopsys platform driver

 .../bindings/media/snps,dw-mipi-csi2-v150.yaml     |  158 +++
 MAINTAINERS                                        |    1 +
 drivers/media/platform/synopsys/Kconfig            |   20 +
 drivers/media/platform/synopsys/Makefile           |    3 +
 drivers/media/platform/synopsys/mipi-csi2-simple.c |   75 ++
 drivers/media/platform/synopsys/mipi-csi2.c        | 1258 ++++++++++++++++++++
 drivers/media/v4l2-core/v4l2-common.c              |  220 ++++
 drivers/staging/media/imx/Kconfig                  |    1 +
 drivers/staging/media/imx/Makefile                 |    2 +-
 drivers/staging/media/imx/imx6-csi2.c              |  181 +++
 drivers/staging/media/imx/imx6-mipi-csi2.c         |  846 -------------
 include/media/dw-mipi-csi2.h                       |  120 ++
 include/media/mipi-csi2.h                          |    5 +
 include/media/v4l2-common.h                        |   30 +
 14 files changed, 2073 insertions(+), 847 deletions(-)
---
base-commit: 33652d58b64e92d2598205fd992989bd93cd61f4
change-id: 20250606-95_cam-b74c094ad1fb

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


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

* [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-18 14:39   ` Rob Herring
  2025-08-08 22:39 ` [PATCH v2 02/32] media: v4l2-common: Add helper function v4l_get_required_align_by_bpp() Frank Li
                   ` (31 subsequent siblings)
  32 siblings, 1 reply; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li, Luis Oliveira

From: Eugen Hristev <eugen.hristev@linaro.org>

Add bindings for Synopsys DesignWare MIPI CSI-2 host, which used at i.MX93
and i.MX95 platform.

Signed-off-by: Luis Oliveira <lolivei@synopsys.com>
Signed-off-by: Eugen Hristev <eugen.hristev@linaro.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change in v2
- remove Eugen Hristev <eugen.hristev@microchip.com> from mantainer.
- update ugen Hristev's s-o-b tag to align original author's email address
- remove single snps,dw-mipi-csi2-v150 compatible string
- move additionalProperties after required
---
 .../bindings/media/snps,dw-mipi-csi2-v150.yaml     | 158 +++++++++++++++++++++
 MAINTAINERS                                        |   1 +
 2 files changed, 159 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml b/Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fc1b167d6d3b142a01e2ea7f04230934260a05e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/snps,dw-mipi-csi2-v150.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare CSI-2 Host controller (csi2host)
+
+maintainers:
+  - Frank Li <Frank.Li@nxp.com>
+
+description:
+  CSI2HOST is used to receive image coming from an MIPI CSI-2 compatible
+  camera. It will convert the incoming CSI-2 stream into a dedicated
+  interface called the Synopsys IDI (Image Data Interface).
+  This interface is a 32-bit SoC internal only, and can be assimilated
+  with a CSI-2 interface.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - fsl,imx93-mipi-csi2
+      - const: snps,dw-mipi-csi2-v150
+
+  reg:
+    items:
+      - description: MIPI CSI-2 core register
+
+  reg-names:
+    items:
+      - const: core
+
+  clocks:
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: per
+      - const: pixel
+
+  phys:
+    maxItems: 1
+    description: MIPI D-PHY
+
+  phy-names:
+    items:
+      - const: rx
+
+  resets:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description:
+          Input port node, single endpoint describing the input port.
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+            description: Endpoint connected to input device
+
+            properties:
+              bus-type:
+                const: 4
+
+              data-lanes:
+                minItems: 1
+                maxItems: 4
+                items:
+                  maximum: 4
+
+              clock-lanes:
+                maxItems: 1
+
+              remote-endpoint: true
+
+      port@1:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description:
+          Output port node, single endpoint describing the output port.
+
+        properties:
+          endpoint:
+            unevaluatedProperties: false
+            $ref: video-interfaces.yaml#
+            description: Endpoint connected to output device
+
+            properties:
+              bus-type:
+                const: 4
+
+              remote-endpoint: true
+
+    required:
+      - port@0
+      - port@1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    csi@3000 {
+        compatible = "fsl,imx93-mipi-csi2", "snps,dw-mipi-csi2-v150";
+        reg = <0x03000 0x1000>;
+        reg-names = "core";
+        phys = <&mipi_dphy_rx 0>;
+        phy-names = "rx";
+        resets = <&dw_rst 1>;
+        interrupts = <2>;
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port@0 {
+                reg = <0>;
+
+                endpoint {
+                    bus-type = <4>; /* MIPI CSI2 D-PHY */
+                    remote-endpoint = <&camera_1>;
+                    data-lanes = <1 2>;
+                    clock-lanes = <0>;
+                };
+            };
+
+            port@1 {
+                reg = <1>;
+
+                endpoint {
+                    remote-endpoint = <&idi_receiver>;
+                    bus-type = <4>;
+                };
+            };
+        };
+    };
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index edfcee622f74054f519336f0ea963e7c8f2f6add..385b797c1e29c71fb89a908d543cc60806aaa978 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15193,6 +15193,7 @@ F:	Documentation/devicetree/bindings/media/fsl,imx93-parallel-csi.yaml
 F:	Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
 F:	Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
 F:	Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml
+F:	Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml
 F:	drivers/media/platform/nxp/imx-mipi-csis.c
 F:	drivers/media/platform/nxp/imx-parallel-csi.c
 F:	drivers/media/platform/nxp/imx7-media-csi.c

-- 
2.34.1


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

* [PATCH v2 02/32] media: v4l2-common: Add helper function v4l_get_required_align_by_bpp()
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
  2025-08-08 22:39 ` [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 03/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp() Frank Li
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add helper v4l_get_required_align_by_bpp() to help get width alignment
requirement. Basic replace below logic and enhance to any 2^[0..31] in
drivers/media/platform/nxp/imx-mipi-csis.c

mipi_csis_set_fmt(
{
        ...

        switch (csis_fmt->width % 8) {
        case 0:
                align = 0;
                break;
        case 4:
                align = 1;
                break;
        case 2:
        case 6:
                align = 2;
                break;
        default:
                /* 1, 3, 5, 7 */
                align = 3;
                break;
        }
	...
}

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
The same patch will be see at https://lore.kernel.org/imx/20250729-imx8qxp_pcam-v4-2-4dfca4ed2f87@nxp.com/
dw csi2 patch also this
---
 include/media/v4l2-common.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 0a43f56578bce1896cf63e29dd19f58ec0c46bed..a861d83bcd835dc854476b25919383415e5d434f 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -669,4 +669,34 @@ static inline bool v4l2_is_quant_valid(__u8 quantization)
 	       quantization == V4L2_QUANTIZATION_LIM_RANGE;
 }
 
+/**
+ * v4l_get_required_align_by_bpp - get align requirement for
+ *	v4l_bound_align_image(). (bpp * width) % (1 << align) have to be 0.
+ *	given number bpp, get width's alignment requirement. For example,
+ *	if align is 3, means require bpp * width must be multiples of 8.
+ *	    bpp     return  width's requirememnt
+ *	    0       0       none
+ *	    1       3       8 (need 3 zero bits)
+ *	    2       2       4
+ *	    3       3       8
+ *	    4       1       2
+ *	    5       3       8
+ *	    6       2       4
+ *	    7       3       8
+ * @bpp: input bpp
+ * @align: expected alignment, 2^(align).
+ *
+ * return: required alignment.
+ */
+static inline u32 v4l_get_required_align_by_bpp(u32 bpp, u32 align)
+{
+	int pos;
+
+	if (bpp == 0)
+		return 0;
+
+	pos = ffs(bpp) - 1;
+	return pos > align ? 0 : align - pos;
+}
+
 #endif /* V4L2_COMMON_H_ */

-- 
2.34.1


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

* [PATCH v2 03/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp()
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
  2025-08-08 22:39 ` [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support Frank Li
  2025-08-08 22:39 ` [PATCH v2 02/32] media: v4l2-common: Add helper function v4l_get_required_align_by_bpp() Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 04/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt() Frank Li
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add helper function media_bus_fmt_to_csi2_bpp() to get media bus fmt's bpp
to reduce codes such as

	static const struct imx7_csi_pixfmt pixel_formats[] = {
        {
                .fourcc = V4L2_PIX_FMT_UYVY,
                .codes  = IMX_BUS_FMTS(
                        MEDIA_BUS_FMT_UYVY8_2X8,
                        MEDIA_BUS_FMT_UYVY8_1X16
                ),
                .yuv    = true,
                .bpp    = 16,
        },
	....

.bpp can be removed from pixel_formats with this helper function.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/v4l2-core/v4l2-common.c | 176 ++++++++++++++++++++++++++++++++++
 include/media/mipi-csi2.h             |   2 +
 2 files changed, 178 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index a9bd3ca0f281d557cb80de5e1200c82b5282a70e..3a48b6a55c6e322696b910dd519def4f0b4a58fb 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -43,6 +43,7 @@
 #include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/div64.h>
+#include <media/mipi-csi2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
@@ -699,3 +700,178 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
+
+int media_bus_fmt_to_csi2_bpp(int bus_fmt)
+{
+	switch (bus_fmt) {
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case MEDIA_BUS_FMT_SGBRG8_1X8:
+	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case MEDIA_BUS_FMT_SRGGB8_1X8:
+	case MEDIA_BUS_FMT_Y8_1X8:
+	case MEDIA_BUS_FMT_UV8_1X8:
+	case MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8:
+	case MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8:
+	case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
+	case MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8:
+	case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
+	case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+	case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+	case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
+	case MEDIA_BUS_FMT_META_8:
+	case MEDIA_BUS_FMT_JPEG_1X8:
+		return 8;
+
+	case MEDIA_BUS_FMT_Y10_1X10:
+	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case MEDIA_BUS_FMT_SGBRG10_1X10:
+	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case MEDIA_BUS_FMT_SRGGB10_1X10:
+	case MEDIA_BUS_FMT_META_10:
+		return 10;
+
+	case MEDIA_BUS_FMT_RGB444_1X12:
+	case MEDIA_BUS_FMT_Y12_1X12:
+	case MEDIA_BUS_FMT_SBGGR12_1X12:
+	case MEDIA_BUS_FMT_SGBRG12_1X12:
+	case MEDIA_BUS_FMT_SGRBG12_1X12:
+	case MEDIA_BUS_FMT_SRGGB12_1X12:
+	case MEDIA_BUS_FMT_META_12:
+		return 12;
+
+	case MEDIA_BUS_FMT_Y14_1X14:
+	case MEDIA_BUS_FMT_SBGGR14_1X14:
+	case MEDIA_BUS_FMT_SGBRG14_1X14:
+	case MEDIA_BUS_FMT_SGRBG14_1X14:
+	case MEDIA_BUS_FMT_SRGGB14_1X14:
+	case MEDIA_BUS_FMT_META_14:
+		return 14;
+
+	case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
+	case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
+	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
+	case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+	case MEDIA_BUS_FMT_RGB565_1X16:
+	case MEDIA_BUS_FMT_BGR565_2X8_BE:
+	case MEDIA_BUS_FMT_BGR565_2X8_LE:
+	case MEDIA_BUS_FMT_RGB565_2X8_BE:
+	case MEDIA_BUS_FMT_RGB565_2X8_LE:
+
+	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case MEDIA_BUS_FMT_Y10_2X8_PADHI_LE:
+	case MEDIA_BUS_FMT_Y16_1X16:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYUY8_1X16:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_YDYUYDYV8_1X16:
+
+	case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
+	case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+	case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
+	case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
+	case MEDIA_BUS_FMT_SBGGR16_1X16:
+	case MEDIA_BUS_FMT_SGBRG16_1X16:
+	case MEDIA_BUS_FMT_SRGGB16_1X16:
+	case MEDIA_BUS_FMT_META_16:
+		return 16;
+
+	case MEDIA_BUS_FMT_RGB666_1X18:
+	case MEDIA_BUS_FMT_RGB666_2X9_BE:
+	case MEDIA_BUS_FMT_BGR666_1X18:
+		return 18;
+
+	case MEDIA_BUS_FMT_UYVY10_2X10:
+	case MEDIA_BUS_FMT_VYUY10_2X10:
+	case MEDIA_BUS_FMT_YUYV10_2X10:
+	case MEDIA_BUS_FMT_YVYU10_2X10:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_VYUY10_1X20:
+	case MEDIA_BUS_FMT_YUYV10_1X20:
+	case MEDIA_BUS_FMT_YVYU10_1X20:
+	case MEDIA_BUS_FMT_META_20:
+		return 20;
+
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+		return 21;
+
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_BGR888_3X8:
+	case MEDIA_BUS_FMT_GBR888_1X24:
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB888_2X12_BE:
+	case MEDIA_BUS_FMT_RGB888_2X12_LE:
+	case MEDIA_BUS_FMT_RGB888_3X8:
+	case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
+	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+	case MEDIA_BUS_FMT_BGR666_1X24_CPADHI:
+	case MEDIA_BUS_FMT_RGB565_1X24_CPADHI:
+	case MEDIA_BUS_FMT_UYVY12_2X12:
+	case MEDIA_BUS_FMT_VYUY12_2X12:
+	case MEDIA_BUS_FMT_YUYV12_2X12:
+	case MEDIA_BUS_FMT_YVYU12_2X12:
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+	case MEDIA_BUS_FMT_VYUY12_1X24:
+	case MEDIA_BUS_FMT_YUYV12_1X24:
+	case MEDIA_BUS_FMT_YVYU12_1X24:
+	case MEDIA_BUS_FMT_META_24:
+		return 24;
+
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+		return 28;
+
+	case MEDIA_BUS_FMT_RGB666_1X30_CPADLO:
+	case MEDIA_BUS_FMT_RGB888_1X30_CPADLO:
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+		return 30;
+
+	case MEDIA_BUS_FMT_ARGB8888_1X32:
+	case MEDIA_BUS_FMT_RGB888_1X32_PADHI:
+	case MEDIA_BUS_FMT_AYUV8_1X32:
+	case MEDIA_BUS_FMT_AHSV8888_1X32:
+		return 32;
+
+	case MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG:
+	case MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA:
+		return 35;
+
+	case MEDIA_BUS_FMT_RGB666_1X36_CPADLO:
+	case MEDIA_BUS_FMT_RGB888_1X36_CPADLO:
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+	case MEDIA_BUS_FMT_YUV12_1X36:
+		return 36;
+
+	case MEDIA_BUS_FMT_UYVY8_1_5X8:
+	case MEDIA_BUS_FMT_VYUY8_1_5X8:
+	case MEDIA_BUS_FMT_YUYV8_1_5X8:
+	case MEDIA_BUS_FMT_YVYU8_1_5X8:
+		return 40;
+
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+	case MEDIA_BUS_FMT_YUV16_1X48:
+		return 48;
+
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		return 120;
+
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+		return 150;
+
+	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
+		return 180;
+
+	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
+		return 240;
+
+	};
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_bus_fmt_to_csi2_bpp);
diff --git a/include/media/mipi-csi2.h b/include/media/mipi-csi2.h
index 40fc0264250d779ab5dfa7d2fe16e6f1382c07d4..c5b4e8e1ca93803568b1eee85f7f99c3a45a0b6e 100644
--- a/include/media/mipi-csi2.h
+++ b/include/media/mipi-csi2.h
@@ -44,4 +44,6 @@
 #define MIPI_CSI2_DT_RAW20		0x2f
 #define MIPI_CSI2_DT_USER_DEFINED(n)	(0x30 + (n))	/* 0..7 */
 
+int media_bus_fmt_to_csi2_bpp(int bus_fmt);
+
 #endif /* _MEDIA_MIPI_CSI2_H */

-- 
2.34.1


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

* [PATCH v2 04/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt()
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (2 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 03/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp() Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-20 19:16   ` Laurent Pinchart
  2025-08-08 22:39 ` [PATCH v2 05/32] media: staging: media: imx6-mipi-csi2: replace space with tab for alignment Frank Li
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

CSI2 data type is defined by MIPI Camera Serial Interface 2 Spec Ver4.1.
See section 9.4.

Add helper function media_bus_fmt_to_csi2_dt() to convert media bus fmt to
MIPI defined data type and avoid below duplicated static array in each CSI2
drivers.

	{
		.code = MEDIA_BUS_FMT_UYVY8_1X16,
		.data_type = MIPI_CSI2_DT_YUV422_8B,
	}

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/v4l2-core/v4l2-common.c | 44 +++++++++++++++++++++++++++++++++++
 include/media/mipi-csi2.h             |  3 +++
 2 files changed, 47 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 3a48b6a55c6e322696b910dd519def4f0b4a58fb..fcc01030beb347499da2a3c8539793d20f6f512c 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -701,6 +701,50 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
 }
 EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
 
+int media_bus_fmt_to_csi2_dt(int bus_fmt)
+{
+	switch (bus_fmt) {
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		return MIPI_CSI2_DT_YUV422_8B;
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		return MIPI_CSI2_DT_RGB565;
+	case MEDIA_BUS_FMT_BGR888_1X24:
+		return MIPI_CSI2_DT_RGB888;
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case MEDIA_BUS_FMT_SGBRG8_1X8:
+	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case MEDIA_BUS_FMT_SRGGB8_1X8:
+	case MEDIA_BUS_FMT_Y8_1X8:
+		return MIPI_CSI2_DT_RAW8;
+	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case MEDIA_BUS_FMT_SGBRG10_1X10:
+	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case MEDIA_BUS_FMT_SRGGB10_1X10:
+	case MEDIA_BUS_FMT_Y10_1X10:
+		return MIPI_CSI2_DT_RAW10;
+	case MEDIA_BUS_FMT_SBGGR12_1X12:
+	case MEDIA_BUS_FMT_SGBRG12_1X12:
+	case MEDIA_BUS_FMT_SGRBG12_1X12:
+	case MEDIA_BUS_FMT_SRGGB12_1X12:
+	case MEDIA_BUS_FMT_Y12_1X12:
+		return MIPI_CSI2_DT_RAW12;
+	case MEDIA_BUS_FMT_SBGGR14_1X14:
+	case MEDIA_BUS_FMT_SGBRG14_1X14:
+	case MEDIA_BUS_FMT_SGRBG14_1X14:
+	case MEDIA_BUS_FMT_SRGGB14_1X14:
+		return MIPI_CSI2_DT_RAW14;
+	case MEDIA_BUS_FMT_SBGGR16_1X16:
+	case MEDIA_BUS_FMT_SGBRG16_1X16:
+	case MEDIA_BUS_FMT_SGRBG16_1X16:
+	case MEDIA_BUS_FMT_SRGGB16_1X16:
+		return MIPI_CSI2_DT_RAW16;
+
+	default:
+		return MIPI_CSI2_DT_NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(media_bus_fmt_to_csi2_dt);
+
 int media_bus_fmt_to_csi2_bpp(int bus_fmt)
 {
 	switch (bus_fmt) {
diff --git a/include/media/mipi-csi2.h b/include/media/mipi-csi2.h
index c5b4e8e1ca93803568b1eee85f7f99c3a45a0b6e..35de536b9b65b49ad9e2914437d26d0e4240cf38 100644
--- a/include/media/mipi-csi2.h
+++ b/include/media/mipi-csi2.h
@@ -8,6 +8,8 @@
 #ifndef _MEDIA_MIPI_CSI2_H
 #define _MEDIA_MIPI_CSI2_H
 
+/* DT value ref to MIPI Camera Serial Interface 2 Spec Ver4.1 section 9.4 */
+
 /* Short packet data types */
 #define MIPI_CSI2_DT_FS			0x00
 #define MIPI_CSI2_DT_FE			0x01
@@ -44,6 +46,7 @@
 #define MIPI_CSI2_DT_RAW20		0x2f
 #define MIPI_CSI2_DT_USER_DEFINED(n)	(0x30 + (n))	/* 0..7 */
 
+int media_bus_fmt_to_csi2_dt(int buf_fmt);
 int media_bus_fmt_to_csi2_bpp(int bus_fmt);
 
 #endif /* _MEDIA_MIPI_CSI2_H */

-- 
2.34.1


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

* [PATCH v2 05/32] media: staging: media: imx6-mipi-csi2: replace space with tab for alignment
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (3 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 04/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt() Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 06/32] media: staging: media: imx6-mipi-csi2: use devm_add_action_or_reset() to simplify code Frank Li
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Replace space with tab to follow coding convention. No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 92 +++++++++++++++---------------
 1 file changed, 46 insertions(+), 46 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index dd8c7b3233bccfc34b59e0f0ff813b36752e1526..42256441b881d9f132ad7ff899d6f1e35643b4ac 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -23,65 +23,65 @@
  * there must be 5 pads: 1 input pad from sensor, and
  * the 4 virtual channel output pads
  */
-#define CSI2_SINK_PAD       0
-#define CSI2_NUM_SINK_PADS  1
-#define CSI2_NUM_SRC_PADS   4
-#define CSI2_NUM_PADS       5
+#define CSI2_SINK_PAD		0
+#define CSI2_NUM_SINK_PADS	1
+#define CSI2_NUM_SRC_PADS	4
+#define CSI2_NUM_PADS		5
 
 /*
  * The default maximum bit-rate per lane in Mbps, if the
  * source subdev does not provide V4L2_CID_LINK_FREQ.
  */
-#define CSI2_DEFAULT_MAX_MBPS 849
+#define CSI2_DEFAULT_MAX_MBPS	849
 
 struct csi2_dev {
-	struct device          *dev;
-	struct v4l2_subdev      sd;
-	struct v4l2_async_notifier notifier;
-	struct media_pad       pad[CSI2_NUM_PADS];
-	struct clk             *dphy_clk;
-	struct clk             *pllref_clk;
-	struct clk             *pix_clk; /* what is this? */
-	void __iomem           *base;
-
-	struct v4l2_subdev	*remote;
-	unsigned int		remote_pad;
-	unsigned short		data_lanes;
+	struct device			*dev;
+	struct v4l2_subdev		sd;
+	struct v4l2_async_notifier	notifier;
+	struct media_pad		pad[CSI2_NUM_PADS];
+	struct clk			*dphy_clk;
+	struct clk			*pllref_clk;
+	struct clk			*pix_clk; /* what is this? */
+	void __iomem			*base;
+
+	struct v4l2_subdev		*remote;
+	unsigned int			remote_pad;
+	unsigned short			data_lanes;
 
 	/* lock to protect all members below */
-	struct mutex lock;
+	struct mutex			lock;
 
-	struct v4l2_mbus_framefmt format_mbus;
+	struct v4l2_mbus_framefmt	format_mbus;
 
-	int                     stream_count;
-	struct v4l2_subdev      *src_sd;
-	bool                    sink_linked[CSI2_NUM_SRC_PADS];
+	int				stream_count;
+	struct v4l2_subdev		*src_sd;
+	bool				sink_linked[CSI2_NUM_SRC_PADS];
 };
 
 #define DEVICE_NAME "imx6-mipi-csi2"
 
 /* Register offsets */
-#define CSI2_VERSION            0x000
-#define CSI2_N_LANES            0x004
-#define CSI2_PHY_SHUTDOWNZ      0x008
-#define CSI2_DPHY_RSTZ          0x00c
-#define CSI2_RESETN             0x010
-#define CSI2_PHY_STATE          0x014
-#define PHY_STOPSTATEDATA_BIT   4
-#define PHY_STOPSTATEDATA(n)    BIT(PHY_STOPSTATEDATA_BIT + (n))
-#define PHY_RXCLKACTIVEHS       BIT(8)
-#define PHY_RXULPSCLKNOT        BIT(9)
-#define PHY_STOPSTATECLK        BIT(10)
-#define CSI2_DATA_IDS_1         0x018
-#define CSI2_DATA_IDS_2         0x01c
-#define CSI2_ERR1               0x020
-#define CSI2_ERR2               0x024
-#define CSI2_MSK1               0x028
-#define CSI2_MSK2               0x02c
-#define CSI2_PHY_TST_CTRL0      0x030
+#define CSI2_VERSION		0x000
+#define CSI2_N_LANES		0x004
+#define CSI2_PHY_SHUTDOWNZ	0x008
+#define CSI2_DPHY_RSTZ		0x00c
+#define CSI2_RESETN		0x010
+#define CSI2_PHY_STATE		0x014
+#define PHY_STOPSTATEDATA_BIT	4
+#define PHY_STOPSTATEDATA(n)	BIT(PHY_STOPSTATEDATA_BIT + (n))
+#define PHY_RXCLKACTIVEHS	BIT(8)
+#define PHY_RXULPSCLKNOT	BIT(9)
+#define PHY_STOPSTATECLK	BIT(10)
+#define CSI2_DATA_IDS_1		0x018
+#define CSI2_DATA_IDS_2		0x01c
+#define CSI2_ERR1		0x020
+#define CSI2_ERR2		0x024
+#define CSI2_MSK1		0x028
+#define CSI2_MSK2		0x02c
+#define CSI2_PHY_TST_CTRL0	0x030
 #define PHY_TESTCLR		BIT(0)
 #define PHY_TESTCLK		BIT(1)
-#define CSI2_PHY_TST_CTRL1      0x034
+#define CSI2_PHY_TST_CTRL1	0x034
 #define PHY_TESTEN		BIT(16)
 /*
  * i.MX CSI2IPU Gasket registers follow. The CSI2IPU gasket is
@@ -106,13 +106,13 @@ static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
  * reference manual is as follows:
  *
  * 1. Deassert presetn signal (global reset).
- *        It's not clear what this "global reset" signal is (maybe APB
- *        global reset), but in any case this step would be probably
- *        be carried out during driver load in csi2_probe().
+ *	It's not clear what this "global reset" signal is (maybe APB
+ *	global reset), but in any case this step would be probably
+ *	be carried out during driver load in csi2_probe().
  *
  * 2. Configure MIPI Camera Sensor to put all Tx lanes in LP-11 state.
- *        This must be carried out by the MIPI sensor's s_power(ON) subdev
- *        op.
+ *	This must be carried out by the MIPI sensor's s_power(ON) subdev
+ *	op.
  *
  * 3. D-PHY initialization.
  * 4. CSI2 Controller programming (Set N_LANES, deassert PHY_SHUTDOWNZ,

-- 
2.34.1


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

* [PATCH v2 06/32] media: staging: media: imx6-mipi-csi2: use devm_add_action_or_reset() to simplify code
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (4 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 05/32] media: staging: media: imx6-mipi-csi2: replace space with tab for alignment Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 07/32] media: staging: media: imx6-mipi-csi2: use devm_clk_bulk_get_all() to fetch clocks Frank Li
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use devm_add_action_or_reset() to simplify the code. No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 42256441b881d9f132ad7ff899d6f1e35643b4ac..eba9a650030f5e380aa900b94728ad375171c6a5 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -716,6 +716,14 @@ static int csi2_async_register(struct csi2_dev *csi2)
 	return ret;
 }
 
+static void csi2_nf_cleanup(void *data)
+{
+	struct csi2_dev *csi2 = data;
+
+	v4l2_async_nf_unregister(&csi2->notifier);
+	v4l2_async_nf_cleanup(&csi2->notifier);
+}
+
 static int csi2_probe(struct platform_device *pdev)
 {
 	struct csi2_dev *csi2;
@@ -749,6 +757,10 @@ static int csi2_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = devm_add_action_or_reset(&pdev->dev, csi2_nf_cleanup, csi2);
+	if (ret)
+		return ret;
+
 	csi2->pllref_clk = devm_clk_get(&pdev->dev, "ref");
 	if (IS_ERR(csi2->pllref_clk)) {
 		v4l2_err(&csi2->sd, "failed to get pll reference clock\n");
@@ -800,8 +812,6 @@ static int csi2_probe(struct platform_device *pdev)
 	return 0;
 
 clean_notifier:
-	v4l2_async_nf_unregister(&csi2->notifier);
-	v4l2_async_nf_cleanup(&csi2->notifier);
 	clk_disable_unprepare(csi2->dphy_clk);
 pllref_off:
 	clk_disable_unprepare(csi2->pllref_clk);
@@ -815,8 +825,6 @@ static void csi2_remove(struct platform_device *pdev)
 	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
 	struct csi2_dev *csi2 = sd_to_dev(sd);
 
-	v4l2_async_nf_unregister(&csi2->notifier);
-	v4l2_async_nf_cleanup(&csi2->notifier);
 	v4l2_async_unregister_subdev(sd);
 	clk_disable_unprepare(csi2->dphy_clk);
 	clk_disable_unprepare(csi2->pllref_clk);

-- 
2.34.1


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

* [PATCH v2 07/32] media: staging: media: imx6-mipi-csi2: use devm_clk_bulk_get_all() to fetch clocks
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (5 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 06/32] media: staging: media: imx6-mipi-csi2: use devm_add_action_or_reset() to simplify code Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 08/32] media: staging: media: imx6-mipi-csi2: use devm_mutex_init() to simplify code Frank Li
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use devm_clk_bulk_get_all_enabled() helper to simplify clock handling.

Defer all clock prepare and enable to csi2_start(), which previous only
enable pix clock here.

We can safely do that because there are not register access before
csi2_start().

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 52 ++++++------------------------
 1 file changed, 9 insertions(+), 43 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index eba9a650030f5e380aa900b94728ad375171c6a5..32ddcef7ec8535a44e121754bb621c0d2e226369 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -39,11 +39,11 @@ struct csi2_dev {
 	struct v4l2_subdev		sd;
 	struct v4l2_async_notifier	notifier;
 	struct media_pad		pad[CSI2_NUM_PADS];
-	struct clk			*dphy_clk;
-	struct clk			*pllref_clk;
-	struct clk			*pix_clk; /* what is this? */
 	void __iomem			*base;
 
+	struct clk_bulk_data		*clks;
+	int				num_clks;
+
 	struct v4l2_subdev		*remote;
 	unsigned int			remote_pad;
 	unsigned short			data_lanes;
@@ -343,7 +343,7 @@ static int csi2_start(struct csi2_dev *csi2)
 	unsigned int lanes;
 	int ret;
 
-	ret = clk_prepare_enable(csi2->pix_clk);
+	ret = clk_bulk_prepare_enable(csi2->num_clks, csi2->clks);
 	if (ret)
 		return ret;
 
@@ -390,7 +390,7 @@ static int csi2_start(struct csi2_dev *csi2)
 err_assert_reset:
 	csi2_enable(csi2, false);
 err_disable_clk:
-	clk_disable_unprepare(csi2->pix_clk);
+	clk_bulk_disable_unprepare(csi2->num_clks, csi2->clks);
 	return ret;
 }
 
@@ -401,7 +401,7 @@ static void csi2_stop(struct csi2_dev *csi2)
 	v4l2_subdev_call(csi2->src_sd, video, post_streamoff);
 
 	csi2_enable(csi2, false);
-	clk_disable_unprepare(csi2->pix_clk);
+	clk_bulk_disable_unprepare(csi2->num_clks, csi2->clks);
 }
 
 /*
@@ -761,24 +761,6 @@ static int csi2_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	csi2->pllref_clk = devm_clk_get(&pdev->dev, "ref");
-	if (IS_ERR(csi2->pllref_clk)) {
-		v4l2_err(&csi2->sd, "failed to get pll reference clock\n");
-		return PTR_ERR(csi2->pllref_clk);
-	}
-
-	csi2->dphy_clk = devm_clk_get(&pdev->dev, "dphy");
-	if (IS_ERR(csi2->dphy_clk)) {
-		v4l2_err(&csi2->sd, "failed to get dphy clock\n");
-		return PTR_ERR(csi2->dphy_clk);
-	}
-
-	csi2->pix_clk = devm_clk_get(&pdev->dev, "pix");
-	if (IS_ERR(csi2->pix_clk)) {
-		v4l2_err(&csi2->sd, "failed to get pixel clock\n");
-		return PTR_ERR(csi2->pix_clk);
-	}
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		v4l2_err(&csi2->sd, "failed to get platform resources\n");
@@ -791,19 +773,9 @@ static int csi2_probe(struct platform_device *pdev)
 
 	mutex_init(&csi2->lock);
 
-	ret = clk_prepare_enable(csi2->pllref_clk);
-	if (ret) {
-		v4l2_err(&csi2->sd, "failed to enable pllref_clk\n");
-		goto rmmutex;
-	}
-
-	ret = clk_prepare_enable(csi2->dphy_clk);
-	if (ret) {
-		v4l2_err(&csi2->sd, "failed to enable dphy_clk\n");
-		goto pllref_off;
-	}
-
-	platform_set_drvdata(pdev, &csi2->sd);
+	csi2->num_clks = devm_clk_bulk_get_all(&pdev->dev, &csi2->clks);
+	if (csi2->num_clks < 0)
+		return dev_err_probe(&pdev->dev, csi2->num_clks, "Failed to get clocks\n");
 
 	ret = csi2_async_register(csi2);
 	if (ret)
@@ -812,10 +784,6 @@ static int csi2_probe(struct platform_device *pdev)
 	return 0;
 
 clean_notifier:
-	clk_disable_unprepare(csi2->dphy_clk);
-pllref_off:
-	clk_disable_unprepare(csi2->pllref_clk);
-rmmutex:
 	mutex_destroy(&csi2->lock);
 	return ret;
 }
@@ -826,8 +794,6 @@ static void csi2_remove(struct platform_device *pdev)
 	struct csi2_dev *csi2 = sd_to_dev(sd);
 
 	v4l2_async_unregister_subdev(sd);
-	clk_disable_unprepare(csi2->dphy_clk);
-	clk_disable_unprepare(csi2->pllref_clk);
 	mutex_destroy(&csi2->lock);
 	media_entity_cleanup(&sd->entity);
 }

-- 
2.34.1


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

* [PATCH v2 08/32] media: staging: media: imx6-mipi-csi2: use devm_mutex_init() to simplify code
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (6 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 07/32] media: staging: media: imx6-mipi-csi2: use devm_clk_bulk_get_all() to fetch clocks Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 09/32] media: staging: media: imx6-mipi-csi2: use guard() " Frank Li
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use devm_mutex_init() to simplify the code. No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 32ddcef7ec8535a44e121754bb621c0d2e226369..72ede5ebf4d4c426e62cf288225a2b2dd7cfe1bd 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -771,30 +771,21 @@ static int csi2_probe(struct platform_device *pdev)
 	if (!csi2->base)
 		return -ENOMEM;
 
-	mutex_init(&csi2->lock);
+	devm_mutex_init(&pdev->dev, &csi2->lock);
 
 	csi2->num_clks = devm_clk_bulk_get_all(&pdev->dev, &csi2->clks);
 	if (csi2->num_clks < 0)
 		return dev_err_probe(&pdev->dev, csi2->num_clks, "Failed to get clocks\n");
 
-	ret = csi2_async_register(csi2);
-	if (ret)
-		goto clean_notifier;
-
-	return 0;
+	return csi2_async_register(csi2);
 
-clean_notifier:
-	mutex_destroy(&csi2->lock);
-	return ret;
 }
 
 static void csi2_remove(struct platform_device *pdev)
 {
 	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
-	struct csi2_dev *csi2 = sd_to_dev(sd);
 
 	v4l2_async_unregister_subdev(sd);
-	mutex_destroy(&csi2->lock);
 	media_entity_cleanup(&sd->entity);
 }
 

-- 
2.34.1


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

* [PATCH v2 09/32] media: staging: media: imx6-mipi-csi2: use guard() to simplify code
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (7 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 08/32] media: staging: media: imx6-mipi-csi2: use devm_mutex_init() to simplify code Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 10/32] media: staging: media: imx6-mipi-csi2: use register structure to match hardware Frank Li
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use guard() to simplify mutex locking. No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 54 +++++++++++-------------------
 1 file changed, 19 insertions(+), 35 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 72ede5ebf4d4c426e62cf288225a2b2dd7cfe1bd..73278d9ec2d66afa33b2bea17f2d56bb1391108b 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -413,21 +413,17 @@ static int csi2_s_stream(struct v4l2_subdev *sd, int enable)
 	struct csi2_dev *csi2 = sd_to_dev(sd);
 	int i, ret = 0;
 
-	mutex_lock(&csi2->lock);
+	guard(mutex)(&csi2->lock);
 
-	if (!csi2->src_sd) {
-		ret = -EPIPE;
-		goto out;
-	}
+	if (!csi2->src_sd)
+		return -EPIPE;
 
 	for (i = 0; i < CSI2_NUM_SRC_PADS; i++) {
 		if (csi2->sink_linked[i])
 			break;
 	}
-	if (i >= CSI2_NUM_SRC_PADS) {
-		ret = -EPIPE;
-		goto out;
-	}
+	if (i >= CSI2_NUM_SRC_PADS)
+		return -EPIPE;
 
 	/*
 	 * enable/disable streaming only if stream_count is
@@ -442,14 +438,12 @@ static int csi2_s_stream(struct v4l2_subdev *sd, int enable)
 	else
 		csi2_stop(csi2);
 	if (ret)
-		goto out;
+		return ret;
 
 update_count:
 	csi2->stream_count += enable ? 1 : -1;
 	if (csi2->stream_count < 0)
 		csi2->stream_count = 0;
-out:
-	mutex_unlock(&csi2->lock);
 	return ret;
 }
 
@@ -467,32 +461,28 @@ static int csi2_link_setup(struct media_entity *entity,
 
 	remote_sd = media_entity_to_v4l2_subdev(remote->entity);
 
-	mutex_lock(&csi2->lock);
+	guard(mutex)(&csi2->lock);
 
 	if (local->flags & MEDIA_PAD_FL_SOURCE) {
 		if (flags & MEDIA_LNK_FL_ENABLED) {
-			if (csi2->sink_linked[local->index - 1]) {
-				ret = -EBUSY;
-				goto out;
-			}
+			if (csi2->sink_linked[local->index - 1])
+				return -EBUSY;
+
 			csi2->sink_linked[local->index - 1] = true;
 		} else {
 			csi2->sink_linked[local->index - 1] = false;
 		}
 	} else {
 		if (flags & MEDIA_LNK_FL_ENABLED) {
-			if (csi2->src_sd) {
-				ret = -EBUSY;
-				goto out;
-			}
+			if (csi2->src_sd)
+				return -EBUSY;
+
 			csi2->src_sd = remote_sd;
 		} else {
 			csi2->src_sd = NULL;
 		}
 	}
 
-out:
-	mutex_unlock(&csi2->lock);
 	return ret;
 }
 
@@ -513,14 +503,12 @@ static int csi2_get_fmt(struct v4l2_subdev *sd,
 	struct csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
 
-	mutex_lock(&csi2->lock);
+	guard(mutex)(&csi2->lock);
 
 	fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
 
 	sdformat->format = *fmt;
 
-	mutex_unlock(&csi2->lock);
-
 	return 0;
 }
 
@@ -530,17 +518,14 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 {
 	struct csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
-	int ret = 0;
 
 	if (sdformat->pad >= CSI2_NUM_PADS)
 		return -EINVAL;
 
-	mutex_lock(&csi2->lock);
+	guard(mutex)(&csi2->lock);
 
-	if (csi2->stream_count > 0) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if (csi2->stream_count > 0)
+		return -EBUSY;
 
 	/* Output pads mirror active input pad, no limits on input pads */
 	if (sdformat->pad != CSI2_SINK_PAD)
@@ -549,9 +534,8 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 	fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
 
 	*fmt = sdformat->format;
-out:
-	mutex_unlock(&csi2->lock);
-	return ret;
+
+	return 0;
 }
 
 static int csi2_registered(struct v4l2_subdev *sd)

-- 
2.34.1


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

* [PATCH v2 10/32] media: staging: media: imx6-mipi-csi2: use register structure to match hardware
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (8 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 09/32] media: staging: media: imx6-mipi-csi2: use guard() " Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 11/32] media: staging: media: imx6-mipi-csi2: use devm_platform_ioremap_resource() simplify code Frank Li
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use register structure to handle different versions of the DesignWare CSI2
controller, as register offsets slightly differ between versions. Add
register existence bits to detect invalid register access when using
different versions of the CSI2 controller.

No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 165 +++++++++++++++++------------
 1 file changed, 96 insertions(+), 69 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 73278d9ec2d66afa33b2bea17f2d56bb1391108b..cef9a5dbca40c94a36d5d8473d3b7d9806381bf9 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -34,12 +34,30 @@
  */
 #define CSI2_DEFAULT_MAX_MBPS	849
 
+struct dw_csi2_regs {
+	u32	version;
+	u32	n_lanes;
+	u32	phy_shutdownz;
+	u32	dphy_rstz;
+	u32	resetn;
+	u32	phy_state;
+	u32	data_ids_1;
+	u32	data_ids_2;
+	u32	err1;
+	u32	err2;
+	u32	msk1;
+	u32	msk2;
+	u32	phy_tst_ctrl0;
+	u32	phy_tst_ctrl1;
+};
+
 struct csi2_dev {
 	struct device			*dev;
 	struct v4l2_subdev		sd;
 	struct v4l2_async_notifier	notifier;
 	struct media_pad		pad[CSI2_NUM_PADS];
 	void __iomem			*base;
+	const struct dw_csi2_regs	*regs;
 
 	struct clk_bulk_data		*clks;
 	int				num_clks;
@@ -60,28 +78,53 @@ struct csi2_dev {
 
 #define DEVICE_NAME "imx6-mipi-csi2"
 
-/* Register offsets */
-#define CSI2_VERSION		0x000
-#define CSI2_N_LANES		0x004
-#define CSI2_PHY_SHUTDOWNZ	0x008
-#define CSI2_DPHY_RSTZ		0x00c
-#define CSI2_RESETN		0x010
-#define CSI2_PHY_STATE		0x014
+/* Help check wrong access unexisted register at difference IP version */
+#define DW_REG_EXIST		0x80000000
+#define DW_REG(x)		(DW_REG_EXIST | (x))
+
+/* Register offsets for v0 */
+static const struct dw_csi2_regs dw_csi2_v0 = {
+	.version = DW_REG(0x0),
+	.n_lanes = DW_REG(0x4),
+	.phy_shutdownz = DW_REG(0x8),
+	.dphy_rstz = DW_REG(0xc),
+	.resetn = DW_REG(0x10),
+	.phy_state = DW_REG(0x14),
+	.data_ids_1 = DW_REG(0x18),
+	.data_ids_2 = DW_REG(0x1c),
+	.err1 = DW_REG(0x20),
+	.err2 = DW_REG(0x24),
+	.msk1 = DW_REG(0x28),
+	.msk2 = DW_REG(0x2c),
+	.phy_tst_ctrl0 = DW_REG(0x30),
+	.phy_tst_ctrl1 = DW_REG(0x34),
+};
+
+static int dw_csi2_reg_err(struct csi2_dev *csi2, const char *name)
+{
+	dev_err_once(csi2->dev, "access to unexisted register: %s", name);
+	return 0;
+}
+
+#define dw_reg_exist(csi2, __name) ((csi2)->regs->__name & DW_REG_EXIST)
+
+#define dw_writel(csi2, value, __name) (dw_reg_exist((csi2), __name) ? \
+writel(value, (csi2)->base + (csi2->regs->__name & ~DW_REG_EXIST)) : \
+dw_csi2_reg_err((csi2), #__name))
+
+#define dw_readl(csi2, __name) (dw_reg_exist((csi2), __name) ? \
+readl((csi2)->base + ((csi2)->regs->__name & ~DW_REG_EXIST)) : \
+dw_csi2_reg_err(csi2, #__name))
+
 #define PHY_STOPSTATEDATA_BIT	4
 #define PHY_STOPSTATEDATA(n)	BIT(PHY_STOPSTATEDATA_BIT + (n))
 #define PHY_RXCLKACTIVEHS	BIT(8)
 #define PHY_RXULPSCLKNOT	BIT(9)
 #define PHY_STOPSTATECLK	BIT(10)
-#define CSI2_DATA_IDS_1		0x018
-#define CSI2_DATA_IDS_2		0x01c
-#define CSI2_ERR1		0x020
-#define CSI2_ERR2		0x024
-#define CSI2_MSK1		0x028
-#define CSI2_MSK2		0x02c
-#define CSI2_PHY_TST_CTRL0	0x030
+
 #define PHY_TESTCLR		BIT(0)
 #define PHY_TESTCLK		BIT(1)
-#define CSI2_PHY_TST_CTRL1	0x034
+
 #define PHY_TESTEN		BIT(16)
 /*
  * i.MX CSI2IPU Gasket registers follow. The CSI2IPU gasket is
@@ -132,42 +175,42 @@ static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
 static void csi2_enable(struct csi2_dev *csi2, bool enable)
 {
 	if (enable) {
-		writel(0x1, csi2->base + CSI2_PHY_SHUTDOWNZ);
-		writel(0x1, csi2->base + CSI2_DPHY_RSTZ);
-		writel(0x1, csi2->base + CSI2_RESETN);
+		dw_writel(csi2, 0x1, phy_shutdownz);
+		dw_writel(csi2, 0x1, dphy_rstz);
+		dw_writel(csi2, 0x1, resetn);
 	} else {
-		writel(0x0, csi2->base + CSI2_PHY_SHUTDOWNZ);
-		writel(0x0, csi2->base + CSI2_DPHY_RSTZ);
-		writel(0x0, csi2->base + CSI2_RESETN);
+		dw_writel(csi2, 0x0, phy_shutdownz);
+		dw_writel(csi2, 0x0, dphy_rstz);
+		dw_writel(csi2, 0x0, resetn);
 	}
 }
 
 static void csi2_set_lanes(struct csi2_dev *csi2, unsigned int lanes)
 {
-	writel(lanes - 1, csi2->base + CSI2_N_LANES);
+	dw_writel(csi2, lanes - 1, n_lanes);
 }
 
 static void dw_mipi_csi2_phy_write(struct csi2_dev *csi2,
 				   u32 test_code, u32 test_data)
 {
 	/* Clear PHY test interface */
-	writel(PHY_TESTCLR, csi2->base + CSI2_PHY_TST_CTRL0);
-	writel(0x0, csi2->base + CSI2_PHY_TST_CTRL1);
-	writel(0x0, csi2->base + CSI2_PHY_TST_CTRL0);
+	dw_writel(csi2, PHY_TESTCLR, phy_tst_ctrl0);
+	dw_writel(csi2, 0x0, phy_tst_ctrl1);
+	dw_writel(csi2, 0x0, phy_tst_ctrl0);
 
 	/* Raise test interface strobe signal */
-	writel(PHY_TESTCLK, csi2->base + CSI2_PHY_TST_CTRL0);
+	dw_writel(csi2, PHY_TESTCLK, phy_tst_ctrl0);
 
 	/* Configure address write on falling edge and lower strobe signal */
-	writel(PHY_TESTEN | test_code, csi2->base + CSI2_PHY_TST_CTRL1);
-	writel(0x0, csi2->base + CSI2_PHY_TST_CTRL0);
+	dw_writel(csi2, PHY_TESTEN | test_code, phy_tst_ctrl1);
+	dw_writel(csi2, 0x0, phy_tst_ctrl0);
 
 	/* Configure data write on rising edge and raise strobe signal */
-	writel(test_data, csi2->base + CSI2_PHY_TST_CTRL1);
-	writel(PHY_TESTCLK, csi2->base + CSI2_PHY_TST_CTRL0);
+	dw_writel(csi2, test_data, phy_tst_ctrl1);
+	dw_writel(csi2, PHY_TESTCLK, phy_tst_ctrl0);
 
 	/* Clear strobe signal */
-	writel(0x0, csi2->base + CSI2_PHY_TST_CTRL0);
+	dw_writel(csi2, 0x0, phy_tst_ctrl0);
 }
 
 /*
@@ -233,16 +276,15 @@ static int __maybe_unused csi2_dphy_wait_ulp(struct csi2_dev *csi2)
 	int ret;
 
 	/* wait for ULP on clock lane */
-	ret = readl_poll_timeout(csi2->base + CSI2_PHY_STATE, reg,
-				 !(reg & PHY_RXULPSCLKNOT), 0, 500000);
+	ret = read_poll_timeout(dw_readl, reg, !(reg & PHY_RXULPSCLKNOT),
+				0, 500000, 0, csi2, phy_state);
 	if (ret) {
 		v4l2_err(&csi2->sd, "ULP timeout, phy_state = 0x%08x\n", reg);
 		return ret;
 	}
 
 	/* wait until no errors on bus */
-	ret = readl_poll_timeout(csi2->base + CSI2_ERR1, reg,
-				 reg == 0x0, 0, 500000);
+	ret = read_poll_timeout(dw_readl, reg, reg == 0x0, 0, 500000, 0, csi2, err1);
 	if (ret) {
 		v4l2_err(&csi2->sd, "stable bus timeout, err1 = 0x%08x\n", reg);
 		return ret;
@@ -259,8 +301,7 @@ static void csi2_dphy_wait_stopstate(struct csi2_dev *csi2, unsigned int lanes)
 
 	mask = PHY_STOPSTATECLK | (((1 << lanes) - 1) << PHY_STOPSTATEDATA_BIT);
 
-	ret = readl_poll_timeout(csi2->base + CSI2_PHY_STATE, reg,
-				 (reg & mask) == mask, 0, 500000);
+	ret = read_poll_timeout(dw_readl, reg, (reg & mask) == mask, 0, 500000, 0, csi2, phy_state);
 	if (ret) {
 		v4l2_warn(&csi2->sd, "LP-11 wait timeout, likely a sensor driver bug, expect capture failures.\n");
 		v4l2_warn(&csi2->sd, "phy_state = 0x%08x\n", reg);
@@ -273,8 +314,8 @@ static int csi2_dphy_wait_clock_lane(struct csi2_dev *csi2)
 	u32 reg;
 	int ret;
 
-	ret = readl_poll_timeout(csi2->base + CSI2_PHY_STATE, reg,
-				 (reg & PHY_RXCLKACTIVEHS), 0, 500000);
+	ret = read_poll_timeout(dw_readl, reg, (reg & PHY_RXCLKACTIVEHS),
+				0, 500000, 0, csi2, phy_state);
 	if (ret) {
 		v4l2_err(&csi2->sd, "clock lane timeout, phy_state = 0x%08x\n",
 			 reg);
@@ -556,34 +597,20 @@ static int csi2_log_status(struct v4l2_subdev *sd)
 	struct csi2_dev *csi2 = sd_to_dev(sd);
 
 	v4l2_info(sd, "-----MIPI CSI status-----\n");
-	v4l2_info(sd, "VERSION: 0x%x\n",
-		  readl(csi2->base + CSI2_VERSION));
-	v4l2_info(sd, "N_LANES: 0x%x\n",
-		  readl(csi2->base + CSI2_N_LANES));
-	v4l2_info(sd, "PHY_SHUTDOWNZ: 0x%x\n",
-		  readl(csi2->base + CSI2_PHY_SHUTDOWNZ));
-	v4l2_info(sd, "DPHY_RSTZ: 0x%x\n",
-		  readl(csi2->base + CSI2_DPHY_RSTZ));
-	v4l2_info(sd, "RESETN: 0x%x\n",
-		  readl(csi2->base + CSI2_RESETN));
-	v4l2_info(sd, "PHY_STATE: 0x%x\n",
-		  readl(csi2->base + CSI2_PHY_STATE));
-	v4l2_info(sd, "DATA_IDS_1: 0x%x\n",
-		  readl(csi2->base + CSI2_DATA_IDS_1));
-	v4l2_info(sd, "DATA_IDS_2: 0x%x\n",
-		  readl(csi2->base + CSI2_DATA_IDS_2));
-	v4l2_info(sd, "ERR1: 0x%x\n",
-		  readl(csi2->base + CSI2_ERR1));
-	v4l2_info(sd, "ERR2: 0x%x\n",
-		  readl(csi2->base + CSI2_ERR2));
-	v4l2_info(sd, "MSK1: 0x%x\n",
-		  readl(csi2->base + CSI2_MSK1));
-	v4l2_info(sd, "MSK2: 0x%x\n",
-		  readl(csi2->base + CSI2_MSK2));
-	v4l2_info(sd, "PHY_TST_CTRL0: 0x%x\n",
-		  readl(csi2->base + CSI2_PHY_TST_CTRL0));
-	v4l2_info(sd, "PHY_TST_CTRL1: 0x%x\n",
-		  readl(csi2->base + CSI2_PHY_TST_CTRL1));
+	v4l2_info(sd, "VERSION: 0x%x\n", dw_readl(csi2, version));
+	v4l2_info(sd, "N_LANES: 0x%x\n", dw_readl(csi2, n_lanes));
+	v4l2_info(sd, "PHY_SHUTDOWNZ: 0x%x\n", dw_readl(csi2, phy_shutdownz));
+	v4l2_info(sd, "DPHY_RSTZ: 0x%x\n", dw_readl(csi2, dphy_rstz));
+	v4l2_info(sd, "RESETN: 0x%x\n", dw_readl(csi2, resetn));
+	v4l2_info(sd, "PHY_STATE: 0x%x\n", dw_readl(csi2, phy_state));
+	v4l2_info(sd, "DATA_IDS_1: 0x%x\n", dw_readl(csi2, data_ids_1));
+	v4l2_info(sd, "DATA_IDS_2: 0x%x\n", dw_readl(csi2, data_ids_2));
+	v4l2_info(sd, "ERR1: 0x%x\n", dw_readl(csi2, err1));
+	v4l2_info(sd, "ERR2: 0x%x\n", dw_readl(csi2, err2));
+	v4l2_info(sd, "MSK1: 0x%x\n", dw_readl(csi2, msk1));
+	v4l2_info(sd, "MSK2: 0x%x\n", dw_readl(csi2, msk2));
+	v4l2_info(sd, "PHY_TST_CTRL0: 0x%x\n", dw_readl(csi2, phy_tst_ctrl0));
+	v4l2_info(sd, "PHY_TST_CTRL1: 0x%x\n", dw_readl(csi2, phy_tst_ctrl1));
 
 	return 0;
 }
@@ -719,7 +746,7 @@ static int csi2_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	csi2->dev = &pdev->dev;
-
+	csi2->regs = &dw_csi2_v0;
 	v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops);
 	v4l2_set_subdevdata(&csi2->sd, &pdev->dev);
 	csi2->sd.internal_ops = &csi2_internal_ops;
@@ -774,7 +801,7 @@ static void csi2_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id csi2_dt_ids[] = {
-	{ .compatible = "fsl,imx6-mipi-csi2", },
+	{ .compatible = "fsl,imx6-mipi-csi2"},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, csi2_dt_ids);

-- 
2.34.1


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

* [PATCH v2 11/32] media: staging: media: imx6-mipi-csi2: use devm_platform_ioremap_resource() simplify code
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (9 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 10/32] media: staging: media: imx6-mipi-csi2: use register structure to match hardware Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 12/32] media: staging: media: imx6-mipi-csi2: move probe part to imx6-csi2.c Frank Li
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use devm_platform_ioremap_resource() simplify code. No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index cef9a5dbca40c94a36d5d8473d3b7d9806381bf9..3956c352a27ae6d962e74a4ce7733946574668ef 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -738,7 +738,6 @@ static void csi2_nf_cleanup(void *data)
 static int csi2_probe(struct platform_device *pdev)
 {
 	struct csi2_dev *csi2;
-	struct resource *res;
 	int i, ret;
 
 	csi2 = devm_kzalloc(&pdev->dev, sizeof(*csi2), GFP_KERNEL);
@@ -772,15 +771,10 @@ static int csi2_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		v4l2_err(&csi2->sd, "failed to get platform resources\n");
-		return -ENODEV;
-	}
-
-	csi2->base = devm_ioremap(&pdev->dev, res->start, PAGE_SIZE);
-	if (!csi2->base)
-		return -ENOMEM;
+	csi2->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(csi2->base))
+		return dev_err_probe(&pdev->dev, -ENOMEM,
+				     "failed to get platform resources");
 
 	devm_mutex_init(&pdev->dev, &csi2->lock);
 

-- 
2.34.1


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

* [PATCH v2 12/32] media: staging: media: imx6-mipi-csi2: move probe part to imx6-csi2.c
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (10 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 11/32] media: staging: media: imx6-mipi-csi2: use devm_platform_ioremap_resource() simplify code Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 13/32] media: staging: media: imx6-mipi-csi2: move sd imx6's specific initialization into imx6-sci2.c Frank Li
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Prepare create common dw mipi csi2 library from imx6-mipi-csi2.c.

Move probe part to imx6-csi.c.

Rename struct csi2_dev to struct dw_mipi_csi2_dev and move it
include/media/dw-mipi-csi2.h.

Create two API dw_mipi_csi2_init() and dw_mipi_csi2_deinit().

No functional change.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/Makefile         |   2 +-
 drivers/staging/media/imx/imx6-csi2.c      |  61 ++++++++++++++
 drivers/staging/media/imx/imx6-mipi-csi2.c | 130 ++++++++---------------------
 include/media/dw-mipi-csi2.h               |  62 ++++++++++++++
 4 files changed, 159 insertions(+), 96 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
index 330e0825f506bd98d6a8093a58d3b7d06a94a626..064a6c6c069aa440c72a483080cbedf89d370193 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -11,4 +11,4 @@ imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media-csi.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-mipi-csi2.o
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-mipi-csi2.o imx6-csi2.o
diff --git a/drivers/staging/media/imx/imx6-csi2.c b/drivers/staging/media/imx/imx6-csi2.c
new file mode 100644
index 0000000000000000000000000000000000000000..72eff685fad99b3def46cf2866565191b7de9a8b
--- /dev/null
+++ b/drivers/staging/media/imx/imx6-csi2.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MIPI CSI-2 Receiver Subdev for Freescale i.MX6 SOC.
+ *
+ * Copyright (c) 2012-2017 Mentor Graphics Inc.
+ */
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <media/dw-mipi-csi2.h>
+#include "imx-media.h"
+
+struct imx6_csi2 {
+	struct dw_mipi_csi2_dev dw;
+};
+
+static int csi2_probe(struct platform_device *pdev)
+{
+	struct imx6_csi2 *csi2;
+
+	csi2 = devm_kzalloc(&pdev->dev, sizeof(*csi2), GFP_KERNEL);
+	if (!csi2)
+		return -ENOMEM;
+
+	return dw_mipi_csi2_init(pdev, &csi2->dw, NULL);
+}
+
+static void csi2_remove(struct platform_device *pdev)
+{
+	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dw_mipi_csi2_dev(sd);
+
+	dw_mipi_csi2_deinit(csi2);
+}
+
+static const struct of_device_id csi2_dt_ids[] = {
+	{ .compatible = "fsl,imx6-mipi-csi2"},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, csi2_dt_ids);
+
+static struct platform_driver csi2_driver = {
+	.driver = {
+		.name = "imx6-mipi-csi2",
+		.of_match_table = csi2_dt_ids,
+	},
+	.probe = csi2_probe,
+	.remove = csi2_remove,
+};
+
+module_platform_driver(csi2_driver);
+
+MODULE_DESCRIPTION("i.MX5/6 MIPI CSI-2 Receiver driver");
+MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 3956c352a27ae6d962e74a4ce7733946574668ef..29b27a58d9bcaf882d7f434605ee7b424b2588bd 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2012-2017 Mentor Graphics Inc.
  */
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -12,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
+#include <media/dw-mipi-csi2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
@@ -19,15 +21,6 @@
 #include <media/v4l2-subdev.h>
 #include "imx-media.h"
 
-/*
- * there must be 5 pads: 1 input pad from sensor, and
- * the 4 virtual channel output pads
- */
-#define CSI2_SINK_PAD		0
-#define CSI2_NUM_SINK_PADS	1
-#define CSI2_NUM_SRC_PADS	4
-#define CSI2_NUM_PADS		5
-
 /*
  * The default maximum bit-rate per lane in Mbps, if the
  * source subdev does not provide V4L2_CID_LINK_FREQ.
@@ -51,31 +44,6 @@ struct dw_csi2_regs {
 	u32	phy_tst_ctrl1;
 };
 
-struct csi2_dev {
-	struct device			*dev;
-	struct v4l2_subdev		sd;
-	struct v4l2_async_notifier	notifier;
-	struct media_pad		pad[CSI2_NUM_PADS];
-	void __iomem			*base;
-	const struct dw_csi2_regs	*regs;
-
-	struct clk_bulk_data		*clks;
-	int				num_clks;
-
-	struct v4l2_subdev		*remote;
-	unsigned int			remote_pad;
-	unsigned short			data_lanes;
-
-	/* lock to protect all members below */
-	struct mutex			lock;
-
-	struct v4l2_mbus_framefmt	format_mbus;
-
-	int				stream_count;
-	struct v4l2_subdev		*src_sd;
-	bool				sink_linked[CSI2_NUM_SRC_PADS];
-};
-
 #define DEVICE_NAME "imx6-mipi-csi2"
 
 /* Help check wrong access unexisted register at difference IP version */
@@ -100,7 +68,7 @@ static const struct dw_csi2_regs dw_csi2_v0 = {
 	.phy_tst_ctrl1 = DW_REG(0x34),
 };
 
-static int dw_csi2_reg_err(struct csi2_dev *csi2, const char *name)
+static int dw_csi2_reg_err(struct dw_mipi_csi2_dev *csi2, const char *name)
 {
 	dev_err_once(csi2->dev, "access to unexisted register: %s", name);
 	return 0;
@@ -134,14 +102,11 @@ dw_csi2_reg_err(csi2, #__name))
 #define CSI2IPU_GASKET		0xf00
 #define CSI2IPU_YUV422_YUYV	BIT(2)
 
-static inline struct csi2_dev *sd_to_dev(struct v4l2_subdev *sdev)
-{
-	return container_of(sdev, struct csi2_dev, sd);
-}
+#define sd_to_dev sd_to_dw_mipi_csi2_dev
 
-static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
+static inline struct dw_mipi_csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
 {
-	return container_of(n, struct csi2_dev, notifier);
+	return container_of(n, struct dw_mipi_csi2_dev, notifier);
 }
 
 /*
@@ -172,7 +137,7 @@ static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
  * steps 5 and 7.
  */
 
-static void csi2_enable(struct csi2_dev *csi2, bool enable)
+static void csi2_enable(struct dw_mipi_csi2_dev *csi2, bool enable)
 {
 	if (enable) {
 		dw_writel(csi2, 0x1, phy_shutdownz);
@@ -185,12 +150,12 @@ static void csi2_enable(struct csi2_dev *csi2, bool enable)
 	}
 }
 
-static void csi2_set_lanes(struct csi2_dev *csi2, unsigned int lanes)
+static void csi2_set_lanes(struct dw_mipi_csi2_dev *csi2, unsigned int lanes)
 {
 	dw_writel(csi2, lanes - 1, n_lanes);
 }
 
-static void dw_mipi_csi2_phy_write(struct csi2_dev *csi2,
+static void dw_mipi_csi2_phy_write(struct dw_mipi_csi2_dev *csi2,
 				   u32 test_code, u32 test_data)
 {
 	/* Clear PHY test interface */
@@ -243,7 +208,7 @@ static int max_mbps_to_hsfreqrange_sel(u32 max_mbps)
 	return -EINVAL;
 }
 
-static int csi2_dphy_init(struct csi2_dev *csi2)
+static int csi2_dphy_init(struct dw_mipi_csi2_dev *csi2)
 {
 	struct v4l2_ctrl *ctrl;
 	u32 mbps_per_lane;
@@ -270,7 +235,7 @@ static int csi2_dphy_init(struct csi2_dev *csi2)
  * Waits for ultra-low-power state on D-PHY clock lane. This is currently
  * unused and may not be needed at all, but keep around just in case.
  */
-static int __maybe_unused csi2_dphy_wait_ulp(struct csi2_dev *csi2)
+static int __maybe_unused csi2_dphy_wait_ulp(struct dw_mipi_csi2_dev *csi2)
 {
 	u32 reg;
 	int ret;
@@ -294,7 +259,7 @@ static int __maybe_unused csi2_dphy_wait_ulp(struct csi2_dev *csi2)
 }
 
 /* Waits for low-power LP-11 state on data and clock lanes. */
-static void csi2_dphy_wait_stopstate(struct csi2_dev *csi2, unsigned int lanes)
+static void csi2_dphy_wait_stopstate(struct dw_mipi_csi2_dev *csi2, unsigned int lanes)
 {
 	u32 mask, reg;
 	int ret;
@@ -309,7 +274,7 @@ static void csi2_dphy_wait_stopstate(struct csi2_dev *csi2, unsigned int lanes)
 }
 
 /* Wait for active clock on the clock lane. */
-static int csi2_dphy_wait_clock_lane(struct csi2_dev *csi2)
+static int csi2_dphy_wait_clock_lane(struct dw_mipi_csi2_dev *csi2)
 {
 	u32 reg;
 	int ret;
@@ -326,7 +291,7 @@ static int csi2_dphy_wait_clock_lane(struct csi2_dev *csi2)
 }
 
 /* Setup the i.MX CSI2IPU Gasket */
-static void csi2ipu_gasket_init(struct csi2_dev *csi2)
+static void csi2ipu_gasket_init(struct dw_mipi_csi2_dev *csi2)
 {
 	u32 reg = 0;
 
@@ -342,7 +307,7 @@ static void csi2ipu_gasket_init(struct csi2_dev *csi2)
 	writel(reg, csi2->base + CSI2IPU_GASKET);
 }
 
-static int csi2_get_active_lanes(struct csi2_dev *csi2, unsigned int *lanes)
+static int csi2_get_active_lanes(struct dw_mipi_csi2_dev *csi2, unsigned int *lanes)
 {
 	struct v4l2_mbus_config mbus_config = { 0 };
 	int ret;
@@ -379,7 +344,7 @@ static int csi2_get_active_lanes(struct csi2_dev *csi2, unsigned int *lanes)
 	return 0;
 }
 
-static int csi2_start(struct csi2_dev *csi2)
+static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 {
 	unsigned int lanes;
 	int ret;
@@ -435,7 +400,7 @@ static int csi2_start(struct csi2_dev *csi2)
 	return ret;
 }
 
-static void csi2_stop(struct csi2_dev *csi2)
+static void csi2_stop(struct dw_mipi_csi2_dev *csi2)
 {
 	/* stop upstream */
 	v4l2_subdev_call(csi2->src_sd, video, s_stream, 0);
@@ -451,7 +416,7 @@ static void csi2_stop(struct csi2_dev *csi2)
 
 static int csi2_s_stream(struct v4l2_subdev *sd, int enable)
 {
-	struct csi2_dev *csi2 = sd_to_dev(sd);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	int i, ret = 0;
 
 	guard(mutex)(&csi2->lock);
@@ -493,7 +458,7 @@ static int csi2_link_setup(struct media_entity *entity,
 			   const struct media_pad *remote, u32 flags)
 {
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
-	struct csi2_dev *csi2 = sd_to_dev(sd);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_subdev *remote_sd;
 	int ret = 0;
 
@@ -528,7 +493,7 @@ static int csi2_link_setup(struct media_entity *entity,
 }
 
 static struct v4l2_mbus_framefmt *
-__csi2_get_fmt(struct csi2_dev *csi2, struct v4l2_subdev_state *sd_state,
+__csi2_get_fmt(struct dw_mipi_csi2_dev *csi2, struct v4l2_subdev_state *sd_state,
 	       unsigned int pad, enum v4l2_subdev_format_whence which)
 {
 	if (which == V4L2_SUBDEV_FORMAT_TRY)
@@ -541,7 +506,7 @@ static int csi2_get_fmt(struct v4l2_subdev *sd,
 			struct v4l2_subdev_state *sd_state,
 			struct v4l2_subdev_format *sdformat)
 {
-	struct csi2_dev *csi2 = sd_to_dev(sd);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
 
 	guard(mutex)(&csi2->lock);
@@ -557,7 +522,7 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 			struct v4l2_subdev_state *sd_state,
 			struct v4l2_subdev_format *sdformat)
 {
-	struct csi2_dev *csi2 = sd_to_dev(sd);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
 
 	if (sdformat->pad >= CSI2_NUM_PADS)
@@ -581,7 +546,7 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 
 static int csi2_registered(struct v4l2_subdev *sd)
 {
-	struct csi2_dev *csi2 = sd_to_dev(sd);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 
 	/* set a default mbus format  */
 	return imx_media_init_mbus_fmt(&csi2->format_mbus,
@@ -594,7 +559,7 @@ static int csi2_registered(struct v4l2_subdev *sd)
 
 static int csi2_log_status(struct v4l2_subdev *sd)
 {
-	struct csi2_dev *csi2 = sd_to_dev(sd);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 
 	v4l2_info(sd, "-----MIPI CSI status-----\n");
 	v4l2_info(sd, "VERSION: 0x%x\n", dw_readl(csi2, version));
@@ -649,7 +614,7 @@ static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
 			     struct v4l2_subdev *sd,
 			     struct v4l2_async_connection *asd)
 {
-	struct csi2_dev *csi2 = notifier_to_dev(notifier);
+	struct dw_mipi_csi2_dev *csi2 = notifier_to_dev(notifier);
 	struct media_pad *sink = &csi2->sd.entity.pads[CSI2_SINK_PAD];
 	int pad;
 
@@ -672,7 +637,7 @@ static void csi2_notify_unbind(struct v4l2_async_notifier *notifier,
 			       struct v4l2_subdev *sd,
 			       struct v4l2_async_connection *asd)
 {
-	struct csi2_dev *csi2 = notifier_to_dev(notifier);
+	struct dw_mipi_csi2_dev *csi2 = notifier_to_dev(notifier);
 
 	csi2->remote = NULL;
 }
@@ -682,7 +647,7 @@ static const struct v4l2_async_notifier_operations csi2_notify_ops = {
 	.unbind = csi2_notify_unbind,
 };
 
-static int csi2_async_register(struct csi2_dev *csi2)
+static int csi2_async_register(struct dw_mipi_csi2_dev *csi2)
 {
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
@@ -729,21 +694,17 @@ static int csi2_async_register(struct csi2_dev *csi2)
 
 static void csi2_nf_cleanup(void *data)
 {
-	struct csi2_dev *csi2 = data;
+	struct dw_mipi_csi2_dev *csi2 = data;
 
 	v4l2_async_nf_unregister(&csi2->notifier);
 	v4l2_async_nf_cleanup(&csi2->notifier);
 }
 
-static int csi2_probe(struct platform_device *pdev)
+int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi2,
+		      const struct dw_mipi_csi2_config *config)
 {
-	struct csi2_dev *csi2;
 	int i, ret;
 
-	csi2 = devm_kzalloc(&pdev->dev, sizeof(*csi2), GFP_KERNEL);
-	if (!csi2)
-		return -ENOMEM;
-
 	csi2->dev = &pdev->dev;
 	csi2->regs = &dw_csi2_v0;
 	v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops);
@@ -785,32 +746,11 @@ static int csi2_probe(struct platform_device *pdev)
 	return csi2_async_register(csi2);
 
 }
+EXPORT_SYMBOL_GPL(dw_mipi_csi2_init);
 
-static void csi2_remove(struct platform_device *pdev)
+void dw_mipi_csi2_deinit(struct dw_mipi_csi2_dev *csi2)
 {
-	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
-
-	v4l2_async_unregister_subdev(sd);
-	media_entity_cleanup(&sd->entity);
+	v4l2_async_unregister_subdev(&csi2->sd);
+	media_entity_cleanup(&csi2->sd.entity);
 }
-
-static const struct of_device_id csi2_dt_ids[] = {
-	{ .compatible = "fsl,imx6-mipi-csi2"},
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, csi2_dt_ids);
-
-static struct platform_driver csi2_driver = {
-	.driver = {
-		.name = DEVICE_NAME,
-		.of_match_table = csi2_dt_ids,
-	},
-	.probe = csi2_probe,
-	.remove = csi2_remove,
-};
-
-module_platform_driver(csi2_driver);
-
-MODULE_DESCRIPTION("i.MX5/6 MIPI CSI-2 Receiver driver");
-MODULE_AUTHOR("Steve Longerbeam <steve_longerbeam@mentor.com>");
-MODULE_LICENSE("GPL");
+EXPORT_SYMBOL_GPL(dw_mipi_csi2_deinit);
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e656f09c81db9dc9f232ed061f70803a5478c85
--- /dev/null
+++ b/include/media/dw-mipi-csi2.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __DW_MIPI_CSI2_COMMON_
+#define __DW_MIPI_CSI2_COMMON_
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-mc.h>
+#include <media/v4l2-subdev.h>
+
+struct dw_mipi_csi2_config {
+};
+
+/*
+ * there must be 5 pads: 1 input pad from sensor, and
+ * the 4 virtual channel output pads
+ */
+#define CSI2_SINK_PAD		0
+#define CSI2_NUM_SINK_PADS	1
+#define CSI2_NUM_SRC_PADS	4
+#define CSI2_NUM_PADS		5
+
+struct dw_mipi_csi2_dev {
+	struct device			*dev;
+	struct v4l2_subdev		sd;
+	struct v4l2_async_notifier	notifier;
+	struct media_pad		pad[CSI2_NUM_PADS];
+	void __iomem			*base;
+	const struct dw_csi2_regs	*regs;
+
+	struct clk_bulk_data		*clks;
+	int				num_clks;
+
+	struct v4l2_subdev		*remote;
+	unsigned int			remote_pad;
+	unsigned short			data_lanes;
+
+	/* lock to protect all members below */
+	struct mutex			lock;
+
+	struct v4l2_mbus_framefmt	format_mbus;
+
+	int				stream_count;
+	struct v4l2_subdev		*src_sd;
+	bool				sink_linked[CSI2_NUM_SRC_PADS];
+};
+
+static inline struct dw_mipi_csi2_dev *
+sd_to_dw_mipi_csi2_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct dw_mipi_csi2_dev, sd);
+}
+
+int dw_mipi_csi2_init(struct platform_device *pdev,
+		      struct dw_mipi_csi2_dev *csi2,
+		      const struct dw_mipi_csi2_config *config);
+
+void dw_mipi_csi2_deinit(struct dw_mipi_csi2_dev *csi2);
+
+#endif
+

-- 
2.34.1


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

* [PATCH v2 13/32] media: staging: media: imx6-mipi-csi2: move sd imx6's specific initialization into imx6-sci2.c
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (11 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 12/32] media: staging: media: imx6-mipi-csi2: move probe part to imx6-csi2.c Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 14/32] media: staging: media: imx6-mipi-csi2: move csi2ipu_gasket_init() to imx6-csi2.c Frank Li
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Move imx6's specific sd's owner, name, csi2_internal_ops, grp_id into
imx6-sci2.c.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-csi2.c      | 23 +++++++++++++++++++++++
 drivers/staging/media/imx/imx6-mipi-csi2.c | 29 ++++++-----------------------
 include/media/dw-mipi-csi2.h               |  4 ++++
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-csi2.c b/drivers/staging/media/imx/imx6-csi2.c
index 72eff685fad99b3def46cf2866565191b7de9a8b..66274d8d73b67b35682bb82a9eb745bb24da7ae4 100644
--- a/drivers/staging/media/imx/imx6-csi2.c
+++ b/drivers/staging/media/imx/imx6-csi2.c
@@ -19,6 +19,29 @@ struct imx6_csi2 {
 	struct dw_mipi_csi2_dev dw;
 };
 
+static int csi2_registered(struct v4l2_subdev *sd)
+{
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dw_mipi_csi2_dev(sd);
+
+	/* set a default mbus format  */
+	return imx_media_init_mbus_fmt(&csi2->format_mbus,
+				      IMX_MEDIA_DEF_PIX_WIDTH,
+				      IMX_MEDIA_DEF_PIX_HEIGHT, 0,
+				      V4L2_FIELD_NONE, NULL);
+}
+
+static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
+	.init_state = imx_media_init_state,
+	.registered = csi2_registered,
+};
+
+static const struct dw_mipi_csi2_config imx6_config = {
+	.module = THIS_MODULE,
+	.name = "imx6-mipi-csi2",
+	.internal_ops = &csi2_internal_ops,
+	.grp_id = IMX_MEDIA_GRP_ID_CSI2,
+};
+
 static int csi2_probe(struct platform_device *pdev)
 {
 	struct imx6_csi2 *csi2;
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 29b27a58d9bcaf882d7f434605ee7b424b2588bd..40a146faaa9c79304b1e1f16e608b3b10eae6c80 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -15,11 +15,11 @@
 #include <linux/platform_device.h>
 #include <media/dw-mipi-csi2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-mc.h>
 #include <media/v4l2-subdev.h>
-#include "imx-media.h"
 
 /*
  * The default maximum bit-rate per lane in Mbps, if the
@@ -44,8 +44,6 @@ struct dw_csi2_regs {
 	u32	phy_tst_ctrl1;
 };
 
-#define DEVICE_NAME "imx6-mipi-csi2"
-
 /* Help check wrong access unexisted register at difference IP version */
 #define DW_REG_EXIST		0x80000000
 #define DW_REG(x)		(DW_REG_EXIST | (x))
@@ -544,17 +542,6 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int csi2_registered(struct v4l2_subdev *sd)
-{
-	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
-
-	/* set a default mbus format  */
-	return imx_media_init_mbus_fmt(&csi2->format_mbus,
-				      IMX_MEDIA_DEF_PIX_WIDTH,
-				      IMX_MEDIA_DEF_PIX_HEIGHT, 0,
-				      V4L2_FIELD_NONE, NULL);
-}
-
 /* --------------- CORE OPS --------------- */
 
 static int csi2_log_status(struct v4l2_subdev *sd)
@@ -605,11 +592,6 @@ static const struct v4l2_subdev_ops csi2_subdev_ops = {
 	.pad = &csi2_pad_ops,
 };
 
-static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
-	.init_state = imx_media_init_state,
-	.registered = csi2_registered,
-};
-
 static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
 			     struct v4l2_subdev *sd,
 			     struct v4l2_async_connection *asd)
@@ -709,14 +691,15 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	csi2->regs = &dw_csi2_v0;
 	v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops);
 	v4l2_set_subdevdata(&csi2->sd, &pdev->dev);
-	csi2->sd.internal_ops = &csi2_internal_ops;
 	csi2->sd.entity.ops = &csi2_entity_ops;
 	csi2->sd.dev = &pdev->dev;
-	csi2->sd.owner = THIS_MODULE;
 	csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
-	strscpy(csi2->sd.name, DEVICE_NAME, sizeof(csi2->sd.name));
 	csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
-	csi2->sd.grp_id = IMX_MEDIA_GRP_ID_CSI2;
+
+	csi2->sd.owner = config->module;
+	strscpy(csi2->sd.name, config->name, sizeof(csi2->sd.name));
+	csi2->sd.internal_ops = config->internal_ops;
+	csi2->sd.grp_id = config->grp_id;
 
 	for (i = 0; i < CSI2_NUM_PADS; i++) {
 		csi2->pad[i].flags = (i == CSI2_SINK_PAD) ?
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index 4e656f09c81db9dc9f232ed061f70803a5478c85..dfd25e23ea93fd53b064471b6a9557ef9c070fe7 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -10,6 +10,10 @@
 #include <media/v4l2-subdev.h>
 
 struct dw_mipi_csi2_config {
+	struct module *module;
+	const char *name;
+	int grp_id;
+	const struct v4l2_subdev_internal_ops *internal_ops;
 };
 
 /*

-- 
2.34.1


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

* [PATCH v2 14/32] media: staging: media: imx6-mipi-csi2: move csi2ipu_gasket_init() to imx6-csi2.c
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (12 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 13/32] media: staging: media: imx6-mipi-csi2: move sd imx6's specific initialization into imx6-sci2.c Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 15/32] media: staging: media: imx6-mipi-csi2: move number pad macro define into imx6-csi2.c Frank Li
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Move platform specific csi2ipu_gasket_init() to imx6-csi2.c.

Create callback function in struct dw_mipi_csi2_config.

Prepare create common library for dw MIPI CSI2.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-csi2.c      | 28 +++++++++++++++++++++++++++-
 drivers/staging/media/imx/imx6-mipi-csi2.c | 28 +++-------------------------
 include/media/dw-mipi-csi2.h               |  6 ++++++
 3 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-csi2.c b/drivers/staging/media/imx/imx6-csi2.c
index 66274d8d73b67b35682bb82a9eb745bb24da7ae4..b7ea710df07cba33465d79ef57be4792c503958a 100644
--- a/drivers/staging/media/imx/imx6-csi2.c
+++ b/drivers/staging/media/imx/imx6-csi2.c
@@ -15,10 +15,35 @@
 #include <media/dw-mipi-csi2.h>
 #include "imx-media.h"
 
+/*
+ * i.MX CSI2IPU Gasket registers follow. The CSI2IPU gasket is
+ * not part of the MIPI CSI-2 core, but its registers fall in the
+ * same register map range.
+ */
+#define CSI2IPU_GASKET		0xf00
+#define CSI2IPU_YUV422_YUYV	BIT(2)
+
 struct imx6_csi2 {
 	struct dw_mipi_csi2_dev dw;
 };
 
+/* Setup the i.MX CSI2IPU Gasket */
+static void csi2ipu_gasket_init(struct dw_mipi_csi2_dev *csi2)
+{
+	u32 reg = 0;
+
+	switch (csi2->format_mbus.code) {
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+		reg = CSI2IPU_YUV422_YUYV;
+		break;
+	default:
+		break;
+	}
+
+	writel(reg, csi2->base + CSI2IPU_GASKET);
+}
+
 static int csi2_registered(struct v4l2_subdev *sd)
 {
 	struct dw_mipi_csi2_dev *csi2 = sd_to_dw_mipi_csi2_dev(sd);
@@ -40,6 +65,7 @@ static const struct dw_mipi_csi2_config imx6_config = {
 	.name = "imx6-mipi-csi2",
 	.internal_ops = &csi2_internal_ops,
 	.grp_id = IMX_MEDIA_GRP_ID_CSI2,
+	.gasket_init = csi2ipu_gasket_init,
 };
 
 static int csi2_probe(struct platform_device *pdev)
@@ -50,7 +76,7 @@ static int csi2_probe(struct platform_device *pdev)
 	if (!csi2)
 		return -ENOMEM;
 
-	return dw_mipi_csi2_init(pdev, &csi2->dw, NULL);
+	return dw_mipi_csi2_init(pdev, &csi2->dw, &imx6_config);
 }
 
 static void csi2_remove(struct platform_device *pdev)
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 40a146faaa9c79304b1e1f16e608b3b10eae6c80..4127b927a73aaf2eada1636fcc6101155f41b334 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -92,13 +92,6 @@ dw_csi2_reg_err(csi2, #__name))
 #define PHY_TESTCLK		BIT(1)
 
 #define PHY_TESTEN		BIT(16)
-/*
- * i.MX CSI2IPU Gasket registers follow. The CSI2IPU gasket is
- * not part of the MIPI CSI-2 core, but its registers fall in the
- * same register map range.
- */
-#define CSI2IPU_GASKET		0xf00
-#define CSI2IPU_YUV422_YUYV	BIT(2)
 
 #define sd_to_dev sd_to_dw_mipi_csi2_dev
 
@@ -288,23 +281,6 @@ static int csi2_dphy_wait_clock_lane(struct dw_mipi_csi2_dev *csi2)
 	return 0;
 }
 
-/* Setup the i.MX CSI2IPU Gasket */
-static void csi2ipu_gasket_init(struct dw_mipi_csi2_dev *csi2)
-{
-	u32 reg = 0;
-
-	switch (csi2->format_mbus.code) {
-	case MEDIA_BUS_FMT_YUYV8_2X8:
-	case MEDIA_BUS_FMT_YUYV8_1X16:
-		reg = CSI2IPU_YUV422_YUYV;
-		break;
-	default:
-		break;
-	}
-
-	writel(reg, csi2->base + CSI2IPU_GASKET);
-}
-
 static int csi2_get_active_lanes(struct dw_mipi_csi2_dev *csi2, unsigned int *lanes)
 {
 	struct v4l2_mbus_config mbus_config = { 0 };
@@ -352,7 +328,8 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 		return ret;
 
 	/* setup the gasket */
-	csi2ipu_gasket_init(csi2);
+	if (csi2->config && csi2->config->gasket_init)
+		csi2->config->gasket_init(csi2);
 
 	/* Step 3 */
 	ret = csi2_dphy_init(csi2);
@@ -700,6 +677,7 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	strscpy(csi2->sd.name, config->name, sizeof(csi2->sd.name));
 	csi2->sd.internal_ops = config->internal_ops;
 	csi2->sd.grp_id = config->grp_id;
+	csi2->config = config;
 
 	for (i = 0; i < CSI2_NUM_PADS; i++) {
 		csi2->pad[i].flags = (i == CSI2_SINK_PAD) ?
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index dfd25e23ea93fd53b064471b6a9557ef9c070fe7..d3e1c334df692c5dff10b467d759fe4da45b7b5f 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -9,11 +9,15 @@
 #include <media/v4l2-mc.h>
 #include <media/v4l2-subdev.h>
 
+struct dw_mipi_csi2_dev;
+
 struct dw_mipi_csi2_config {
 	struct module *module;
 	const char *name;
 	int grp_id;
 	const struct v4l2_subdev_internal_ops *internal_ops;
+	/* Deprecated, should go through phy interface */
+	void (*gasket_init)(struct dw_mipi_csi2_dev *dev);
 };
 
 /*
@@ -48,6 +52,8 @@ struct dw_mipi_csi2_dev {
 	int				stream_count;
 	struct v4l2_subdev		*src_sd;
 	bool				sink_linked[CSI2_NUM_SRC_PADS];
+
+	const struct dw_mipi_csi2_config *config;
 };
 
 static inline struct dw_mipi_csi2_dev *

-- 
2.34.1


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

* [PATCH v2 15/32] media: staging: media: imx6-mipi-csi2: move number pad macro define into imx6-csi2.c
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (13 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 14/32] media: staging: media: imx6-mipi-csi2: move csi2ipu_gasket_init() to imx6-csi2.c Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 16/32] media: staging: media: imx6-mipi-csi2: move dphy init part to imx6-csi2.c Frank Li
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Move number of pad macro to imx6-csi2.c. The number of pads is platform
related feature.

This version just support maximum 32 pads.

Prepare to create common library for dw MIPI CSI2 controller.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-csi2.c      | 12 ++++++++++++
 drivers/staging/media/imx/imx6-mipi-csi2.c | 27 ++++++++++++++++++---------
 include/media/dw-mipi-csi2.h               | 21 +++++++++------------
 3 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-csi2.c b/drivers/staging/media/imx/imx6-csi2.c
index b7ea710df07cba33465d79ef57be4792c503958a..062db72a36ef294566272d9f39d82e9414640e9a 100644
--- a/drivers/staging/media/imx/imx6-csi2.c
+++ b/drivers/staging/media/imx/imx6-csi2.c
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2012-2017 Mentor Graphics Inc.
  */
+#include <linux/bits.h>
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -60,12 +61,23 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
 	.registered = csi2_registered,
 };
 
+/*
+ * there must be 5 pads: 1 input pad from sensor, and
+ * the 4 virtual channel output pads
+ */
+#define CSI2_SINK_PAD		0
+#define CSI2_NUM_SINK_PADS	1
+#define CSI2_NUM_SRC_PADS	4
+#define CSI2_NUM_PADS		5
+
 static const struct dw_mipi_csi2_config imx6_config = {
 	.module = THIS_MODULE,
 	.name = "imx6-mipi-csi2",
 	.internal_ops = &csi2_internal_ops,
 	.grp_id = IMX_MEDIA_GRP_ID_CSI2,
 	.gasket_init = csi2ipu_gasket_init,
+	.num_pads = CSI2_NUM_PADS,
+	.sink_pad_mask = BIT(CSI2_NUM_SINK_PADS),
 };
 
 static int csi2_probe(struct platform_device *pdev)
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 4127b927a73aaf2eada1636fcc6101155f41b334..546c6e7c5d13f3be618fc3eeca780695ead6bfe5 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -399,11 +399,11 @@ static int csi2_s_stream(struct v4l2_subdev *sd, int enable)
 	if (!csi2->src_sd)
 		return -EPIPE;
 
-	for (i = 0; i < CSI2_NUM_SRC_PADS; i++) {
+	for (i = 0; i < csi2->num_sink_pads; i++) {
 		if (csi2->sink_linked[i])
 			break;
 	}
-	if (i >= CSI2_NUM_SRC_PADS)
+	if (i >= csi2->num_sink_pads)
 		return -EPIPE;
 
 	/*
@@ -500,7 +500,7 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
 
-	if (sdformat->pad >= CSI2_NUM_PADS)
+	if (sdformat->pad >= (csi2->num_src_pads + csi2->num_sink_pads))
 		return -EINVAL;
 
 	guard(mutex)(&csi2->lock);
@@ -509,7 +509,7 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 		return -EBUSY;
 
 	/* Output pads mirror active input pad, no limits on input pads */
-	if (sdformat->pad != CSI2_SINK_PAD)
+	if (!(csi2->config->sink_pad_mask & BIT(sdformat->pad)))
 		sdformat->format = csi2->format_mbus;
 
 	fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
@@ -574,7 +574,8 @@ static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
 			     struct v4l2_async_connection *asd)
 {
 	struct dw_mipi_csi2_dev *csi2 = notifier_to_dev(notifier);
-	struct media_pad *sink = &csi2->sd.entity.pads[CSI2_SINK_PAD];
+	int sink_index = ffs(csi2->config->sink_pad_mask) - 1;
+	struct media_pad *sink = &csi2->sd.entity.pads[sink_index];
 	int pad;
 
 	pad = media_entity_get_fwnode_pad(&sd->entity, asd->match.fwnode,
@@ -679,12 +680,20 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	csi2->sd.grp_id = config->grp_id;
 	csi2->config = config;
 
-	for (i = 0; i < CSI2_NUM_PADS; i++) {
-		csi2->pad[i].flags = (i == CSI2_SINK_PAD) ?
-		MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+	if (!config)
+		return -EINVAL;
+
+	for (i = 0; i < config->num_pads; i++) {
+		if (config->sink_pad_mask & BIT(i)) {
+			csi2->pad[i].flags = MEDIA_PAD_FL_SINK;
+			csi2->num_sink_pads++;
+		} else {
+			csi2->pad[i].flags = MEDIA_PAD_FL_SOURCE;
+			csi2->num_src_pads++;
+		}
 	}
 
-	ret = media_entity_pads_init(&csi2->sd.entity, CSI2_NUM_PADS,
+	ret = media_entity_pads_init(&csi2->sd.entity, config->num_pads,
 				     csi2->pad);
 	if (ret)
 		return ret;
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index d3e1c334df692c5dff10b467d759fe4da45b7b5f..12e1db1d149513fcd0db8c191c801cb144d18143 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -11,6 +11,8 @@
 
 struct dw_mipi_csi2_dev;
 
+#define DW_MAX_PAD_NUM		32
+
 struct dw_mipi_csi2_config {
 	struct module *module;
 	const char *name;
@@ -18,22 +20,18 @@ struct dw_mipi_csi2_config {
 	const struct v4l2_subdev_internal_ops *internal_ops;
 	/* Deprecated, should go through phy interface */
 	void (*gasket_init)(struct dw_mipi_csi2_dev *dev);
+	u32	num_pads;	/* Max 64 pad now */
+	u32	sink_pad_mask;
 };
 
-/*
- * there must be 5 pads: 1 input pad from sensor, and
- * the 4 virtual channel output pads
- */
-#define CSI2_SINK_PAD		0
-#define CSI2_NUM_SINK_PADS	1
-#define CSI2_NUM_SRC_PADS	4
-#define CSI2_NUM_PADS		5
-
 struct dw_mipi_csi2_dev {
 	struct device			*dev;
 	struct v4l2_subdev		sd;
 	struct v4l2_async_notifier	notifier;
-	struct media_pad		pad[CSI2_NUM_PADS];
+	struct media_pad		pad[DW_MAX_PAD_NUM];
+	int				num_src_pads;
+	int				num_sink_pads;
+
 	void __iomem			*base;
 	const struct dw_csi2_regs	*regs;
 
@@ -51,8 +49,7 @@ struct dw_mipi_csi2_dev {
 
 	int				stream_count;
 	struct v4l2_subdev		*src_sd;
-	bool				sink_linked[CSI2_NUM_SRC_PADS];
-
+	bool				sink_linked[DW_MAX_PAD_NUM];
 	const struct dw_mipi_csi2_config *config;
 };
 

-- 
2.34.1


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

* [PATCH v2 16/32] media: staging: media: imx6-mipi-csi2: move dphy init part to imx6-csi2.c
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (14 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 15/32] media: staging: media: imx6-mipi-csi2: move number pad macro define into imx6-csi2.c Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 17/32] media: staging: media: imx6-mipi-csi2: use runtime_pm frame to control clks Frank Li
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Move dphy init part to imx6-csi.c.

Prepare create common library for dw MIPI CSI2 controller.

Add callback for dphy_init in struct dw_mipi_csi2_config. New driver should
use phy interface.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-csi2.c      | 55 +++++++++++++++++++++++
 drivers/staging/media/imx/imx6-mipi-csi2.c | 72 ++++++------------------------
 include/media/dw-mipi-csi2.h               | 21 +++++++++
 3 files changed, 89 insertions(+), 59 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-csi2.c b/drivers/staging/media/imx/imx6-csi2.c
index 062db72a36ef294566272d9f39d82e9414640e9a..696644aa04c83b1f2877b2b2315202627d927e96 100644
--- a/drivers/staging/media/imx/imx6-csi2.c
+++ b/drivers/staging/media/imx/imx6-csi2.c
@@ -16,6 +16,12 @@
 #include <media/dw-mipi-csi2.h>
 #include "imx-media.h"
 
+/*
+ * The default maximum bit-rate per lane in Mbps, if the
+ * source subdev does not provide V4L2_CID_LINK_FREQ.
+ */
+#define CSI2_DEFAULT_MAX_MBPS	849
+
 /*
  * i.MX CSI2IPU Gasket registers follow. The CSI2IPU gasket is
  * not part of the MIPI CSI-2 core, but its registers fall in the
@@ -28,6 +34,54 @@ struct imx6_csi2 {
 	struct dw_mipi_csi2_dev dw;
 };
 
+static const struct {
+	u32 max_mbps;
+	u32 hsfreqrange_sel;
+} hsfreq_map[] = {
+	{ 90, 0x00}, {100, 0x20}, {110, 0x40}, {125, 0x02},
+	{140, 0x22}, {150, 0x42}, {160, 0x04}, {180, 0x24},
+	{200, 0x44}, {210, 0x06}, {240, 0x26}, {250, 0x46},
+	{270, 0x08}, {300, 0x28}, {330, 0x48}, {360, 0x2a},
+	{400, 0x4a}, {450, 0x0c}, {500, 0x2c}, {550, 0x0e},
+	{600, 0x2e}, {650, 0x10}, {700, 0x30}, {750, 0x12},
+	{800, 0x32}, {850, 0x14}, {900, 0x34}, {950, 0x54},
+	{1000, 0x74},
+};
+
+static int max_mbps_to_hsfreqrange_sel(u32 max_mbps)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hsfreq_map); i++)
+		if (hsfreq_map[i].max_mbps > max_mbps)
+			return hsfreq_map[i].hsfreqrange_sel;
+
+	return -EINVAL;
+}
+
+static int csi2_dphy_init(struct dw_mipi_csi2_dev *csi2)
+{
+	struct v4l2_ctrl *ctrl;
+	u32 mbps_per_lane;
+	int sel;
+
+	ctrl = v4l2_ctrl_find(csi2->src_sd->ctrl_handler,
+			      V4L2_CID_LINK_FREQ);
+	if (!ctrl)
+		mbps_per_lane = CSI2_DEFAULT_MAX_MBPS;
+	else
+		mbps_per_lane = DIV_ROUND_UP_ULL(2 * ctrl->qmenu_int[ctrl->val],
+						 USEC_PER_SEC);
+
+	sel = max_mbps_to_hsfreqrange_sel(mbps_per_lane);
+	if (sel < 0)
+		return sel;
+
+	dw_mipi_csi2_tstif_write(csi2, 0x44, sel);
+
+	return 0;
+}
+
 /* Setup the i.MX CSI2IPU Gasket */
 static void csi2ipu_gasket_init(struct dw_mipi_csi2_dev *csi2)
 {
@@ -74,6 +128,7 @@ static const struct dw_mipi_csi2_config imx6_config = {
 	.module = THIS_MODULE,
 	.name = "imx6-mipi-csi2",
 	.internal_ops = &csi2_internal_ops,
+	.dphy_init = csi2_dphy_init,
 	.grp_id = IMX_MEDIA_GRP_ID_CSI2,
 	.gasket_init = csi2ipu_gasket_init,
 	.num_pads = CSI2_NUM_PADS,
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 546c6e7c5d13f3be618fc3eeca780695ead6bfe5..23656291d808ccdfc47f36d1f7f5104698812eba 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -21,12 +21,6 @@
 #include <media/v4l2-mc.h>
 #include <media/v4l2-subdev.h>
 
-/*
- * The default maximum bit-rate per lane in Mbps, if the
- * source subdev does not provide V4L2_CID_LINK_FREQ.
- */
-#define CSI2_DEFAULT_MAX_MBPS	849
-
 struct dw_csi2_regs {
 	u32	version;
 	u32	n_lanes;
@@ -146,9 +140,11 @@ static void csi2_set_lanes(struct dw_mipi_csi2_dev *csi2, unsigned int lanes)
 	dw_writel(csi2, lanes - 1, n_lanes);
 }
 
-static void dw_mipi_csi2_phy_write(struct dw_mipi_csi2_dev *csi2,
-				   u32 test_code, u32 test_data)
+static int dw_mipi_csi2_phy_write(struct dw_mipi_tstif *tstif,
+				  u32 test_code, u32 test_data)
 {
+	struct dw_mipi_csi2_dev *csi2 = container_of(tstif, struct dw_mipi_csi2_dev, tstif);
+
 	/* Clear PHY test interface */
 	dw_writel(csi2, PHY_TESTCLR, phy_tst_ctrl0);
 	dw_writel(csi2, 0x0, phy_tst_ctrl1);
@@ -167,6 +163,8 @@ static void dw_mipi_csi2_phy_write(struct dw_mipi_csi2_dev *csi2,
 
 	/* Clear strobe signal */
 	dw_writel(csi2, 0x0, phy_tst_ctrl0);
+
+	return 0;
 }
 
 /*
@@ -174,54 +172,6 @@ static void dw_mipi_csi2_phy_write(struct dw_mipi_csi2_dev *csi2,
  * https://community.nxp.com/docs/DOC-94312. It assumes
  * a 27MHz D-PHY pll reference clock.
  */
-static const struct {
-	u32 max_mbps;
-	u32 hsfreqrange_sel;
-} hsfreq_map[] = {
-	{ 90, 0x00}, {100, 0x20}, {110, 0x40}, {125, 0x02},
-	{140, 0x22}, {150, 0x42}, {160, 0x04}, {180, 0x24},
-	{200, 0x44}, {210, 0x06}, {240, 0x26}, {250, 0x46},
-	{270, 0x08}, {300, 0x28}, {330, 0x48}, {360, 0x2a},
-	{400, 0x4a}, {450, 0x0c}, {500, 0x2c}, {550, 0x0e},
-	{600, 0x2e}, {650, 0x10}, {700, 0x30}, {750, 0x12},
-	{800, 0x32}, {850, 0x14}, {900, 0x34}, {950, 0x54},
-	{1000, 0x74},
-};
-
-static int max_mbps_to_hsfreqrange_sel(u32 max_mbps)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(hsfreq_map); i++)
-		if (hsfreq_map[i].max_mbps > max_mbps)
-			return hsfreq_map[i].hsfreqrange_sel;
-
-	return -EINVAL;
-}
-
-static int csi2_dphy_init(struct dw_mipi_csi2_dev *csi2)
-{
-	struct v4l2_ctrl *ctrl;
-	u32 mbps_per_lane;
-	int sel;
-
-	ctrl = v4l2_ctrl_find(csi2->src_sd->ctrl_handler,
-			      V4L2_CID_LINK_FREQ);
-	if (!ctrl)
-		mbps_per_lane = CSI2_DEFAULT_MAX_MBPS;
-	else
-		mbps_per_lane = DIV_ROUND_UP_ULL(2 * ctrl->qmenu_int[ctrl->val],
-						 USEC_PER_SEC);
-
-	sel = max_mbps_to_hsfreqrange_sel(mbps_per_lane);
-	if (sel < 0)
-		return sel;
-
-	dw_mipi_csi2_phy_write(csi2, 0x44, sel);
-
-	return 0;
-}
-
 /*
  * Waits for ultra-low-power state on D-PHY clock lane. This is currently
  * unused and may not be needed at all, but keep around just in case.
@@ -332,9 +282,11 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 		csi2->config->gasket_init(csi2);
 
 	/* Step 3 */
-	ret = csi2_dphy_init(csi2);
-	if (ret)
-		goto err_disable_clk;
+	if (csi2->config && csi2->config->dphy_init) {
+		ret = csi2->config->dphy_init(csi2);
+		if (ret)
+			goto err_disable_clk;
+	}
 
 	ret = csi2_get_active_lanes(csi2, &lanes);
 	if (ret)
@@ -680,6 +632,8 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	csi2->sd.grp_id = config->grp_id;
 	csi2->config = config;
 
+	csi2->tstif.write = dw_mipi_csi2_phy_write;
+
 	if (!config)
 		return -EINVAL;
 
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index 12e1db1d149513fcd0db8c191c801cb144d18143..935c664440aae82d69f0253a551b91ec4ff2724e 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -20,10 +20,26 @@ struct dw_mipi_csi2_config {
 	const struct v4l2_subdev_internal_ops *internal_ops;
 	/* Deprecated, should go through phy interface */
 	void (*gasket_init)(struct dw_mipi_csi2_dev *dev);
+	int (*dphy_init)(struct dw_mipi_csi2_dev *dev);
 	u32	num_pads;	/* Max 64 pad now */
 	u32	sink_pad_mask;
 };
 
+struct dw_mipi_tstif {
+	int (*write)(struct dw_mipi_tstif *tstif, u32 indice, u32 data);
+};
+
+static inline int dw_mipi_tstif_write(struct dw_mipi_tstif *tstif, u32 indice, u32 data)
+{
+	if (!tstif)
+		return -EINVAL;
+
+	if (!tstif->write)
+		return -EINVAL;
+
+	return  tstif->write(tstif, indice, data);
+}
+
 struct dw_mipi_csi2_dev {
 	struct device			*dev;
 	struct v4l2_subdev		sd;
@@ -51,8 +67,13 @@ struct dw_mipi_csi2_dev {
 	struct v4l2_subdev		*src_sd;
 	bool				sink_linked[DW_MAX_PAD_NUM];
 	const struct dw_mipi_csi2_config *config;
+
+	struct dw_mipi_tstif		tstif;
 };
 
+#define dw_mipi_csi2_tstif_write(csi2, indice, data)		\
+dw_mipi_tstif_write(&(csi2)->tstif, indice, data)
+
 static inline struct dw_mipi_csi2_dev *
 sd_to_dw_mipi_csi2_dev(struct v4l2_subdev *sd)
 {

-- 
2.34.1


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

* [PATCH v2 17/32] media: staging: media: imx6-mipi-csi2: use runtime_pm frame to control clks
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (15 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 16/32] media: staging: media: imx6-mipi-csi2: move dphy init part to imx6-csi2.c Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 18/32] media: synopsys: move imx6-mipi-csi2.c to synopsys/mipi-csi2.c Frank Li
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Enable runtime pm and use runtime pm API to control clocks.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/staging/media/imx/imx6-csi2.c      |  4 ++++
 drivers/staging/media/imx/imx6-mipi-csi2.c | 11 ++++++++---
 include/media/dw-mipi-csi2.h               | 18 ++++++++++++++++++
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-csi2.c b/drivers/staging/media/imx/imx6-csi2.c
index 696644aa04c83b1f2877b2b2315202627d927e96..e5192bcd886958a27f4255fca1055ae0a94866ef 100644
--- a/drivers/staging/media/imx/imx6-csi2.c
+++ b/drivers/staging/media/imx/imx6-csi2.c
@@ -154,6 +154,9 @@ static void csi2_remove(struct platform_device *pdev)
 	dw_mipi_csi2_deinit(csi2);
 }
 
+static DEFINE_RUNTIME_DEV_PM_OPS(imx6_csi2_pm_ops, dw_mipi_csi2_runtime_suspend,
+				 dw_mipi_csi2_runtime_resume, NULL);
+
 static const struct of_device_id csi2_dt_ids[] = {
 	{ .compatible = "fsl,imx6-mipi-csi2"},
 	{ /* sentinel */ }
@@ -164,6 +167,7 @@ static struct platform_driver csi2_driver = {
 	.driver = {
 		.name = "imx6-mipi-csi2",
 		.of_match_table = csi2_dt_ids,
+		.pm = pm_ptr(&imx6_csi2_pm_ops),
 	},
 	.probe = csi2_probe,
 	.remove = csi2_remove,
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 23656291d808ccdfc47f36d1f7f5104698812eba..0c8022ecdc18d42fa038c721e0c0953e8eb9cd6c 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -273,7 +273,7 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 	unsigned int lanes;
 	int ret;
 
-	ret = clk_bulk_prepare_enable(csi2->num_clks, csi2->clks);
+	ret = pm_runtime_resume_and_get(csi2->dev);
 	if (ret)
 		return ret;
 
@@ -323,7 +323,7 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 err_assert_reset:
 	csi2_enable(csi2, false);
 err_disable_clk:
-	clk_bulk_disable_unprepare(csi2->num_clks, csi2->clks);
+	pm_runtime_put(csi2->dev);
 	return ret;
 }
 
@@ -334,7 +334,8 @@ static void csi2_stop(struct dw_mipi_csi2_dev *csi2)
 	v4l2_subdev_call(csi2->src_sd, video, post_streamoff);
 
 	csi2_enable(csi2, false);
-	clk_bulk_disable_unprepare(csi2->num_clks, csi2->clks);
+
+	pm_runtime_put(csi2->dev);
 }
 
 /*
@@ -634,6 +635,8 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 
 	csi2->tstif.write = dw_mipi_csi2_phy_write;
 
+	platform_set_drvdata(pdev, csi2);
+
 	if (!config)
 		return -EINVAL;
 
@@ -667,6 +670,8 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	if (csi2->num_clks < 0)
 		return dev_err_probe(&pdev->dev, csi2->num_clks, "Failed to get clocks\n");
 
+	devm_pm_runtime_enable(&pdev->dev);
+
 	return csi2_async_register(csi2);
 
 }
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index 935c664440aae82d69f0253a551b91ec4ff2724e..3d70c1f4f38e7d663f9b043d8903ce57d630d1b1 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -3,6 +3,8 @@
 #ifndef __DW_MIPI_CSI2_COMMON_
 #define __DW_MIPI_CSI2_COMMON_
 
+#include <linux/pm_runtime.h>
+
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
@@ -86,5 +88,21 @@ int dw_mipi_csi2_init(struct platform_device *pdev,
 
 void dw_mipi_csi2_deinit(struct dw_mipi_csi2_dev *csi2);
 
+static inline int dw_mipi_csi2_runtime_suspend(struct device *dev)
+{
+	struct dw_mipi_csi2_dev *csi2 = dev_get_drvdata(dev);
+
+	clk_bulk_disable_unprepare(csi2->num_clks, csi2->clks);
+
+	return 0;
+}
+
+static inline int dw_mipi_csi2_runtime_resume(struct device *dev)
+{
+	struct dw_mipi_csi2_dev *csi2 = dev_get_drvdata(dev);
+
+	return clk_bulk_prepare_enable(csi2->num_clks, csi2->clks);
+}
+
 #endif
 

-- 
2.34.1


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

* [PATCH v2 18/32] media: synopsys: move imx6-mipi-csi2.c to synopsys/mipi-csi2.c
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (16 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 17/32] media: staging: media: imx6-mipi-csi2: use runtime_pm frame to control clks Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 19/32] media: synopsys: csi2: Remove deprecated s_stream and use v4l2_subdev_pad_ops Frank Li
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Move dw MIPI CSI2 common part drivers/staging/media/imx/imx6-mipi-csi2.c
under synopsys to let more SoC can reuse it.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/Kconfig                      | 12 ++++++++++++
 drivers/media/platform/synopsys/Makefile                     |  2 ++
 .../imx6-mipi-csi2.c => media/platform/synopsys/mipi-csi2.c} |  0
 drivers/staging/media/imx/Kconfig                            |  1 +
 drivers/staging/media/imx/Makefile                           |  2 +-
 5 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/synopsys/Kconfig b/drivers/media/platform/synopsys/Kconfig
index 4fd521f78425a96985fa3b6b017deef36631d1a9..e54dad835349d420dead6d5313c0623567c28c0b 100644
--- a/drivers/media/platform/synopsys/Kconfig
+++ b/drivers/media/platform/synopsys/Kconfig
@@ -1,3 +1,15 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
+config VIDEO_SYNOPSYS_MIPI_CSI2
+        tristate "Synopsys DesignWare MIPI CSI2 Receiver common library"
+        depends on VIDEO_DEV
+        select MEDIA_CONTROLLER
+        select VIDEO_V4L2_SUBDEV_API
+        select VIDEOBUF2_DMA_CONTIG
+        help
+          Common library for MIPI CSI2 Controller.
+
+          To compile this driver as a module, choose M here. The module
+          will be called synopsys_hdmirx
+
 source "drivers/media/platform/synopsys/hdmirx/Kconfig"
diff --git a/drivers/media/platform/synopsys/Makefile b/drivers/media/platform/synopsys/Makefile
index 3b12c574dd67c072901108d88cad64ca3a723938..045ed3177738e6d28aa223804b79e6774e141dc8 100644
--- a/drivers/media/platform/synopsys/Makefile
+++ b/drivers/media/platform/synopsys/Makefile
@@ -1,2 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y += hdmirx/
+
+obj-$(CONFIG_VIDEO_SYNOPSYS_MIPI_CSI2) += mipi-csi2.o
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
similarity index 100%
rename from drivers/staging/media/imx/imx6-mipi-csi2.c
rename to drivers/media/platform/synopsys/mipi-csi2.c
diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig
index 1cd48028b6416ae16ed69c68186281b6c6bcbec8..53e5c1546ac53e4942974a9acdcf078de1cb6073 100644
--- a/drivers/staging/media/imx/Kconfig
+++ b/drivers/staging/media/imx/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_IMX_MEDIA
 	select V4L2_MEM2MEM_DEV
 	select VIDEOBUF2_DMA_CONTIG
 	select VIDEO_V4L2_SUBDEV_API
+	select VIDEO_SYNOPSYS_MIPI_CSI2
 	help
 	  Say yes here to enable support for video4linux media controller
 	  drivers for the i.MX5/6 SOC.
diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile
index 064a6c6c069aa440c72a483080cbedf89d370193..1978b82fd1876566acbb952a4d14cf9aca35e996 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -11,4 +11,4 @@ imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media-csi.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-mipi-csi2.o imx6-csi2.o
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-csi2.o

-- 
2.34.1


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

* [PATCH v2 19/32] media: synopsys: csi2: Remove deprecated s_stream and use v4l2_subdev_pad_ops
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (17 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 18/32] media: synopsys: move imx6-mipi-csi2.c to synopsys/mipi-csi2.c Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 20/32] media: synopsys: csi2: Add phy interface support Frank Li
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use new v4l2_subdev_pad_ops.enable_streams(disalbe_stream) replace
deprecated s_stream interface.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 52 +++++++++++++++++------------
 1 file changed, 31 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 0c8022ecdc18d42fa038c721e0c0953e8eb9cd6c..9ea3ae22fecfbb66abc460c40cbbcf15e1a97494 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -342,7 +342,9 @@ static void csi2_stop(struct dw_mipi_csi2_dev *csi2)
  * V4L2 subdev operations.
  */
 
-static int csi2_s_stream(struct v4l2_subdev *sd, int enable)
+static int dw_csi2_enable_streams(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_state *state, u32 pad,
+				  u64 streams_mask)
 {
 	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	int i, ret = 0;
@@ -359,28 +361,39 @@ static int csi2_s_stream(struct v4l2_subdev *sd, int enable)
 	if (i >= csi2->num_sink_pads)
 		return -EPIPE;
 
-	/*
-	 * enable/disable streaming only if stream_count is
-	 * going from 0 to 1 / 1 to 0.
-	 */
-	if (csi2->stream_count != !enable)
-		goto update_count;
+	if (csi2->stream_count)
+		return 0;
 
-	dev_dbg(csi2->dev, "stream %s\n", enable ? "ON" : "OFF");
-	if (enable)
-		ret = csi2_start(csi2);
-	else
-		csi2_stop(csi2);
+	ret = csi2_start(csi2);
 	if (ret)
 		return ret;
 
-update_count:
-	csi2->stream_count += enable ? 1 : -1;
-	if (csi2->stream_count < 0)
-		csi2->stream_count = 0;
+	csi2->stream_count++;
+
 	return ret;
 }
 
+static int dw_csi2_disable_streams(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_state *state, u32 pad,
+				   u64 streams_mask)
+{
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
+
+	guard(mutex)(&csi2->lock);
+
+	if (!csi2->stream_count) {
+		dev_err(csi2->dev, "Error: csi2 enable count already be 0\n");
+		return 0;
+	}
+
+	csi2->stream_count--;
+
+	if (!csi2->stream_count)
+		csi2_stop(csi2);
+
+	return 0;
+}
+
 static int csi2_link_setup(struct media_entity *entity,
 			   const struct media_pad *local,
 			   const struct media_pad *remote, u32 flags)
@@ -507,18 +520,15 @@ static const struct media_entity_operations csi2_entity_ops = {
 	.get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1,
 };
 
-static const struct v4l2_subdev_video_ops csi2_video_ops = {
-	.s_stream = csi2_s_stream,
-};
-
 static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
 	.get_fmt = csi2_get_fmt,
 	.set_fmt = csi2_set_fmt,
+	.enable_streams = dw_csi2_enable_streams,
+	.disable_streams = dw_csi2_disable_streams,
 };
 
 static const struct v4l2_subdev_ops csi2_subdev_ops = {
 	.core = &csi2_core_ops,
-	.video = &csi2_video_ops,
 	.pad = &csi2_pad_ops,
 };
 

-- 
2.34.1


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

* [PATCH v2 20/32] media: synopsys: csi2: Add phy interface support
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (18 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 19/32] media: synopsys: csi2: Remove deprecated s_stream and use v4l2_subdev_pad_ops Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 21/32] media: synopsys: csi2: Add basic v150* version register Frank Li
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add standard phy interface support.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 91 +++++++++++++++++++++++++++--
 include/media/dw-mipi-csi2.h                |  4 ++
 2 files changed, 90 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 9ea3ae22fecfbb66abc460c40cbbcf15e1a97494..610f2debbf08f571a47f5372853d5ef10a6add52 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -14,6 +14,7 @@
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <media/dw-mipi-csi2.h>
+#include <media/mipi-csi2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -268,7 +269,63 @@ static int csi2_get_active_lanes(struct dw_mipi_csi2_dev *csi2, unsigned int *la
 	return 0;
 }
 
-static int csi2_start(struct dw_mipi_csi2_dev *csi2)
+static int dw_csi2_get_dphy_configuration(struct dw_mipi_csi2_dev *csi2,
+					  union phy_configure_opts *opts,
+					  int bpp)
+{
+	struct phy_configure_opts_mipi_dphy *cfg = &opts->mipi_dphy;
+	struct v4l2_subdev *source = csi2->src_sd;
+	s64 link_freq;
+
+	link_freq = v4l2_get_link_freq(source->ctrl_handler,
+				       bpp,
+				       csi2->data_lanes * 2);
+	if (link_freq < 0) {
+		dev_err(csi2->dev, "Unable to obtain link frequency: %d\n",
+			(int)link_freq);
+		return link_freq;
+	}
+
+	memset(cfg, 0x0, sizeof(*cfg));
+	cfg->hs_clk_rate = link_freq * 2;
+	cfg->lanes = csi2->data_lanes;
+
+	return 0;
+}
+
+static int dw_mipi_csi2_phy_prep(struct dw_mipi_csi2_dev *csi2, int bpp)
+{
+	union phy_configure_opts opts;
+	int ret;
+
+	ret = dw_csi2_get_dphy_configuration(csi2, &opts, bpp);
+	if (ret)
+		return ret;
+
+	ret = phy_init(csi2->phy);
+	if (ret)
+		return ret;
+
+	ret = phy_reset(csi2->phy);
+	if (ret)
+		goto exit;
+
+	ret = phy_set_mode(csi2->phy, PHY_MODE_MIPI_DPHY);
+	if (ret)
+		goto exit;
+
+	ret = phy_configure(csi2->phy, &opts);
+	if (ret)
+		goto exit;
+
+	return 0;
+
+exit:
+	phy_exit(csi2->phy);
+	return ret;
+}
+
+static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 {
 	unsigned int lanes;
 	int ret;
@@ -277,6 +334,10 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 	if (ret)
 		return ret;
 
+	ret = dw_mipi_csi2_phy_prep(csi2, bpp);
+	if (ret)
+		goto err_phy_prep;
+
 	/* setup the gasket */
 	if (csi2->config && csi2->config->gasket_init)
 		csi2->config->gasket_init(csi2);
@@ -285,15 +346,20 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 	if (csi2->config && csi2->config->dphy_init) {
 		ret = csi2->config->dphy_init(csi2);
 		if (ret)
-			goto err_disable_clk;
+			goto err_dphy_init;
 	}
 
 	ret = csi2_get_active_lanes(csi2, &lanes);
 	if (ret)
-		goto err_disable_clk;
+		goto err_active_lanes;
 
 	/* Step 4 */
 	csi2_set_lanes(csi2, lanes);
+
+	ret = phy_power_on(csi2->phy);
+	if (ret)
+		goto err_phy_power_on;
+
 	csi2_enable(csi2, true);
 
 	/* Step 5 */
@@ -322,13 +388,21 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2)
 	v4l2_subdev_call(csi2->src_sd, video, post_streamoff);
 err_assert_reset:
 	csi2_enable(csi2, false);
-err_disable_clk:
+err_phy_power_on:
+	phy_power_off(csi2->phy);
+err_active_lanes:
+err_dphy_init:
+	phy_exit(csi2->phy);
+err_phy_prep:
 	pm_runtime_put(csi2->dev);
 	return ret;
 }
 
 static void csi2_stop(struct dw_mipi_csi2_dev *csi2)
 {
+	phy_power_off(csi2->phy);
+	phy_exit(csi2->phy);
+
 	/* stop upstream */
 	v4l2_subdev_call(csi2->src_sd, video, s_stream, 0);
 	v4l2_subdev_call(csi2->src_sd, video, post_streamoff);
@@ -364,7 +438,7 @@ static int dw_csi2_enable_streams(struct v4l2_subdev *sd,
 	if (csi2->stream_count)
 		return 0;
 
-	ret = csi2_start(csi2);
+	ret = csi2_start(csi2, media_bus_fmt_to_csi2_bpp(csi2->format_mbus.code));
 	if (ret)
 		return ret;
 
@@ -680,6 +754,13 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	if (csi2->num_clks < 0)
 		return dev_err_probe(&pdev->dev, csi2->num_clks, "Failed to get clocks\n");
 
+	if (config->has_phy) {
+		csi2->phy = devm_phy_get(&pdev->dev, "rx");
+		if (IS_ERR(csi2->phy))
+			return dev_err_probe(&pdev->dev, PTR_ERR(csi2->phy),
+					     "Failed to get DPHY Rx\n");
+	}
+
 	devm_pm_runtime_enable(&pdev->dev);
 
 	return csi2_async_register(csi2);
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index 3d70c1f4f38e7d663f9b043d8903ce57d630d1b1..14a80c09fd273c334f91ea70d955dcf92b6646ce 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -3,6 +3,7 @@
 #ifndef __DW_MIPI_CSI2_COMMON_
 #define __DW_MIPI_CSI2_COMMON_
 
+#include <linux/phy/phy.h>
 #include <linux/pm_runtime.h>
 
 #include <media/v4l2-common.h>
@@ -25,6 +26,7 @@ struct dw_mipi_csi2_config {
 	int (*dphy_init)(struct dw_mipi_csi2_dev *dev);
 	u32	num_pads;	/* Max 64 pad now */
 	u32	sink_pad_mask;
+	bool	has_phy: 1;
 };
 
 struct dw_mipi_tstif {
@@ -56,6 +58,8 @@ struct dw_mipi_csi2_dev {
 	struct clk_bulk_data		*clks;
 	int				num_clks;
 
+	struct phy			*phy;
+
 	struct v4l2_subdev		*remote;
 	unsigned int			remote_pad;
 	unsigned short			data_lanes;

-- 
2.34.1


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

* [PATCH v2 21/32] media: synopsys: csi2: Add basic v150* version register
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (19 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 20/32] media: synopsys: csi2: Add phy interface support Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 22/32] media: synopsys: csi2: Add irq support to record error count Frank Li
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add basic v150* version register and auto detect IP version by read version
register, which located position 0 for both version.

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

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 610f2debbf08f571a47f5372853d5ef10a6add52..0386d91522ec7b41694ac9c36ad0c3c37b1e68b3 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -61,6 +61,19 @@ static const struct dw_csi2_regs dw_csi2_v0 = {
 	.phy_tst_ctrl1 = DW_REG(0x34),
 };
 
+static const struct dw_csi2_regs dw_csi2_v150 = {
+	.version = DW_REG(0x0),
+	.n_lanes = DW_REG(0x4),
+	.resetn = DW_REG(0x8),
+	.data_ids_1 = DW_REG(0x10),
+	.data_ids_2 = DW_REG(0x14),
+	.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),
+};
+
 static int dw_csi2_reg_err(struct dw_mipi_csi2_dev *csi2, const char *name)
 {
 	dev_err_once(csi2->dev, "access to unexisted register: %s", name);
@@ -697,13 +710,31 @@ static void csi2_nf_cleanup(void *data)
 	v4l2_async_nf_cleanup(&csi2->notifier);
 }
 
+static int dw_detect_version(struct dw_mipi_csi2_dev *csi2)
+{
+	int ret;
+	int ver;
+
+	ret = pm_runtime_resume_and_get(csi2->dev);
+	if (ret)
+		return ret;
+
+	/* version is first register for known chips */
+	ver = readl(csi2->base);
+	if (ver >= 0x3135302a) /* ASCII "150*" */
+		csi2->regs = &dw_csi2_v150;
+	else
+		csi2->regs = &dw_csi2_v0;
+
+	return 0;
+}
+
 int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi2,
 		      const struct dw_mipi_csi2_config *config)
 {
 	int i, ret;
 
 	csi2->dev = &pdev->dev;
-	csi2->regs = &dw_csi2_v0;
 	v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops);
 	v4l2_set_subdevdata(&csi2->sd, &pdev->dev);
 	csi2->sd.entity.ops = &csi2_entity_ops;
@@ -763,6 +794,10 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 
 	devm_pm_runtime_enable(&pdev->dev);
 
+	ret = dw_detect_version(csi2);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Failed to detect IP version");
+
 	return csi2_async_register(csi2);
 
 }

-- 
2.34.1


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

* [PATCH v2 22/32] media: synopsys: csi2: Add irq support to record error count
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (20 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 21/32] media: synopsys: csi2: Add basic v150* version register Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 23/32] media: synopsys: csi2: Handle alignment requirement for width Frank Li
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add irq support to record error count. Use debugfs to show such error
count.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 171 ++++++++++++++++++++++++++++
 include/media/dw-mipi-csi2.h                |   8 ++
 2 files changed, 179 insertions(+)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 0386d91522ec7b41694ac9c36ad0c3c37b1e68b3..dcad69cea99f3172786156699513f8cc8771ad2a 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -4,6 +4,7 @@
  *
  * Copyright (c) 2012-2017 Mentor Graphics Inc.
  */
+#include <linux/debugfs.h>
 #include <linux/export.h>
 #include <linux/clk.h>
 #include <linux/interrupt.h>
@@ -37,6 +38,19 @@ struct dw_csi2_regs {
 	u32	msk2;
 	u32	phy_tst_ctrl0;
 	u32	phy_tst_ctrl1;
+	u32	int_st_main;
+	u32	int_st_dphy_fatal;
+	u32	int_msk_dphy_fatal;
+	u32	int_force_dphy_fatal;
+	u32	int_st_pkt_fatal;
+	u32	int_msk_pkt_fatal;
+	u32	int_force_pkt_fatal;
+	u32	int_st_dphy;
+	u32	int_msk_dphy;
+	u32	int_force_dphy;
+	u32	int_st_ipi_fatal;
+	u32	int_msk_ipi_fatal;
+	u32	int_force_ipi_fatal;
 };
 
 /* Help check wrong access unexisted register at difference IP version */
@@ -65,6 +79,7 @@ static const struct dw_csi2_regs dw_csi2_v150 = {
 	.version = DW_REG(0x0),
 	.n_lanes = DW_REG(0x4),
 	.resetn = DW_REG(0x8),
+	.int_st_main = DW_REG(0xc),
 	.data_ids_1 = DW_REG(0x10),
 	.data_ids_2 = DW_REG(0x14),
 	.phy_shutdownz = DW_REG(0x40),
@@ -72,8 +87,48 @@ static const struct dw_csi2_regs dw_csi2_v150 = {
 	.phy_state = DW_REG(0x48),
 	.phy_tst_ctrl0 = DW_REG(0x50),
 	.phy_tst_ctrl1 = DW_REG(0x54),
+	.int_st_dphy_fatal = DW_REG(0xe0),
+	.int_msk_dphy_fatal = DW_REG(0xe4),
+	.int_force_dphy_fatal = DW_REG(0xe8),
+	.int_st_pkt_fatal = DW_REG(0xf0),
+	.int_msk_pkt_fatal = DW_REG(0xf4),
+	.int_force_pkt_fatal = DW_REG(0xf8),
+	.int_st_dphy = DW_REG(0x110),
+	.int_msk_dphy = DW_REG(0x114),
+	.int_force_dphy = DW_REG(0x118),
+	.int_st_ipi_fatal = DW_REG(0x140),
+	.int_msk_ipi_fatal = DW_REG(0x144),
+	.int_force_ipi_fatal = DW_REG(0x148),
 };
 
+#define INT_ST_MAIN_FATAL_ERR_PHY		BIT(0)
+#define INT_ST_MAIN_FATAL_ERR_PKT		BIT(1)
+#define INT_ST_MAIN_FATAL_ERR_BNDRY_FRAMEL	BIT(2)
+#define INT_ST_MAIN_FATAL_ERR_SEQ_FRAME		BIT(3)
+#define INT_ST_MAIN_FATAL_ERR_CRC_FRAME		BIT(4)
+#define INT_ST_MAIN_FATAL_ERR_PLD_CRC		BIT(5)
+#define INT_ST_MAIN_ERR_DID			BIT(6)
+#define INT_ST_MAIN_ERR_ECC			BIT(7)
+#define INT_ST_MAIN_ERR_PHY			BIT(16)
+#define INT_ST_MAIN_FATAL_ERR_IPI		BIT(18)
+
+#define INT_MSK_DPHY_FATAL_ERR_SOT_LANE0	BIT(0)
+#define INT_MSK_DPHY_FATAL_ERR_SOT_LANE1	BIT(1)
+
+#define INT_ST_PKT_FATAL_ERR_ECC		BIT(0)
+#define INT_ST_PKT_FATAL_ERR_PAYLOAD	BIT(1)
+
+#define INT_MSK_PKT_FATAL_ERR_ECC		BIT(0)
+#define INT_MSK_PKT_FATAL_ERR_PAYLOAD		BIT(1)
+
+#define INT_ST_IPI_FATAL_ERR_IFFIFO_UNDERFLOW	BIT(0)
+#define INT_ST_IPI_FATAL_ERR_IFFIFO_OVERFLOW	BIT(1)
+#define INT_ST_IPI_FATAL_ERR_FRAME_SYNC		BIT(2)
+#define INT_ST_IPI_FATAL_ERR_FIFO_NOT_EMPTY	BIT(3)
+#define INT_ST_IPI_FATAL_ERR_HLINE_TIME		BIT(4)
+#define INT_ST_IPI_FATAL_ERR_FIFO_OVERFLOW	BIT(5)
+#define INT_ST_IPI_FATAL_ERR_PD_FIFO_OVERFLOW	BIT(6)
+
 static int dw_csi2_reg_err(struct dw_mipi_csi2_dev *csi2, const char *name)
 {
 	dev_err_once(csi2->dev, "access to unexisted register: %s", name);
@@ -108,6 +163,25 @@ static inline struct dw_mipi_csi2_dev *notifier_to_dev(struct v4l2_async_notifie
 	return container_of(n, struct dw_mipi_csi2_dev, notifier);
 }
 
+struct dw_csi2_event {
+	u32 mask;
+	const char * const name;
+	u32 counter;
+};
+
+static const struct dw_csi2_event dw_events[] = {
+	{ INT_ST_MAIN_FATAL_ERR_IPI, "IPI Interface Fatal Error" },
+	{ INT_ST_MAIN_ERR_PHY, "PHY Error" },
+	{ INT_ST_MAIN_ERR_ECC, "Header Single Bit Error" },
+	{ INT_ST_MAIN_ERR_DID, "Data ID Error" },
+	{ INT_ST_MAIN_FATAL_ERR_PLD_CRC, "Payload CRC Fatal Error" },
+	{ INT_ST_MAIN_FATAL_ERR_CRC_FRAME, "Frame CRC Fatal Error" },
+	{ INT_ST_MAIN_FATAL_ERR_SEQ_FRAME, "Frame Sequence Fatal Error" },
+	{ INT_ST_MAIN_FATAL_ERR_BNDRY_FRAMEL, "Frame Boundaries Fatal Error" },
+	{ INT_ST_MAIN_FATAL_ERR_PKT, "Packet Construction Fatal Error" },
+	{ INT_ST_MAIN_FATAL_ERR_PHY, "PHY Fatal Error" },
+};
+
 /*
  * The required sequence of MIPI CSI-2 startup as specified in the i.MX6
  * reference manual is as follows:
@@ -338,6 +412,40 @@ static int dw_mipi_csi2_phy_prep(struct dw_mipi_csi2_dev *csi2, int bpp)
 	return ret;
 }
 
+static void dw_csi2_enable_irq(struct dw_mipi_csi2_dev *csi2)
+{
+	u32 val;
+
+	/* Define errors to be enabled */
+	val = INT_MSK_DPHY_FATAL_ERR_SOT_LANE0 |
+	      INT_MSK_DPHY_FATAL_ERR_SOT_LANE0;
+	dw_writel(csi2, val, int_msk_dphy_fatal);
+
+	val = INT_ST_PKT_FATAL_ERR_ECC | INT_ST_PKT_FATAL_ERR_PAYLOAD;
+	dw_writel(csi2, val, int_msk_pkt_fatal);
+
+	val = INT_MSK_PKT_FATAL_ERR_ECC | INT_MSK_PKT_FATAL_ERR_PAYLOAD;
+	dw_writel(csi2, val, int_msk_dphy);
+
+	val = INT_ST_IPI_FATAL_ERR_IFFIFO_UNDERFLOW |
+	      INT_ST_IPI_FATAL_ERR_IFFIFO_OVERFLOW |
+	      INT_ST_IPI_FATAL_ERR_FRAME_SYNC |
+	      INT_ST_IPI_FATAL_ERR_FIFO_NOT_EMPTY |
+	      INT_ST_IPI_FATAL_ERR_HLINE_TIME |
+	      INT_ST_IPI_FATAL_ERR_FIFO_OVERFLOW |
+	      INT_ST_IPI_FATAL_ERR_PD_FIFO_OVERFLOW;
+
+	dw_writel(csi2, val, int_msk_ipi_fatal);
+}
+
+static void dw_csi2_disable_irq(struct dw_mipi_csi2_dev *csi2)
+{
+	dw_writel(csi2, 0, int_msk_dphy_fatal);
+	dw_writel(csi2, 0, int_msk_pkt_fatal);
+	dw_writel(csi2, 0, int_msk_dphy);
+	dw_writel(csi2, 0, int_msk_ipi_fatal);
+}
+
 static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 {
 	unsigned int lanes;
@@ -393,6 +501,8 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 	if (ret)
 		goto err_stop_upstream;
 
+	dw_csi2_enable_irq(csi2);
+
 	return 0;
 
 err_stop_upstream:
@@ -422,6 +532,8 @@ static void csi2_stop(struct dw_mipi_csi2_dev *csi2)
 
 	csi2_enable(csi2, false);
 
+	dw_csi2_disable_irq(csi2);
+
 	pm_runtime_put(csi2->dev);
 }
 
@@ -729,6 +841,42 @@ static int dw_detect_version(struct dw_mipi_csi2_dev *csi2)
 	return 0;
 }
 
+static irqreturn_t dw_csi2_irq_handler(int irq, void *priv)
+{
+	struct dw_mipi_csi2_dev *csi2 = priv;
+	u32 status;
+	int i;
+
+	/* Hardware auto clean after read */
+	status = dw_readl(csi2, int_st_main);
+
+	for (i = 0; i < csi2->num_event; i++) {
+		struct dw_csi2_event *event = &csi2->event[i];
+
+		if (status & event->mask)
+			event->counter++;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void dw_mipi_csi_create_debugfs(struct dw_mipi_csi2_dev *csi2)
+{
+	int i;
+
+	csi2->debugfs_root = debugfs_create_dir(dev_name(csi2->dev), NULL);
+
+	if (!csi2->debugfs_root)
+		return;
+
+	for (i = 0; i < csi2->num_event; i++) {
+		struct dw_csi2_event *event = &csi2->event[i];
+
+		debugfs_create_u32(event->name, 0600, csi2->debugfs_root,
+				   &event->counter);
+	}
+}
+
 int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi2,
 		      const struct dw_mipi_csi2_config *config)
 {
@@ -798,6 +946,27 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	if (ret)
 		return dev_err_probe(&pdev->dev, ret, "Failed to detect IP version");
 
+	if (config->has_irq) {
+		int irq;
+
+		csi2->event = devm_kmemdup(&pdev->dev, dw_events, sizeof(dw_events), GFP_KERNEL);
+		csi2->num_event = ARRAY_SIZE(dw_events);
+
+		if (!csi2->event)
+			return -ENOMEM;
+
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return dev_err_probe(&pdev->dev, irq, "Failed to get IRQ\n");
+
+		ret = devm_request_irq(&pdev->dev, irq, dw_csi2_irq_handler, 0,
+				       dev_name(&pdev->dev), csi2);
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret, "Failed to request IRQ\n");
+	}
+
+	dw_mipi_csi_create_debugfs(csi2);
+
 	return csi2_async_register(csi2);
 
 }
@@ -807,5 +976,7 @@ void dw_mipi_csi2_deinit(struct dw_mipi_csi2_dev *csi2)
 {
 	v4l2_async_unregister_subdev(&csi2->sd);
 	media_entity_cleanup(&csi2->sd.entity);
+
+	debugfs_remove(csi2->debugfs_root);
 }
 EXPORT_SYMBOL_GPL(dw_mipi_csi2_deinit);
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index 14a80c09fd273c334f91ea70d955dcf92b6646ce..20ce6a21f0674cad54f01edb508dce14cd07a8dd 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -27,6 +27,7 @@ struct dw_mipi_csi2_config {
 	u32	num_pads;	/* Max 64 pad now */
 	u32	sink_pad_mask;
 	bool	has_phy: 1;
+	bool	has_irq: 1;
 };
 
 struct dw_mipi_tstif {
@@ -44,6 +45,8 @@ static inline int dw_mipi_tstif_write(struct dw_mipi_tstif *tstif, u32 indice, u
 	return  tstif->write(tstif, indice, data);
 }
 
+struct dw_csi2_event;
+
 struct dw_mipi_csi2_dev {
 	struct device			*dev;
 	struct v4l2_subdev		sd;
@@ -74,6 +77,11 @@ struct dw_mipi_csi2_dev {
 	bool				sink_linked[DW_MAX_PAD_NUM];
 	const struct dw_mipi_csi2_config *config;
 
+	struct dw_csi2_event		*event;
+	int				num_event;
+
+	struct dentry			*debugfs_root;
+
 	struct dw_mipi_tstif		tstif;
 };
 

-- 
2.34.1


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

* [PATCH v2 23/32] media: synopsys: csi2: Handle alignment requirement for width
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (21 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 22/32] media: synopsys: csi2: Add irq support to record error count Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 24/32] media: synopsys: csi2: Add register prefix to register field definitions Frank Li
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

bpp * width must align to 8. Use media_bus_fmt_to_csi2_bpp() and
v4l_get_required_align_by_bpp() to get width's alignment requirement.

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

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index dcad69cea99f3172786156699513f8cc8771ad2a..5c41b9570dcb97f58018bbaba1dc67a3c120a60b 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/irq.h>
+#include <linux/limits.h>
 #include <linux/module.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
@@ -664,15 +665,31 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 {
 	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
+	u32 align;
+	u32 bpp;
 
 	if (sdformat->pad >= (csi2->num_src_pads + csi2->num_sink_pads))
 		return -EINVAL;
 
+	/*
+	 * The CSIS can't transcode in any way, the source format can't be
+	 * modified.
+	 */
+	if (sdformat->pad < csi2->num_src_pads)
+		return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
+
 	guard(mutex)(&csi2->lock);
 
 	if (csi2->stream_count > 0)
 		return -EBUSY;
 
+	bpp = media_bus_fmt_to_csi2_bpp(sdformat->format.code);
+
+	align = v4l_get_required_align_by_bpp(bpp, 3); /* need align to 2^3 */
+
+	v4l_bound_align_image(&sdformat->format.width, 1, U16_MAX, align,
+			      &sdformat->format.height, 1, U16_MAX, 0, 0);
+
 	/* Output pads mirror active input pad, no limits on input pads */
 	if (!(csi2->config->sink_pad_mask & BIT(sdformat->pad)))
 		sdformat->format = csi2->format_mbus;

-- 
2.34.1


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

* [PATCH v2 24/32] media: synopsys: csi2: Add register prefix to register field definitions
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (22 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 23/32] media: synopsys: csi2: Handle alignment requirement for width Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 25/32] media: synopsys: csi2: Add need_dphy_reset in config Frank Li
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add register prefix to register field definitions to improve readability.

No functional change.

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

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 5c41b9570dcb97f58018bbaba1dc67a3c120a60b..df19b960d33681452af49dad5e6bbb94daa63489 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -146,16 +146,16 @@ dw_csi2_reg_err((csi2), #__name))
 readl((csi2)->base + ((csi2)->regs->__name & ~DW_REG_EXIST)) : \
 dw_csi2_reg_err(csi2, #__name))
 
-#define PHY_STOPSTATEDATA_BIT	4
-#define PHY_STOPSTATEDATA(n)	BIT(PHY_STOPSTATEDATA_BIT + (n))
-#define PHY_RXCLKACTIVEHS	BIT(8)
-#define PHY_RXULPSCLKNOT	BIT(9)
-#define PHY_STOPSTATECLK	BIT(10)
+#define PHY_STATE_STOPSTATEDATA_BIT	4
+#define PHY_STATE_STOPSTATEDATA(n)	BIT(PHY_STATE_STOPSTATEDATA_BIT + (n))
+#define PHY_STATE_RXCLKACTIVEHS	BIT(8)
+#define PHY_STATE_RXULPSCLKNOT	BIT(9)
+#define PHY_STATE_STOPSTATECLK	BIT(10)
 
-#define PHY_TESTCLR		BIT(0)
-#define PHY_TESTCLK		BIT(1)
+#define DPHY_TEST_CTRL0_TEST_CLR		BIT(0)
+#define DPHY_TEST_CTRL0_TEST_CLKEN	BIT(1)
 
-#define PHY_TESTEN		BIT(16)
+#define DPHY_TEST_CTRL1_TEST_EN		BIT(16)
 
 #define sd_to_dev sd_to_dw_mipi_csi2_dev
 
@@ -235,20 +235,20 @@ static int dw_mipi_csi2_phy_write(struct dw_mipi_tstif *tstif,
 	struct dw_mipi_csi2_dev *csi2 = container_of(tstif, struct dw_mipi_csi2_dev, tstif);
 
 	/* Clear PHY test interface */
-	dw_writel(csi2, PHY_TESTCLR, phy_tst_ctrl0);
+	dw_writel(csi2, DPHY_TEST_CTRL0_TEST_CLR, phy_tst_ctrl0);
 	dw_writel(csi2, 0x0, phy_tst_ctrl1);
 	dw_writel(csi2, 0x0, phy_tst_ctrl0);
 
 	/* Raise test interface strobe signal */
-	dw_writel(csi2, PHY_TESTCLK, phy_tst_ctrl0);
+	dw_writel(csi2, DPHY_TEST_CTRL0_TEST_CLKEN, phy_tst_ctrl0);
 
 	/* Configure address write on falling edge and lower strobe signal */
-	dw_writel(csi2, PHY_TESTEN | test_code, phy_tst_ctrl1);
+	dw_writel(csi2, DPHY_TEST_CTRL1_TEST_EN | test_code, phy_tst_ctrl1);
 	dw_writel(csi2, 0x0, phy_tst_ctrl0);
 
 	/* Configure data write on rising edge and raise strobe signal */
 	dw_writel(csi2, test_data, phy_tst_ctrl1);
-	dw_writel(csi2, PHY_TESTCLK, phy_tst_ctrl0);
+	dw_writel(csi2, DPHY_TEST_CTRL0_TEST_CLKEN, phy_tst_ctrl0);
 
 	/* Clear strobe signal */
 	dw_writel(csi2, 0x0, phy_tst_ctrl0);
@@ -271,7 +271,7 @@ static int __maybe_unused csi2_dphy_wait_ulp(struct dw_mipi_csi2_dev *csi2)
 	int ret;
 
 	/* wait for ULP on clock lane */
-	ret = read_poll_timeout(dw_readl, reg, !(reg & PHY_RXULPSCLKNOT),
+	ret = read_poll_timeout(dw_readl, reg, !(reg & PHY_STATE_RXULPSCLKNOT),
 				0, 500000, 0, csi2, phy_state);
 	if (ret) {
 		v4l2_err(&csi2->sd, "ULP timeout, phy_state = 0x%08x\n", reg);
@@ -294,7 +294,7 @@ static void csi2_dphy_wait_stopstate(struct dw_mipi_csi2_dev *csi2, unsigned int
 	u32 mask, reg;
 	int ret;
 
-	mask = PHY_STOPSTATECLK | (((1 << lanes) - 1) << PHY_STOPSTATEDATA_BIT);
+	mask = PHY_STATE_STOPSTATECLK | (((1 << lanes) - 1) << PHY_STATE_STOPSTATEDATA_BIT);
 
 	ret = read_poll_timeout(dw_readl, reg, (reg & mask) == mask, 0, 500000, 0, csi2, phy_state);
 	if (ret) {
@@ -309,7 +309,7 @@ static int csi2_dphy_wait_clock_lane(struct dw_mipi_csi2_dev *csi2)
 	u32 reg;
 	int ret;
 
-	ret = read_poll_timeout(dw_readl, reg, (reg & PHY_RXCLKACTIVEHS),
+	ret = read_poll_timeout(dw_readl, reg, (reg & PHY_STATE_RXCLKACTIVEHS),
 				0, 500000, 0, csi2, phy_state);
 	if (ret) {
 		v4l2_err(&csi2->sd, "clock lane timeout, phy_state = 0x%08x\n",

-- 
2.34.1


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

* [PATCH v2 25/32] media: synopsys: csi2: Add need_dphy_reset in config
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (23 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 24/32] media: synopsys: csi2: Add register prefix to register field definitions Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 26/32] media: synopsys: csi2: Add default simple dw_csi2_subdev_init_state Frank Li
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add need_dphy_reset in config to indicate need keep dphy reset state during
config dphy because some SoC like i.MX93 need it.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 45 +++++++++++++++++++++++++++++
 include/media/dw-mipi-csi2.h                |  1 +
 2 files changed, 46 insertions(+)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index df19b960d33681452af49dad5e6bbb94daa63489..d1f08c8384ad45d47ffe81b6dc5f225aed43e21a 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -447,6 +447,45 @@ static void dw_csi2_disable_irq(struct dw_mipi_csi2_dev *csi2)
 	dw_writel(csi2, 0, int_msk_ipi_fatal);
 }
 
+static void dw_csi2_dphy_reset(struct dw_mipi_csi2_dev *csi2)
+{
+	u32 val;
+
+	/* Release synopsis DPHY test codes from reset */
+	dw_writel(csi2, 0, dphy_rstz);
+	dw_writel(csi2, 0, phy_shutdownz);
+
+	val = dw_readl(csi2, phy_tst_ctrl0);
+	val &= ~DPHY_TEST_CTRL0_TEST_CLR;
+	dw_writel(csi2, val, phy_tst_ctrl0);
+
+	/*
+	 * ndelay is not necessary have MMIO operation, need dummy read to make
+	 * sure above write reach target.
+	 */
+	val = dw_readl(csi2, phy_tst_ctrl0);
+	/* Wait for at least 15ns */
+	ndelay(15);
+	val |= DPHY_TEST_CTRL0_TEST_CLR;
+	dw_writel(csi2, val, phy_tst_ctrl0);
+}
+
+static void dw_csi2_dphy_release_reset(struct dw_mipi_csi2_dev *csi2)
+{
+	/* Release PHY from reset */
+	dw_writel(csi2, 0x1, phy_shutdownz);
+	/*
+	 * ndelay is not necessary have MMIO operation, need dummy read to make
+	 * sure above write reach target.
+	 */
+	dw_readl(csi2, phy_shutdownz);
+	ndelay(5);
+	dw_writel(csi2, 0x1, dphy_rstz);
+
+	dw_readl(csi2, dphy_rstz);
+	ndelay(5);
+}
+
 static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 {
 	unsigned int lanes;
@@ -460,6 +499,9 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 	if (ret)
 		goto err_phy_prep;
 
+	if (csi2->config->need_dphy_reset)
+		dw_csi2_dphy_reset(csi2);
+
 	/* setup the gasket */
 	if (csi2->config && csi2->config->gasket_init)
 		csi2->config->gasket_init(csi2);
@@ -482,6 +524,9 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 	if (ret)
 		goto err_phy_power_on;
 
+	if (csi2->config->need_dphy_reset)
+		dw_csi2_dphy_release_reset(csi2);
+
 	csi2_enable(csi2, true);
 
 	/* Step 5 */
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index 20ce6a21f0674cad54f01edb508dce14cd07a8dd..d1afd8c6d95457c28d7e1de6935908437372572d 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -28,6 +28,7 @@ struct dw_mipi_csi2_config {
 	u32	sink_pad_mask;
 	bool	has_phy: 1;
 	bool	has_irq: 1;
+	bool	need_dphy_reset: 1;
 };
 
 struct dw_mipi_tstif {

-- 
2.34.1


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

* [PATCH v2 26/32] media: synopsys: csi2: Add default simple dw_csi2_subdev_init_state
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (24 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 25/32] media: synopsys: csi2: Add need_dphy_reset in config Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 27/32] media: synopsys: csi2: Add v150 lane stop state register bit define Frank Li
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add default simple dw_csi2_subdev_init_state, which have 1 sink and 1
source pad, 1920x1080p and MEDIA_BUS_FMT_UYVY8_1X16 format.

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

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index d1f08c8384ad45d47ffe81b6dc5f225aed43e21a..7a3776df3e074aa823ae89c824bb942475c95045 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -831,6 +831,59 @@ static const struct v4l2_async_notifier_operations csi2_notify_ops = {
 	.unbind = csi2_notify_unbind,
 };
 
+static const struct v4l2_mbus_framefmt dwc_csi_default_fmt = {
+	.code = MEDIA_BUS_FMT_UYVY8_1X16,
+	.width = 1920,
+	.height = 1080,
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_SMPTE170M,
+	.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SMPTE170M),
+	.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SMPTE170M),
+	.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+};
+
+static int dw_csi2_subdev_set_routing(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_state *state,
+				      struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
+		return -EINVAL;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &dwc_csi_default_fmt);
+}
+
+static int dw_csi2_subdev_init_state_simple(struct v4l2_subdev *sd,
+					    struct v4l2_subdev_state *sd_state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = 0,
+			.sink_stream = 0,
+			.source_pad = 1,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	return dw_csi2_subdev_set_routing(sd, sd_state, &routing);
+}
+
+static const struct v4l2_subdev_internal_ops dw_csi2_simple_internal_ops = {
+	.init_state = dw_csi2_subdev_init_state_simple,
+};
+
 static int csi2_async_register(struct dw_mipi_csi2_dev *csi2)
 {
 	struct v4l2_fwnode_endpoint vep = {
@@ -954,7 +1007,9 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 
 	csi2->sd.owner = config->module;
 	strscpy(csi2->sd.name, config->name, sizeof(csi2->sd.name));
-	csi2->sd.internal_ops = config->internal_ops;
+	csi2->sd.internal_ops = config->internal_ops ?
+					config->internal_ops :
+					&dw_csi2_simple_internal_ops;
 	csi2->sd.grp_id = config->grp_id;
 	csi2->config = config;
 

-- 
2.34.1


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

* [PATCH v2 27/32] media: synopsys: csi2: Add v150 lane stop state register bit define
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (25 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 26/32] media: synopsys: csi2: Add default simple dw_csi2_subdev_init_state Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 28/32] media: synopsys: csi2: use standard v4l2_subdev_get_fmt() function Frank Li
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

v150 move lane stop state into new register phy_stopstate and field
position also changed.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 40 +++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 7a3776df3e074aa823ae89c824bb942475c95045..a9bf7ce57adc4d2b071f2f7c39f19855dc226a40 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -31,6 +31,7 @@ struct dw_csi2_regs {
 	u32	dphy_rstz;
 	u32	resetn;
 	u32	phy_state;
+	u32	phy_stopstate;
 	u32	data_ids_1;
 	u32	data_ids_2;
 	u32	err1;
@@ -86,6 +87,7 @@ static const struct dw_csi2_regs dw_csi2_v150 = {
 	.phy_shutdownz = DW_REG(0x40),
 	.dphy_rstz = DW_REG(0x44),
 	.phy_state = DW_REG(0x48),
+	.phy_stopstate = DW_REG(0x4c),
 	.phy_tst_ctrl0 = DW_REG(0x50),
 	.phy_tst_ctrl1 = DW_REG(0x54),
 	.int_st_dphy_fatal = DW_REG(0xe0),
@@ -147,10 +149,13 @@ readl((csi2)->base + ((csi2)->regs->__name & ~DW_REG_EXIST)) : \
 dw_csi2_reg_err(csi2, #__name))
 
 #define PHY_STATE_STOPSTATEDATA_BIT	4
+#define PHY_STATE_STOPSTATEDATA_BIT_V150	0
 #define PHY_STATE_STOPSTATEDATA(n)	BIT(PHY_STATE_STOPSTATEDATA_BIT + (n))
 #define PHY_STATE_RXCLKACTIVEHS	BIT(8)
+#define PHY_STATE_RXCLKACTIVEHS_V150	BIT(17)
 #define PHY_STATE_RXULPSCLKNOT	BIT(9)
 #define PHY_STATE_STOPSTATECLK	BIT(10)
+#define PHY_STATE_STOPSTATECLK_V150		BIT(16)
 
 #define DPHY_TEST_CTRL0_TEST_CLR		BIT(0)
 #define DPHY_TEST_CTRL0_TEST_CLKEN	BIT(1)
@@ -289,7 +294,8 @@ static int __maybe_unused csi2_dphy_wait_ulp(struct dw_mipi_csi2_dev *csi2)
 }
 
 /* Waits for low-power LP-11 state on data and clock lanes. */
-static void csi2_dphy_wait_stopstate(struct dw_mipi_csi2_dev *csi2, unsigned int lanes)
+static void csi2_dphy_wait_stopstate_v0(struct dw_mipi_csi2_dev *csi2,
+					unsigned int lanes)
 {
 	u32 mask, reg;
 	int ret;
@@ -303,13 +309,43 @@ static void csi2_dphy_wait_stopstate(struct dw_mipi_csi2_dev *csi2, unsigned int
 	}
 }
 
+static void csi2_dphy_wait_stopstate_v150(struct dw_mipi_csi2_dev *csi2,
+					  unsigned int lanes)
+{
+	u32 mask, reg;
+	int ret;
+
+	mask = PHY_STATE_STOPSTATECLK_V150 | (((1 << lanes) - 1) <<
+	       PHY_STATE_STOPSTATEDATA_BIT_V150);
+
+	ret = read_poll_timeout(dw_readl, reg, (reg & mask) == mask, 0, 500000,
+				0, csi2, phy_stopstate);
+	if (ret) {
+		v4l2_warn(&csi2->sd, "LP-11 wait timeout, likely a sensor driver bug, expect capture failures.\n");
+		v4l2_warn(&csi2->sd, "phy_state = 0x%08x\n", reg);
+	}
+}
+
+static void csi2_dphy_wait_stopstate(struct dw_mipi_csi2_dev *csi2,
+				     unsigned int lanes)
+{
+	if (csi2->regs == &dw_csi2_v0)
+		return csi2_dphy_wait_stopstate_v0(csi2, lanes);
+
+	csi2_dphy_wait_stopstate_v150(csi2, lanes);
+}
+
 /* Wait for active clock on the clock lane. */
 static int csi2_dphy_wait_clock_lane(struct dw_mipi_csi2_dev *csi2)
 {
+	u32 mask;
 	u32 reg;
 	int ret;
 
-	ret = read_poll_timeout(dw_readl, reg, (reg & PHY_STATE_RXCLKACTIVEHS),
+	mask = csi2->regs == &dw_csi2_v0 ?  PHY_STATE_RXCLKACTIVEHS :
+					    PHY_STATE_RXCLKACTIVEHS_V150;
+
+	ret = read_poll_timeout(dw_readl, reg, (reg & mask),
 				0, 500000, 0, csi2, phy_state);
 	if (ret) {
 		v4l2_err(&csi2->sd, "clock lane timeout, phy_state = 0x%08x\n",

-- 
2.34.1


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

* [PATCH v2 28/32] media: synopsys: csi2: use standard v4l2_subdev_get_fmt() function
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (26 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 27/32] media: synopsys: csi2: Add v150 lane stop state register bit define Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 29/32] media: synopsys: csi2: Add customize get_frame_desc() callback Frank Li
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Use standard v4l2_subdev_get_fmt() to simple code and add missed call
v4l2_subdev_init_finalize().

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 49 ++++++++++-------------------
 1 file changed, 16 insertions(+), 33 deletions(-)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index a9bf7ce57adc4d2b071f2f7c39f19855dc226a40..f174dfded167fbd52a72894c3f63871812ca799b 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -714,38 +714,13 @@ static int csi2_link_setup(struct media_entity *entity,
 	return ret;
 }
 
-static struct v4l2_mbus_framefmt *
-__csi2_get_fmt(struct dw_mipi_csi2_dev *csi2, struct v4l2_subdev_state *sd_state,
-	       unsigned int pad, enum v4l2_subdev_format_whence which)
-{
-	if (which == V4L2_SUBDEV_FORMAT_TRY)
-		return v4l2_subdev_state_get_format(sd_state, pad);
-	else
-		return &csi2->format_mbus;
-}
-
-static int csi2_get_fmt(struct v4l2_subdev *sd,
-			struct v4l2_subdev_state *sd_state,
-			struct v4l2_subdev_format *sdformat)
-{
-	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
-	struct v4l2_mbus_framefmt *fmt;
-
-	guard(mutex)(&csi2->lock);
-
-	fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
-
-	sdformat->format = *fmt;
-
-	return 0;
-}
-
 static int csi2_set_fmt(struct v4l2_subdev *sd,
 			struct v4l2_subdev_state *sd_state,
 			struct v4l2_subdev_format *sdformat)
 {
 	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
 	struct v4l2_mbus_framefmt *fmt;
+	int i;
 	u32 align;
 	u32 bpp;
 
@@ -756,7 +731,7 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 	 * The CSIS can't transcode in any way, the source format can't be
 	 * modified.
 	 */
-	if (sdformat->pad < csi2->num_src_pads)
+	if (csi2->pad[sdformat->pad].flags == MEDIA_PAD_FL_SOURCE)
 		return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
 
 	guard(mutex)(&csi2->lock);
@@ -771,13 +746,17 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 	v4l_bound_align_image(&sdformat->format.width, 1, U16_MAX, align,
 			      &sdformat->format.height, 1, U16_MAX, 0, 0);
 
-	/* Output pads mirror active input pad, no limits on input pads */
-	if (!(csi2->config->sink_pad_mask & BIT(sdformat->pad)))
-		sdformat->format = csi2->format_mbus;
+	fmt = v4l2_subdev_state_get_format(sd_state, sdformat->pad);
+	*fmt = sdformat->format;
 
-	fmt = __csi2_get_fmt(csi2, sd_state, sdformat->pad, sdformat->which);
+	/* Output pads mirror active input pad, no limits on input pads */
+	for (i = 0; i < csi2->config->num_pads; i++)
+		if (csi2->pad[i].flags == MEDIA_PAD_FL_SOURCE) {
+			fmt = v4l2_subdev_state_get_format(sd_state, i);
+			*fmt = sdformat->format;
+		}
 
-	*fmt = sdformat->format;
+	csi2->format_mbus = *fmt;
 
 	return 0;
 }
@@ -818,7 +797,7 @@ static const struct media_entity_operations csi2_entity_ops = {
 };
 
 static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
-	.get_fmt = csi2_get_fmt,
+	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = csi2_set_fmt,
 	.enable_streams = dw_csi2_enable_streams,
 	.disable_streams = dw_csi2_disable_streams,
@@ -1071,6 +1050,10 @@ int dw_mipi_csi2_init(struct platform_device *pdev, struct dw_mipi_csi2_dev *csi
 	if (ret)
 		return ret;
 
+	ret = v4l2_subdev_init_finalize(&csi2->sd);
+	if (ret)
+		return ret;
+
 	ret = devm_add_action_or_reset(&pdev->dev, csi2_nf_cleanup, csi2);
 	if (ret)
 		return ret;

-- 
2.34.1


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

* [PATCH v2 29/32] media: synopsys: csi2: Add customize get_frame_desc() callback
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (27 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 28/32] media: synopsys: csi2: use standard v4l2_subdev_get_fmt() function Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 30/32] media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150 Frank Li
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add customize get_frame_desc() callback to work with existed isi drivers.

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

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index f174dfded167fbd52a72894c3f63871812ca799b..8051cfcd8ee158c5efccae9aff124c01a878e916 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -761,6 +761,78 @@ static int csi2_set_fmt(struct v4l2_subdev *sd,
 	return 0;
 }
 
+static int dw_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				  struct v4l2_mbus_frame_desc *fd)
+{
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
+	struct v4l2_mbus_frame_desc source_fd;
+	struct v4l2_subdev_route *route;
+	struct v4l2_subdev_state *state;
+	int data_type;
+	int ret;
+
+	if (!(csi2->pad[pad].flags & MEDIA_PAD_FL_SOURCE))
+		return -EINVAL;
+
+	memset(fd, 0, sizeof(*fd));
+
+	data_type = media_bus_fmt_to_csi2_dt(csi2->format_mbus.code);
+
+	ret = v4l2_subdev_call(csi2->src_sd, pad, get_frame_desc,
+			       csi2->remote_pad, &source_fd);
+	if (ret < 0) {
+		dev_info(csi2->dev,
+			 "Remote sub-device on pad %d should implement .get_frame_desc! Forcing VC = 0 and DT = %x\n",
+			 pad, data_type);
+		fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+		fd->num_entries = 1;
+		fd->entry[0].pixelcode = csi2->format_mbus.code;
+		fd->entry[0].bus.csi2.vc = 0;
+		fd->entry[0].bus.csi2.dt = data_type;
+
+		return 0;
+	}
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	for_each_active_route(&state->routing, route) {
+		struct v4l2_mbus_frame_desc_entry *entry = NULL;
+		unsigned int i;
+
+		if (route->source_pad != pad)
+			continue;
+
+		for (i = 0; i < source_fd.num_entries; ++i) {
+			if (source_fd.entry[i].stream == route->sink_stream) {
+				entry = &source_fd.entry[i];
+				break;
+			}
+		}
+
+		if (!entry) {
+			dev_err(csi2->dev,
+				"Failed to find stream from source frames desc\n");
+			ret = -EPIPE;
+			goto out_unlock;
+		}
+
+		fd->entry[fd->num_entries].stream = route->source_stream;
+		fd->entry[fd->num_entries].flags = entry->flags;
+		fd->entry[fd->num_entries].length = entry->length;
+		fd->entry[fd->num_entries].pixelcode = entry->pixelcode;
+		fd->entry[fd->num_entries].bus.csi2.vc = entry->bus.csi2.vc;
+		fd->entry[fd->num_entries].bus.csi2.dt = entry->bus.csi2.dt;
+
+		fd->num_entries++;
+	}
+
+out_unlock:
+	v4l2_subdev_unlock_state(state);
+	return ret;
+}
+
 /* --------------- CORE OPS --------------- */
 
 static int csi2_log_status(struct v4l2_subdev *sd)
@@ -799,6 +871,7 @@ static const struct media_entity_operations csi2_entity_ops = {
 static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
 	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = csi2_set_fmt,
+	.get_frame_desc = dw_csi2_get_frame_desc,
 	.enable_streams = dw_csi2_enable_streams,
 	.disable_streams = dw_csi2_disable_streams,
 };

-- 
2.34.1


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

* [PATCH v2 30/32] media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (28 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 29/32] media: synopsys: csi2: Add customize get_frame_desc() callback Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 31/32] media: synopsys: csi2: Remove source pad connected check at dw_csi2_enable_streams() Frank Li
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add Image Pixel Interface (IPI) support for v150. Check the ipi_mode
register to determine whether the hardware supports IPI.

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

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 8051cfcd8ee158c5efccae9aff124c01a878e916..48ae455a77b2365b6df8a79a366b37c7f1dfe590 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -40,6 +40,11 @@ struct dw_csi2_regs {
 	u32	msk2;
 	u32	phy_tst_ctrl0;
 	u32	phy_tst_ctrl1;
+	u32	ipi_softrstn;
+	u32	ipi_datatype;
+	u32	ipi_vcid;
+	u32	ipi_mode;
+	u32	ipi_mem_flush;
 	u32	int_st_main;
 	u32	int_st_dphy_fatal;
 	u32	int_msk_dphy_fatal;
@@ -90,6 +95,11 @@ static const struct dw_csi2_regs dw_csi2_v150 = {
 	.phy_stopstate = DW_REG(0x4c),
 	.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),
 	.int_st_dphy_fatal = DW_REG(0xe0),
 	.int_msk_dphy_fatal = DW_REG(0xe4),
 	.int_force_dphy_fatal = DW_REG(0xe8),
@@ -115,6 +125,31 @@ static const struct dw_csi2_regs dw_csi2_v150 = {
 #define INT_ST_MAIN_ERR_PHY			BIT(16)
 #define INT_ST_MAIN_FATAL_ERR_IPI		BIT(18)
 
+#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)
+
+#define INT_ST_MAIN_FATAL_ERR_PHY		BIT(0)
+#define INT_ST_MAIN_FATAL_ERR_PKT		BIT(1)
+#define INT_ST_MAIN_FATAL_ERR_BNDRY_FRAMEL	BIT(2)
+#define INT_ST_MAIN_FATAL_ERR_SEQ_FRAME		BIT(3)
+#define INT_ST_MAIN_FATAL_ERR_CRC_FRAME		BIT(4)
+#define INT_ST_MAIN_FATAL_ERR_PLD_CRC		BIT(5)
+#define INT_ST_MAIN_ERR_DID			BIT(6)
+#define INT_ST_MAIN_ERR_ECC			BIT(7)
+#define INT_ST_MAIN_ERR_PHY			BIT(16)
+#define INT_ST_MAIN_FATAL_ERR_IPI		BIT(18)
+
 #define INT_MSK_DPHY_FATAL_ERR_SOT_LANE0	BIT(0)
 #define INT_MSK_DPHY_FATAL_ERR_SOT_LANE1	BIT(1)
 
@@ -449,6 +484,48 @@ static int dw_mipi_csi2_phy_prep(struct dw_mipi_csi2_dev *csi2, int bpp)
 	return ret;
 }
 
+static void dw_csi2_device_ipi_config(struct dw_mipi_csi2_dev *csi2)
+{
+	int dt = media_bus_fmt_to_csi2_dt(csi2->format_mbus.code);
+	u32 val;
+
+	/* Do IPI soft reset */
+	dw_writel(csi2, 0x0, ipi_softrstn);
+	dw_writel(csi2, 0x1, ipi_softrstn);
+
+	/* Select virtual channel and data type to be processed by IPI */
+	val = IPI_DATA_TYPE_DT(dt);
+	dw_writel(csi2, val, ipi_datatype);
+
+	/* Set virtual channel 0 as default */
+	val  = IPI_VCID_VC(0);
+	dw_writel(csi2, val, ipi_vcid);
+
+	/*
+	 * Select IPI camera timing mode and allow the pixel stream
+	 * to be non-continuous when pixel interface FIFO is empty
+	 */
+	val = dw_readl(csi2, ipi_mode);
+	val &= ~IPI_MODE_CONTROLLER;
+	val &= ~IPI_MODE_COLOR_MODE16;
+	val |= IPI_MODE_CUT_THROUGH;
+	dw_writel(csi2, val, ipi_mode);
+}
+
+static void dw_csi2_ipi_enable(struct dw_mipi_csi2_dev *csi2)
+{
+	u32 val;
+
+	/* Memory is automatically flushed at each Frame Start */
+	val = IPI_MEM_FLUSH_AUTO;
+	dw_writel(csi2, val, ipi_mem_flush);
+
+	/* Enable IPI */
+	val = dw_readl(csi2, ipi_mode);
+	val |= IPI_MODE_ENABLE;
+	dw_writel(csi2, val, ipi_mode);
+}
+
 static void dw_csi2_enable_irq(struct dw_mipi_csi2_dev *csi2)
 {
 	u32 val;
@@ -583,6 +660,11 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp)
 	if (ret)
 		goto err_stop_upstream;
 
+	if (csi2->regs->ipi_mode) {
+		dw_csi2_device_ipi_config(csi2);
+		dw_csi2_ipi_enable(csi2);
+	}
+
 	dw_csi2_enable_irq(csi2);
 
 	return 0;

-- 
2.34.1


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

* [PATCH v2 31/32] media: synopsys: csi2: Remove source pad connected check at dw_csi2_enable_streams()
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (29 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 30/32] media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150 Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-08 22:39 ` [PATCH v2 32/32] media: synopsys: csi2: Add simple synopsys platform driver Frank Li
  2025-08-20 14:39 ` [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

link_setup() callback is not called if remote linked subdev use flag
MEDIA_LNK_FL_ENABLED.

Driver needn't track if source pad is connected since framework already do
that. So remove these check and related variable.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/mipi-csi2.c | 21 +++------------------
 include/media/dw-mipi-csi2.h                |  1 -
 2 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 48ae455a77b2365b6df8a79a366b37c7f1dfe590..01c590a953f3f89ebb56bc42e820b09a8afbf5b9 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c
@@ -710,18 +710,12 @@ static int dw_csi2_enable_streams(struct v4l2_subdev *sd,
 				  u64 streams_mask)
 {
 	struct dw_mipi_csi2_dev *csi2 = sd_to_dev(sd);
-	int i, ret = 0;
+	int ret = 0;
 
 	guard(mutex)(&csi2->lock);
 
-	if (!csi2->src_sd)
-		return -EPIPE;
 
-	for (i = 0; i < csi2->num_sink_pads; i++) {
-		if (csi2->sink_linked[i])
-			break;
-	}
-	if (i >= csi2->num_sink_pads)
+	if (!csi2->src_sd)
 		return -EPIPE;
 
 	if (csi2->stream_count)
@@ -773,16 +767,7 @@ static int csi2_link_setup(struct media_entity *entity,
 
 	guard(mutex)(&csi2->lock);
 
-	if (local->flags & MEDIA_PAD_FL_SOURCE) {
-		if (flags & MEDIA_LNK_FL_ENABLED) {
-			if (csi2->sink_linked[local->index - 1])
-				return -EBUSY;
-
-			csi2->sink_linked[local->index - 1] = true;
-		} else {
-			csi2->sink_linked[local->index - 1] = false;
-		}
-	} else {
+	if (local->flags & MEDIA_PAD_FL_SINK) {
 		if (flags & MEDIA_LNK_FL_ENABLED) {
 			if (csi2->src_sd)
 				return -EBUSY;
diff --git a/include/media/dw-mipi-csi2.h b/include/media/dw-mipi-csi2.h
index d1afd8c6d95457c28d7e1de6935908437372572d..977a9e27cc50ad6ecfb47ebf8d42f115bc51c1ae 100644
--- a/include/media/dw-mipi-csi2.h
+++ b/include/media/dw-mipi-csi2.h
@@ -75,7 +75,6 @@ struct dw_mipi_csi2_dev {
 
 	int				stream_count;
 	struct v4l2_subdev		*src_sd;
-	bool				sink_linked[DW_MAX_PAD_NUM];
 	const struct dw_mipi_csi2_config *config;
 
 	struct dw_csi2_event		*event;

-- 
2.34.1


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

* [PATCH v2 32/32] media: synopsys: csi2: Add simple synopsys platform driver
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (30 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 31/32] media: synopsys: csi2: Remove source pad connected check at dw_csi2_enable_streams() Frank Li
@ 2025-08-08 22:39 ` Frank Li
  2025-08-20 14:39 ` [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-08 22:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Frank Li

Add simple synosys platform driver, which use standard PHY interface and
only 1 sink and 1 source pad. No format convert between source and sink
pad.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/media/platform/synopsys/Kconfig            |  8 +++
 drivers/media/platform/synopsys/Makefile           |  1 +
 drivers/media/platform/synopsys/mipi-csi2-simple.c | 75 ++++++++++++++++++++++
 3 files changed, 84 insertions(+)

diff --git a/drivers/media/platform/synopsys/Kconfig b/drivers/media/platform/synopsys/Kconfig
index e54dad835349d420dead6d5313c0623567c28c0b..642b7dcd8dfb1bafa3b6dbdba1a1d99559d3c01a 100644
--- a/drivers/media/platform/synopsys/Kconfig
+++ b/drivers/media/platform/synopsys/Kconfig
@@ -12,4 +12,12 @@ config VIDEO_SYNOPSYS_MIPI_CSI2
           To compile this driver as a module, choose M here. The module
           will be called synopsys_hdmirx
 
+config VIDEO_SYNOPSYS_MIPI_CSI2_SIMPLE
+	tristate "Simple Synopsys DesignWare HDMI Receiver platform driver"
+	depends on VIDEO_SYNOPSYS_MIPI_CSI2
+	help
+	  Simple platform Synopsys MIPI CSI2 platform driver, which not format
+	  convert between sink and source pad. Only 1 source pad and 1 sink
+	  pad, use standard PHY interface to initialize DPHY.
+
 source "drivers/media/platform/synopsys/hdmirx/Kconfig"
diff --git a/drivers/media/platform/synopsys/Makefile b/drivers/media/platform/synopsys/Makefile
index 045ed3177738e6d28aa223804b79e6774e141dc8..cac610c8e08abeebdbf14157d8edcdc5a635dd00 100644
--- a/drivers/media/platform/synopsys/Makefile
+++ b/drivers/media/platform/synopsys/Makefile
@@ -2,3 +2,4 @@
 obj-y += hdmirx/
 
 obj-$(CONFIG_VIDEO_SYNOPSYS_MIPI_CSI2) += mipi-csi2.o
+obj-$(CONFIG_VIDEO_SYNOPSYS_MIPI_CSI2_SIMPLE) += mipi-csi2-simple.o
diff --git a/drivers/media/platform/synopsys/mipi-csi2-simple.c b/drivers/media/platform/synopsys/mipi-csi2-simple.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf34a515b41290339db06d74d7135c575a8bf031
--- /dev/null
+++ b/drivers/media/platform/synopsys/mipi-csi2-simple.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Synosis MIPI CSI-2 Simple platform driver
+ *
+ * Copyright (c) 2025 NXP.
+ */
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+
+#include <media/dw-mipi-csi2.h>
+
+struct simple_csi2 {
+	struct dw_mipi_csi2_dev dw;
+};
+
+static const struct dw_mipi_csi2_config simple_config = {
+	.module = THIS_MODULE,
+	.name = "dw-mipi-csi2",
+	.num_pads = 2,
+	.sink_pad_mask = BIT(0),
+	.has_irq = true,
+	.has_phy = true,
+	.need_dphy_reset = true,
+};
+
+static DEFINE_RUNTIME_DEV_PM_OPS(csi2_pm_ops, dw_mipi_csi2_runtime_suspend,
+				 dw_mipi_csi2_runtime_resume, NULL);
+
+static int csi2_probe(struct platform_device *pdev)
+{
+	struct simple_csi2 *csi2;
+
+	csi2 = devm_kzalloc(&pdev->dev, sizeof(*csi2), GFP_KERNEL);
+	if (!csi2)
+		return -ENOMEM;
+
+	return dw_mipi_csi2_init(pdev, &csi2->dw, &simple_config);
+}
+
+static void csi2_remove(struct platform_device *pdev)
+{
+	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+	struct dw_mipi_csi2_dev *csi2 = sd_to_dw_mipi_csi2_dev(sd);
+
+	dw_mipi_csi2_deinit(csi2);
+}
+
+static const struct of_device_id csi2_dt_ids[] = {
+	{ .compatible = "snps,dw-mipi-csi2-v150" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, csi2_dt_ids);
+
+static struct platform_driver csi2_driver = {
+	.driver = {
+		.name = "dw-mipi-csi2",
+		.of_match_table = csi2_dt_ids,
+		.pm = pm_ptr(&csi2_pm_ops),
+	},
+	.probe = csi2_probe,
+	.remove = csi2_remove,
+};
+
+module_platform_driver(csi2_driver);
+
+MODULE_DESCRIPTION("Simple Synosis MIPI CSI-2 Receiver platform driver");
+MODULE_AUTHOR("Frank Li <Frank.li@nxp.com>");
+MODULE_LICENSE("GPL");

-- 
2.34.1


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

* Re: [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support
  2025-08-08 22:39 ` [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support Frank Li
@ 2025-08-18 14:39   ` Rob Herring
  0 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2025-08-18 14:39 UTC (permalink / raw)
  To: Frank Li
  Cc: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Krzysztof Kozlowski,
	Conor Dooley, Eugen Hristev, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Peng Fan, Alice Yuan,
	Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman, linux-media, devicetree,
	linux-kernel, imx, linux-arm-kernel, linux-phy, linux-staging,
	Luis Oliveira

On Fri, Aug 08, 2025 at 06:39:04PM -0400, Frank Li wrote:
> From: Eugen Hristev <eugen.hristev@linaro.org>
> 
> Add bindings for Synopsys DesignWare MIPI CSI-2 host, which used at i.MX93
> and i.MX95 platform.
> 
> Signed-off-by: Luis Oliveira <lolivei@synopsys.com>
> Signed-off-by: Eugen Hristev <eugen.hristev@linaro.org>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Change in v2
> - remove Eugen Hristev <eugen.hristev@microchip.com> from mantainer.
> - update ugen Hristev's s-o-b tag to align original author's email address
> - remove single snps,dw-mipi-csi2-v150 compatible string
> - move additionalProperties after required
> ---
>  .../bindings/media/snps,dw-mipi-csi2-v150.yaml     | 158 +++++++++++++++++++++
>  MAINTAINERS                                        |   1 +
>  2 files changed, 159 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml b/Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..fc1b167d6d3b142a01e2ea7f04230934260a05e6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/snps,dw-mipi-csi2-v150.yaml
> @@ -0,0 +1,158 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/snps,dw-mipi-csi2-v150.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Synopsys DesignWare CSI-2 Host controller (csi2host)
> +
> +maintainers:
> +  - Frank Li <Frank.Li@nxp.com>
> +
> +description:
> +  CSI2HOST is used to receive image coming from an MIPI CSI-2 compatible
> +  camera. It will convert the incoming CSI-2 stream into a dedicated
> +  interface called the Synopsys IDI (Image Data Interface).
> +  This interface is a 32-bit SoC internal only, and can be assimilated
> +  with a CSI-2 interface.
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - fsl,imx93-mipi-csi2
> +      - const: snps,dw-mipi-csi2-v150
> +
> +  reg:
> +    items:
> +      - description: MIPI CSI-2 core register
> +
> +  reg-names:
> +    items:
> +      - const: core
> +
> +  clocks:
> +    maxItems: 2
> +
> +  clock-names:
> +    items:
> +      - const: per
> +      - const: pixel
> +
> +  phys:
> +    maxItems: 1
> +    description: MIPI D-PHY
> +
> +  phy-names:
> +    items:
> +      - const: rx
> +
> +  resets:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    properties:
> +      port@0:
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        description:
> +          Input port node, single endpoint describing the input port.
> +
> +        properties:
> +          endpoint:
> +            $ref: video-interfaces.yaml#
> +            unevaluatedProperties: false
> +            description: Endpoint connected to input device
> +
> +            properties:
> +              bus-type:
> +                const: 4
> +
> +              data-lanes:
> +                minItems: 1
> +                maxItems: 4
> +                items:
> +                  maximum: 4
> +
> +              clock-lanes:
> +                maxItems: 1

Drop. clock-lanes is always 1 entry.

> +
> +              remote-endpoint: true

Drop.

> +
> +      port@1:
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        description:
> +          Output port node, single endpoint describing the output port.
> +
> +        properties:
> +          endpoint:
> +            unevaluatedProperties: false
> +            $ref: video-interfaces.yaml#
> +            description: Endpoint connected to output device
> +
> +            properties:
> +              bus-type:
> +                const: 4
> +
> +              remote-endpoint: true

Drop.

Rob

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

* Re: [PATCH v2 00/32] media: add imx93 mipi/controller csi support
  2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
                   ` (31 preceding siblings ...)
  2025-08-08 22:39 ` [PATCH v2 32/32] media: synopsys: csi2: Add simple synopsys platform driver Frank Li
@ 2025-08-20 14:39 ` Frank Li
  32 siblings, 0 replies; 36+ messages in thread
From: Frank Li @ 2025-08-20 14:39 UTC (permalink / raw)
  To: Rui Miguel Silva, Laurent Pinchart, Martin Kepplinger,
	Purism Kernel Team, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Eugen Hristev, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
	Alice Yuan, Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman
  Cc: linux-media, devicetree, linux-kernel, imx, linux-arm-kernel,
	linux-phy, linux-staging, Luis Oliveira

On Fri, Aug 08, 2025 at 06:39:03PM -0400, Frank Li wrote:
> Totally rewrite CSI part driver compared to V1.

Laurent Pinchart:

	Not sure if you have chance to look this patches, which is big
changeset.

	Please check first 3 patches firstly, which help reduce many
hardcode in current code base.

	media: v4l2-common: Add helper function v4l_get_required_align_by_bpp()
	media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp()
	media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt()

	The other patchset https://lore.kernel.org/imx/20250820-csi2_imx8mq-v5-0-e04a6fc593bd@nxp.com/T/#t
depend on this first 3 patches.

Frank
>
> This only includes CSI related patches.
>
> DTS part: see https://lore.kernel.org/imx/20250701-95_cam-v1-6-c5172bab387b@nxp.com/
> PHY part: see https://lore.kernel.org/imx/20250701-95_cam-v1-4-c5172bab387b@nxp.com/
> AP1302 part: see https://lore.kernel.org/imx/20250701-95_cam-v1-7-c5172bab387b@nxp.com/
> 	upstream: https://lore.kernel.org/imx/20250623-ap1302-v3-0-c9ca5b791494@nxp.com/
>
> First 3 patches add some common helper function to simple code and remove
> duplicated code in difference CSI2 drivers.
>
> Clean up stage imx6 old version csi2 driver, and prepare create common
> dw csi2 library for difference IP version.
>
> Move stage driver under driver/media/synosis.
>
> Create simple platform driver for common dw csi2 use case.
>
> TODO:
> 	1. create bus, to probe phy driver under "test_if" interface for
> specific phys under CSI2.
> 	2. support to combine phy, (which connect to both dw CSI and DSI's
> test_if). Need use DSI's test_if to config combo phy to switch to RX mode.
> and also need config RX part's phy register by use CSI's testif.
> 	3. move other vendor's csi driver to use this common DWC CSI
> library.
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Changes in v2:
> - totally rewrite, see above section
> - Link to v1: https://lore.kernel.org/r/20250701-95_cam-v1-0-c5172bab387b@nxp.com
>
> ---
> Eugen Hristev (1):
>       dt-bindings: media: add DW MIPI CSI-2 Host support
>
> Frank Li (31):
>       media: v4l2-common: Add helper function v4l_get_required_align_by_bpp()
>       media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp()
>       media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt()
>       media: staging: media: imx6-mipi-csi2: replace space with tab for alignment
>       media: staging: media: imx6-mipi-csi2: use devm_add_action_or_reset() to simplify code
>       media: staging: media: imx6-mipi-csi2: use devm_clk_bulk_get_all() to fetch clocks
>       media: staging: media: imx6-mipi-csi2: use devm_mutex_init() to simplify code
>       media: staging: media: imx6-mipi-csi2: use guard() to simplify code
>       media: staging: media: imx6-mipi-csi2: use register structure to match hardware
>       media: staging: media: imx6-mipi-csi2: use devm_platform_ioremap_resource() simplify code
>       media: staging: media: imx6-mipi-csi2: move probe part to imx6-csi2.c
>       media: staging: media: imx6-mipi-csi2: move sd imx6's specific initialization into imx6-sci2.c
>       media: staging: media: imx6-mipi-csi2: move csi2ipu_gasket_init() to imx6-csi2.c
>       media: staging: media: imx6-mipi-csi2: move number pad macro define into imx6-csi2.c
>       media: staging: media: imx6-mipi-csi2: move dphy init part to imx6-csi2.c
>       media: staging: media: imx6-mipi-csi2: use runtime_pm frame to control clks
>       media: synopsys: move imx6-mipi-csi2.c to synopsys/mipi-csi2.c
>       media: synopsys: csi2: Remove deprecated s_stream and use v4l2_subdev_pad_ops
>       media: synopsys: csi2: Add phy interface support
>       media: synopsys: csi2: Add basic v150* version register
>       media: synopsys: csi2: Add irq support to record error count
>       media: synopsys: csi2: Handle alignment requirement for width
>       media: synopsys: csi2: Add register prefix to register field definitions
>       media: synopsys: csi2: Add need_dphy_reset in config
>       media: synopsys: csi2: Add default simple dw_csi2_subdev_init_state
>       media: synopsys: csi2: Add v150 lane stop state register bit define
>       media: synopsys: csi2: use standard v4l2_subdev_get_fmt() function
>       media: synopsys: csi2: Add customize get_frame_desc() callback
>       media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150
>       media: synopsys: csi2: Remove source pad connected check at dw_csi2_enable_streams()
>       media: synopsys: csi2: Add simple synopsys platform driver
>
>  .../bindings/media/snps,dw-mipi-csi2-v150.yaml     |  158 +++
>  MAINTAINERS                                        |    1 +
>  drivers/media/platform/synopsys/Kconfig            |   20 +
>  drivers/media/platform/synopsys/Makefile           |    3 +
>  drivers/media/platform/synopsys/mipi-csi2-simple.c |   75 ++
>  drivers/media/platform/synopsys/mipi-csi2.c        | 1258 ++++++++++++++++++++
>  drivers/media/v4l2-core/v4l2-common.c              |  220 ++++
>  drivers/staging/media/imx/Kconfig                  |    1 +
>  drivers/staging/media/imx/Makefile                 |    2 +-
>  drivers/staging/media/imx/imx6-csi2.c              |  181 +++
>  drivers/staging/media/imx/imx6-mipi-csi2.c         |  846 -------------
>  include/media/dw-mipi-csi2.h                       |  120 ++
>  include/media/mipi-csi2.h                          |    5 +
>  include/media/v4l2-common.h                        |   30 +
>  14 files changed, 2073 insertions(+), 847 deletions(-)
> ---
> base-commit: 33652d58b64e92d2598205fd992989bd93cd61f4
> change-id: 20250606-95_cam-b74c094ad1fb
>
> Best regards,
> --
> Frank Li <Frank.Li@nxp.com>
>

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

* Re: [PATCH v2 04/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt()
  2025-08-08 22:39 ` [PATCH v2 04/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt() Frank Li
@ 2025-08-20 19:16   ` Laurent Pinchart
  0 siblings, 0 replies; 36+ messages in thread
From: Laurent Pinchart @ 2025-08-20 19:16 UTC (permalink / raw)
  To: Frank Li
  Cc: Rui Miguel Silva, Martin Kepplinger, Purism Kernel Team,
	Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Eugen Hristev, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Peng Fan, Alice Yuan,
	Vinod Koul, Kishon Vijay Abraham I, Philipp Zabel,
	Steve Longerbeam, Greg Kroah-Hartman, linux-media, devicetree,
	linux-kernel, imx, linux-arm-kernel, linux-phy, linux-staging

Hi Frank,

Thank you for the patch.

On Fri, Aug 08, 2025 at 06:39:07PM -0400, Frank Li wrote:
> CSI2 data type is defined by MIPI Camera Serial Interface 2 Spec Ver4.1.
> See section 9.4.
> 
> Add helper function media_bus_fmt_to_csi2_dt() to convert media bus fmt to
> MIPI defined data type and avoid below duplicated static array in each CSI2
> drivers.
> 
> 	{
> 		.code = MEDIA_BUS_FMT_UYVY8_1X16,
> 		.data_type = MIPI_CSI2_DT_YUV422_8B,
> 	}
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/media/v4l2-core/v4l2-common.c | 44 +++++++++++++++++++++++++++++++++++
>  include/media/mipi-csi2.h             |  3 +++
>  2 files changed, 47 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
> index 3a48b6a55c6e322696b910dd519def4f0b4a58fb..fcc01030beb347499da2a3c8539793d20f6f512c 100644
> --- a/drivers/media/v4l2-core/v4l2-common.c
> +++ b/drivers/media/v4l2-core/v4l2-common.c
> @@ -701,6 +701,50 @@ int v4l2_link_freq_to_bitmap(struct device *dev, const u64 *fw_link_freqs,
>  }
>  EXPORT_SYMBOL_GPL(v4l2_link_freq_to_bitmap);
>  
> +int media_bus_fmt_to_csi2_dt(int bus_fmt)
> +{
> +	switch (bus_fmt) {
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +		return MIPI_CSI2_DT_YUV422_8B;
> +	case MEDIA_BUS_FMT_RGB565_1X16:
> +		return MIPI_CSI2_DT_RGB565;
> +	case MEDIA_BUS_FMT_BGR888_1X24:
> +		return MIPI_CSI2_DT_RGB888;
> +	case MEDIA_BUS_FMT_SBGGR8_1X8:
> +	case MEDIA_BUS_FMT_SGBRG8_1X8:
> +	case MEDIA_BUS_FMT_SGRBG8_1X8:
> +	case MEDIA_BUS_FMT_SRGGB8_1X8:
> +	case MEDIA_BUS_FMT_Y8_1X8:
> +		return MIPI_CSI2_DT_RAW8;
> +	case MEDIA_BUS_FMT_SBGGR10_1X10:
> +	case MEDIA_BUS_FMT_SGBRG10_1X10:
> +	case MEDIA_BUS_FMT_SGRBG10_1X10:
> +	case MEDIA_BUS_FMT_SRGGB10_1X10:
> +	case MEDIA_BUS_FMT_Y10_1X10:
> +		return MIPI_CSI2_DT_RAW10;
> +	case MEDIA_BUS_FMT_SBGGR12_1X12:
> +	case MEDIA_BUS_FMT_SGBRG12_1X12:
> +	case MEDIA_BUS_FMT_SGRBG12_1X12:
> +	case MEDIA_BUS_FMT_SRGGB12_1X12:
> +	case MEDIA_BUS_FMT_Y12_1X12:
> +		return MIPI_CSI2_DT_RAW12;
> +	case MEDIA_BUS_FMT_SBGGR14_1X14:
> +	case MEDIA_BUS_FMT_SGBRG14_1X14:
> +	case MEDIA_BUS_FMT_SGRBG14_1X14:
> +	case MEDIA_BUS_FMT_SRGGB14_1X14:
> +		return MIPI_CSI2_DT_RAW14;
> +	case MEDIA_BUS_FMT_SBGGR16_1X16:
> +	case MEDIA_BUS_FMT_SGBRG16_1X16:
> +	case MEDIA_BUS_FMT_SGRBG16_1X16:
> +	case MEDIA_BUS_FMT_SRGGB16_1X16:
> +		return MIPI_CSI2_DT_RAW16;
> +
> +	default:
> +		return MIPI_CSI2_DT_NULL;

I would use 0 here. MIPI_CSI2_DT_NULL is equal to 0x10, and I'm
concerned about driver comparing the return value of the function to 0.

> +	}
> +}
> +EXPORT_SYMBOL_GPL(media_bus_fmt_to_csi2_dt);
> +

We have something similar for pixel formats, with the v4l2_format_info
structure and the v4l2_format_info() lookup function. Adding information
about media bus formats to the V4L2 core seems to be a good idea.

Regarding the implementation, I think you should mimick what we do for
the pixel formats, and add the data to an info structure with a lookup
function.

>  int media_bus_fmt_to_csi2_bpp(int bus_fmt)
>  {
>  	switch (bus_fmt) {
> diff --git a/include/media/mipi-csi2.h b/include/media/mipi-csi2.h
> index c5b4e8e1ca93803568b1eee85f7f99c3a45a0b6e..35de536b9b65b49ad9e2914437d26d0e4240cf38 100644
> --- a/include/media/mipi-csi2.h
> +++ b/include/media/mipi-csi2.h
> @@ -8,6 +8,8 @@
>  #ifndef _MEDIA_MIPI_CSI2_H
>  #define _MEDIA_MIPI_CSI2_H
>  
> +/* DT value ref to MIPI Camera Serial Interface 2 Spec Ver4.1 section 9.4 */
> +
>  /* Short packet data types */
>  #define MIPI_CSI2_DT_FS			0x00
>  #define MIPI_CSI2_DT_FE			0x01
> @@ -44,6 +46,7 @@
>  #define MIPI_CSI2_DT_RAW20		0x2f
>  #define MIPI_CSI2_DT_USER_DEFINED(n)	(0x30 + (n))	/* 0..7 */
>  
> +int media_bus_fmt_to_csi2_dt(int buf_fmt);
>  int media_bus_fmt_to_csi2_bpp(int bus_fmt);
>  
>  #endif /* _MEDIA_MIPI_CSI2_H */
> 
> 

-- 
Regards,

Laurent Pinchart

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

end of thread, other threads:[~2025-08-20 19:17 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-08 22:39 [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li
2025-08-08 22:39 ` [PATCH v2 01/32] dt-bindings: media: add DW MIPI CSI-2 Host support Frank Li
2025-08-18 14:39   ` Rob Herring
2025-08-08 22:39 ` [PATCH v2 02/32] media: v4l2-common: Add helper function v4l_get_required_align_by_bpp() Frank Li
2025-08-08 22:39 ` [PATCH v2 03/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_bpp() Frank Li
2025-08-08 22:39 ` [PATCH v2 04/32] media: v4l2-common: Add helper function media_bus_fmt_to_csi2_dt() Frank Li
2025-08-20 19:16   ` Laurent Pinchart
2025-08-08 22:39 ` [PATCH v2 05/32] media: staging: media: imx6-mipi-csi2: replace space with tab for alignment Frank Li
2025-08-08 22:39 ` [PATCH v2 06/32] media: staging: media: imx6-mipi-csi2: use devm_add_action_or_reset() to simplify code Frank Li
2025-08-08 22:39 ` [PATCH v2 07/32] media: staging: media: imx6-mipi-csi2: use devm_clk_bulk_get_all() to fetch clocks Frank Li
2025-08-08 22:39 ` [PATCH v2 08/32] media: staging: media: imx6-mipi-csi2: use devm_mutex_init() to simplify code Frank Li
2025-08-08 22:39 ` [PATCH v2 09/32] media: staging: media: imx6-mipi-csi2: use guard() " Frank Li
2025-08-08 22:39 ` [PATCH v2 10/32] media: staging: media: imx6-mipi-csi2: use register structure to match hardware Frank Li
2025-08-08 22:39 ` [PATCH v2 11/32] media: staging: media: imx6-mipi-csi2: use devm_platform_ioremap_resource() simplify code Frank Li
2025-08-08 22:39 ` [PATCH v2 12/32] media: staging: media: imx6-mipi-csi2: move probe part to imx6-csi2.c Frank Li
2025-08-08 22:39 ` [PATCH v2 13/32] media: staging: media: imx6-mipi-csi2: move sd imx6's specific initialization into imx6-sci2.c Frank Li
2025-08-08 22:39 ` [PATCH v2 14/32] media: staging: media: imx6-mipi-csi2: move csi2ipu_gasket_init() to imx6-csi2.c Frank Li
2025-08-08 22:39 ` [PATCH v2 15/32] media: staging: media: imx6-mipi-csi2: move number pad macro define into imx6-csi2.c Frank Li
2025-08-08 22:39 ` [PATCH v2 16/32] media: staging: media: imx6-mipi-csi2: move dphy init part to imx6-csi2.c Frank Li
2025-08-08 22:39 ` [PATCH v2 17/32] media: staging: media: imx6-mipi-csi2: use runtime_pm frame to control clks Frank Li
2025-08-08 22:39 ` [PATCH v2 18/32] media: synopsys: move imx6-mipi-csi2.c to synopsys/mipi-csi2.c Frank Li
2025-08-08 22:39 ` [PATCH v2 19/32] media: synopsys: csi2: Remove deprecated s_stream and use v4l2_subdev_pad_ops Frank Li
2025-08-08 22:39 ` [PATCH v2 20/32] media: synopsys: csi2: Add phy interface support Frank Li
2025-08-08 22:39 ` [PATCH v2 21/32] media: synopsys: csi2: Add basic v150* version register Frank Li
2025-08-08 22:39 ` [PATCH v2 22/32] media: synopsys: csi2: Add irq support to record error count Frank Li
2025-08-08 22:39 ` [PATCH v2 23/32] media: synopsys: csi2: Handle alignment requirement for width Frank Li
2025-08-08 22:39 ` [PATCH v2 24/32] media: synopsys: csi2: Add register prefix to register field definitions Frank Li
2025-08-08 22:39 ` [PATCH v2 25/32] media: synopsys: csi2: Add need_dphy_reset in config Frank Li
2025-08-08 22:39 ` [PATCH v2 26/32] media: synopsys: csi2: Add default simple dw_csi2_subdev_init_state Frank Li
2025-08-08 22:39 ` [PATCH v2 27/32] media: synopsys: csi2: Add v150 lane stop state register bit define Frank Li
2025-08-08 22:39 ` [PATCH v2 28/32] media: synopsys: csi2: use standard v4l2_subdev_get_fmt() function Frank Li
2025-08-08 22:39 ` [PATCH v2 29/32] media: synopsys: csi2: Add customize get_frame_desc() callback Frank Li
2025-08-08 22:39 ` [PATCH v2 30/32] media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150 Frank Li
2025-08-08 22:39 ` [PATCH v2 31/32] media: synopsys: csi2: Remove source pad connected check at dw_csi2_enable_streams() Frank Li
2025-08-08 22:39 ` [PATCH v2 32/32] media: synopsys: csi2: Add simple synopsys platform driver Frank Li
2025-08-20 14:39 ` [PATCH v2 00/32] media: add imx93 mipi/controller csi support Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).