* [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25
@ 2024-10-08 11:18 Alain Volmat
2024-10-08 11:18 ` [PATCH 01/15] media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value Alain Volmat
` (15 more replies)
0 siblings, 16 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat, stable
This series introduces the camera pipeline support for the
STM32MP25 SOC. The STM32MP25 has 3 pipelines, fed from a
single camera input which can be either parallel or csi.
This series adds the basic support for the 1st pipe (dump)
which, in term of features is same as the one featured on
the STM32MP13 SOC. It focuses on introduction of the
CSI input stage for the DCMIPP, and the CSI specific new
control code for the DCMIPP.
One of the subdev of the DCMIPP, dcmipp_parallel is now
renamed as dcmipp_input since it allows to not only control
the parallel but also the csi interface.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
Alain Volmat (15):
media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value
dt-bindings: media: addition of stm32 csi driver description
media: stm32: csi: addition of the STM32 CSI driver
media: stm32: dcmipp: use v4l2_subdev_is_streaming
media: stm32: dcmipp: replace s_stream with enable/disable_streams
media: stm32: dcmipp: rename dcmipp_parallel into dcmipp_input
media: stm32: dcmipp: add support for csi input into dcmipp-input
media: stm32: dcmipp: add bayer 10~14 bits formats
media: stm32: dcmipp: add 1X16 RGB / YUV formats support
media: stm32: dcmipp: avoid duplicated format on enum in bytecap
media: stm32: dcmipp: fill media ctl hw_revision field
dt-bindings: media: addition of stm32mp25 compatible of DCMIPP
media: stm32: dcmipp: add core support for the stm32mp25
arm64: dts: st: add csi & dcmipp node in stm32mp25
arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1
.../devicetree/bindings/media/st,stm32-csi.yaml | 129 +++
.../devicetree/bindings/media/st,stm32-dcmipp.yaml | 53 +-
MAINTAINERS | 8 +
arch/arm64/boot/dts/st/stm32mp251.dtsi | 23 +
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 87 ++
drivers/media/platform/st/stm32/Kconfig | 14 +
drivers/media/platform/st/stm32/Makefile | 1 +
drivers/media/platform/st/stm32/stm32-csi.c | 1150 ++++++++++++++++++++
.../media/platform/st/stm32/stm32-dcmipp/Makefile | 2 +-
.../st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 128 ++-
.../st/stm32/stm32-dcmipp/dcmipp-byteproc.c | 119 +-
.../platform/st/stm32/stm32-dcmipp/dcmipp-common.h | 4 +-
.../platform/st/stm32/stm32-dcmipp/dcmipp-core.c | 116 +-
.../platform/st/stm32/stm32-dcmipp/dcmipp-input.c | 540 +++++++++
.../st/stm32/stm32-dcmipp/dcmipp-parallel.c | 440 --------
15 files changed, 2238 insertions(+), 576 deletions(-)
---
base-commit: 9852d85ec9d492ebef56dc5f229416c925758edc
change-id: 20241007-csi_dcmipp_mp25-7779601f57da
Best regards,
--
Alain Volmat <alain.volmat@foss.st.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 01/15] media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description Alain Volmat
` (14 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat, stable
Correct the call to dma_set_mask_and_coherent which should be set
to DMA_BIT_MASK(32).
Fixes: 28e0f3772296 ("media: stm32-dcmipp: STM32 DCMIPP camera interface driver")
Cc: stable@vger.kernel.org
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
index 9f768f011fa2..0f6918f4db38 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
@@ -893,7 +893,7 @@ struct dcmipp_ent_device *dcmipp_bytecap_ent_init(struct device *dev,
q->dev = dev;
/* DCMIPP requires 16 bytes aligned buffers */
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32) & ~0x0f);
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(dev, "Failed to set DMA mask\n");
goto err_mutex_destroy;
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
2024-10-08 11:18 ` [PATCH 01/15] media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 12:36 ` Rob Herring (Arm)
2024-10-08 13:23 ` Krzysztof Kozlowski
2024-10-08 11:18 ` [PATCH 03/15] media: stm32: csi: addition of the STM32 CSI driver Alain Volmat
` (13 subsequent siblings)
15 siblings, 2 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Addition of the stm32 csi controller driver
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../devicetree/bindings/media/st,stm32-csi.yaml | 129 +++++++++++++++++++++
1 file changed, 129 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/st,stm32-csi.yaml b/Documentation/devicetree/bindings/media/st,stm32-csi.yaml
new file mode 100644
index 000000000000..71e7c51be58c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/st,stm32-csi.yaml
@@ -0,0 +1,129 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics STM32 CSI controller
+
+description:
+ The STM32 CSI controller allows connecting a CSI based
+ camera to the DCMIPP camera pipeline.
+
+maintainers:
+ - Alain Volmat <alain.volmat@foss.st.com>
+
+properties:
+ compatible:
+ enum:
+ - st,stm32mp25-csi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: pclk
+ - const: txesc
+ - const: csi2phy
+
+ resets:
+ maxItems: 1
+
+ vdd-supply:
+ description: Digital core power supply (0.91V)
+
+ vdda18-supply:
+ description: System analog power supply (1.8V)
+
+ access-controllers:
+ minItems: 1
+ maxItems: 2
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port node
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description:
+ Indicate the number of data-lanes and their mapping.
+
+ items:
+ minItems: 1
+ items:
+ - const: 1
+ - const: 2
+
+ required:
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Output port node
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/st,stm32mp25-rcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/media/video-interfaces.h>
+ #include <dt-bindings/reset/st,stm32mp25-rcc.h>
+ csi@48020000 {
+ compatible = "st,stm32mp25-csi";
+ reg = <0x48020000 0x2000>;
+ interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&rcc CSI_R>;
+ clocks = <&rcc CK_KER_CSI>, <&rcc CK_KER_CSITXESC>, <&rcc CK_KER_CSIPHY>;
+ clock-names = "pclk", "txesc", "csi2phy";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&imx335_ep>;
+ data-lanes = <0 1>;
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&dcmipp_0>;
+ };
+ };
+ };
+ };
+
+...
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 03/15] media: stm32: csi: addition of the STM32 CSI driver
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
2024-10-08 11:18 ` [PATCH 01/15] media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value Alain Volmat
2024-10-08 11:18 ` [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 04/15] media: stm32: dcmipp: use v4l2_subdev_is_streaming Alain Volmat
` (12 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
The STM32 CSI controller is tightly coupled with the DCMIPP and act as an
input stage to receive data coming from the sensor and transferring
them into the DCMIPP.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
MAINTAINERS | 8 +
drivers/media/platform/st/stm32/Kconfig | 14 +
drivers/media/platform/st/stm32/Makefile | 1 +
drivers/media/platform/st/stm32/stm32-csi.c | 1150 +++++++++++++++++++++++++++
4 files changed, 1173 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index c27f3190737f..9bdc3aa4bcf5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14376,6 +14376,14 @@ W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
F: drivers/media/dvb-frontends/stv6111*
+MEDIA DRIVERS FOR STM32 - CSI
+M: Alain Volmat <alain.volmat@foss.st.com>
+L: linux-media@vger.kernel.org
+S: Supported
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/st,stm32-csi.yaml
+F: drivers/media/platform/stm32/stm32-csi.c
+
MEDIA DRIVERS FOR STM32 - DCMI / DCMIPP
M: Hugues Fruchet <hugues.fruchet@foss.st.com>
M: Alain Volmat <alain.volmat@foss.st.com>
diff --git a/drivers/media/platform/st/stm32/Kconfig b/drivers/media/platform/st/stm32/Kconfig
index 9df9a2a17728..f12e67bcc9bc 100644
--- a/drivers/media/platform/st/stm32/Kconfig
+++ b/drivers/media/platform/st/stm32/Kconfig
@@ -1,6 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-only
# V4L drivers
+config VIDEO_STM32_CSI
+ tristate "STM32 Camera Serial Interface (CSI) support"
+ depends on V4L_PLATFORM_DRIVERS
+ depends on VIDEO_DEV && OF
+ depends on ARCH_STM32 || COMPILE_TEST
+ select MEDIA_CONTROLLER
+ select V4L2_FWNODE
+ help
+ This module makes the STM32 Camera Serial Interface (CSI)
+ available as a v4l2 device.
+
+ To compile this driver as a module, choose M here: the module
+ will be called stm32-csi.
+
config VIDEO_STM32_DCMI
tristate "STM32 Digital Camera Memory Interface (DCMI) support"
depends on V4L_PLATFORM_DRIVERS
diff --git a/drivers/media/platform/st/stm32/Makefile b/drivers/media/platform/st/stm32/Makefile
index 7ed8297b9b19..9ae57897f030 100644
--- a/drivers/media/platform/st/stm32/Makefile
+++ b/drivers/media/platform/st/stm32/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_VIDEO_STM32_CSI) += stm32-csi.o
obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32-dcmi.o
obj-$(CONFIG_VIDEO_STM32_DCMIPP) += stm32-dcmipp/
stm32-dma2d-objs := dma2d/dma2d.o dma2d/dma2d-hw.o
diff --git a/drivers/media/platform/st/stm32/stm32-csi.c b/drivers/media/platform/st/stm32/stm32-csi.c
new file mode 100644
index 000000000000..51c4dc114f4a
--- /dev/null
+++ b/drivers/media/platform/st/stm32/stm32-csi.c
@@ -0,0 +1,1150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for STM32 Camera Serial Interface
+ *
+ * Copyright (C) STMicroelectronics SA 2024
+ * Author: Alain Volmat <alain.volmat@foss.st.com>
+ * for STMicroelectronics.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define STM32_CSI_CR 0x0000
+#define STM32_CSI_CR_CSIEN BIT(0)
+#define STM32_CSI_CR_VCXSTART(x) BIT(2 + ((x) * 4))
+#define STM32_CSI_CR_VCXSTOP(x) BIT(3 + ((x) * 4))
+#define STM32_CSI_PCR 0x0004
+#define STM32_CSI_PCR_DL1EN BIT(3)
+#define STM32_CSI_PCR_DL0EN BIT(2)
+#define STM32_CSI_PCR_CLEN BIT(1)
+#define STM32_CSI_PCR_PWRDOWN BIT(0)
+#define STM32_CSI_VCXCFGR1(x) ((((x) + 1) * 0x0010) + 0x0)
+#define STM32_CSI_VCXCFGR1_ALLDT BIT(0)
+#define STM32_CSI_VCXCFGR1_DT0EN BIT(1)
+#define STM32_CSI_VCXCFGR1_DT1EN BIT(2)
+#define STM32_CSI_VCXCFGR1_CDTFT_SHIFT 8
+#define STM32_CSI_VCXCFGR1_DT0_SHIFT 16
+#define STM32_CSI_VCXCFGR1_DT0FT_SHIFT 24
+#define STM32_CSI_VCXCFGR2(x) ((((x) + 1) * 0x0010) + 0x4)
+#define STM32_CSI_VCXCFGR2_DT1_SHIFT 0
+#define STM32_CSI_VCXCFGR2_DT1FT_SHIFT 8
+#define STM32_CSI_INPUT_BPP8 2
+#define STM32_CSI_INPUT_BPP10 3
+#define STM32_CSI_INPUT_BPP12 4
+#define STM32_CSI_INPUT_BPP14 5
+#define STM32_CSI_LMCFGR 0x0070
+#define STM32_CSI_LMCFGR_LANENB_SHIFT 8
+#define STM32_CSI_LMCFGR_DLMAP_SHIFT 16
+#define STM32_CSI_IER0 0x0080
+#define STM32_CSI_IER1 0x0084
+#define STM32_CSI_SR0 0x0090
+#define STM32_CSI_SR0_SYNCERRF BIT(30)
+#define STM32_CSI_SR0_SPKTERRF BIT(28)
+#define STM32_CSI_SR0_IDERRF BIT(27)
+#define STM32_CSI_SR0_CECCERRF BIT(26)
+#define STM32_CSI_SR0_ECCERRF BIT(25)
+#define STM32_CSI_SR0_CRCERRF BIT(24)
+#define STM32_CSI_SR0_CCFIFOFF BIT(21)
+#define STM32_CSI_SR0_VCXSTATEF(x) BIT(17 + (x))
+#define STM32_CSI_SR1 0x0094
+#define STM32_CSI_SR1_ECTRLDL1F BIT(12)
+#define STM32_CSI_SR1_ESYNCESCDL1F BIT(11)
+#define STM32_CSI_SR1_EESCDL1F BIT(10)
+#define STM32_CSI_SR1_ESOTSYNCDL1F BIT(9)
+#define STM32_CSI_SR1_ESOTDL1F BIT(8)
+#define STM32_CSI_SR1_ECTRLDL0F BIT(4)
+#define STM32_CSI_SR1_ESYNCESCDL0F BIT(3)
+#define STM32_CSI_SR1_EESCDL0F BIT(2)
+#define STM32_CSI_SR1_ESOTSYNCDL0F BIT(1)
+#define STM32_CSI_SR1_ESOTDL0F BIT(0)
+#define STM32_CSI_FCR0 0x0100
+#define STM32_CSI_FCR1 0x0104
+#define STM32_CSI_SPDFR 0x0110
+#define STM32_CSI_DT_MASK 0x3f
+#define STM32_CSI_VC_MASK 0x03
+#define STM32_CSI_ERR1 0x0114
+#define STM32_CSI_ERR1_IDVCERR_SHIFT 22
+#define STM32_CSI_ERR1_IDDTERR_SHIFT 16
+#define STM32_CSI_ERR1_CECCVCERR_SHIFT 14
+#define STM32_CSI_ERR1_CECCDTERR_SHIFT 8
+#define STM32_CSI_ERR1_CRCVCERR_SHIFT 6
+#define STM32_CSI_ERR1_CRCDTERR_SHIFT 0
+#define STM32_CSI_ERR2 0x0118
+#define STM32_CSI_ERR2_SYNCVCERR_SHIFT 18
+#define STM32_CSI_ERR2_SPKTVCERR_SHIFT 6
+#define STM32_CSI_ERR2_SPKTDTERR_SHIFT 0
+#define STM32_CSI_PRCR 0x1000
+#define STM32_CSI_PRCR_PEN BIT(1)
+#define STM32_CSI_PMCR 0x1004
+#define STM32_CSI_PFCR 0x1008
+#define STM32_CSI_PFCR_CCFR_MASK GENMASK(5, 0)
+#define STM32_CSI_PFCR_CCFR_SHIFT 0
+#define STM32_CSI_PFCR_HSFR_MASK GENMASK(14, 8)
+#define STM32_CSI_PFCR_HSFR_SHIFT 8
+#define STM32_CSI_PFCR_DLD BIT(16)
+#define STM32_CSI_PTCR0 0x1010
+#define STM32_CSI_PTCR0_TCKEN BIT(0)
+#define STM32_CSI_PTCR1 0x1014
+#define STM32_CSI_PTCR1_TWM BIT(16)
+#define STM32_CSI_PTCR1_TDI_MASK GENMASK(7, 0)
+#define STM32_CSI_PTCR1_TDI_SHIFT 0
+#define STM32_CSI_PTSR 0x1018
+
+#define STM32_CSI_LANES_MAX 2
+
+#define STM32_CSI_SR0_ERRORS (STM32_CSI_SR0_SYNCERRF | STM32_CSI_SR0_SPKTERRF |\
+ STM32_CSI_SR0_IDERRF | STM32_CSI_SR0_CECCERRF |\
+ STM32_CSI_SR0_ECCERRF | STM32_CSI_SR0_CRCERRF |\
+ STM32_CSI_SR0_CCFIFOFF)
+#define STM32_CSI_SR1_DL0_ERRORS (STM32_CSI_SR1_ECTRLDL0F | STM32_CSI_SR1_ESYNCESCDL0F |\
+ STM32_CSI_SR1_EESCDL0F | STM32_CSI_SR1_ESOTSYNCDL0F |\
+ STM32_CSI_SR1_ESOTDL0F)
+#define STM32_CSI_SR1_DL1_ERRORS (STM32_CSI_SR1_ECTRLDL1F | STM32_CSI_SR1_ESYNCESCDL1F |\
+ STM32_CSI_SR1_EESCDL1F | STM32_CSI_SR1_ESOTSYNCDL1F |\
+ STM32_CSI_SR1_ESOTDL1F)
+#define STM32_CSI_SR1_ERRORS (STM32_CSI_SR1_DL0_ERRORS | STM32_CSI_SR1_DL1_ERRORS)
+
+enum stm32_csi_pads {
+ STM32_CSI_PAD_SINK,
+ STM32_CSI_PAD_SOURCE,
+ STM32_CSI_PAD_MAX,
+};
+
+struct stm32_csi_event {
+ u32 mask;
+ const char * const name;
+};
+
+static const struct stm32_csi_event stm32_csi_events_sr0[] = {
+ {STM32_CSI_SR0_SYNCERRF, "Synchronization error"},
+ {STM32_CSI_SR0_SPKTERRF, "Short packet error"},
+ {STM32_CSI_SR0_IDERRF, "Data type ID error"},
+ {STM32_CSI_SR0_CECCERRF, "Corrected ECC error"},
+ {STM32_CSI_SR0_ECCERRF, "ECC error"},
+ {STM32_CSI_SR0_CRCERRF, "CRC error"},
+ {STM32_CSI_SR0_CCFIFOFF, "Clk changer FIFO full error"},
+};
+
+#define STM32_CSI_NUM_SR0_EVENTS ARRAY_SIZE(stm32_csi_events_sr0)
+
+static const struct stm32_csi_event stm32_csi_events_sr1[] = {
+ {STM32_CSI_SR1_ECTRLDL1F, "L1: D-PHY control error"},
+ {STM32_CSI_SR1_ESYNCESCDL1F,
+ "L1: D-PHY low power data transmission synchro error"},
+ {STM32_CSI_SR1_EESCDL1F, "L1: D-PHY escape entry error"},
+ {STM32_CSI_SR1_ESOTSYNCDL1F,
+ "L1: Start of transmission synchro error"},
+ {STM32_CSI_SR1_ESOTDL1F, "L1: Start of transmission error"},
+ {STM32_CSI_SR1_ECTRLDL0F, "L0: D-PHY control error"},
+ {STM32_CSI_SR1_ESYNCESCDL0F,
+ "L0: D-PHY low power data transmission synchro error"},
+ {STM32_CSI_SR1_EESCDL0F, "L0: D-PHY escape entry error"},
+ {STM32_CSI_SR1_ESOTSYNCDL0F,
+ "L0: Start of transmission synchro error"},
+ {STM32_CSI_SR1_ESOTDL0F, "L0: Start of transmission error"},
+};
+
+#define STM32_CSI_NUM_SR1_EVENTS ARRAY_SIZE(stm32_csi_events_sr1)
+
+struct stm32_csi_dev {
+ struct device *dev;
+
+ void __iomem *base;
+ struct clk *pclk;
+ struct clk *txesc;
+ struct clk *csi2phy;
+ struct regulator_bulk_data supplies[2];
+ struct reset_control *rstc;
+
+ u8 lanes[STM32_CSI_LANES_MAX];
+ u8 num_lanes;
+
+ /*
+ * spinlock slock is used to protect to srX_counters tables being
+ * accessed from log_status and interrupt context
+ */
+ spinlock_t slock;
+
+ u32 sr0_counters[STM32_CSI_NUM_SR0_EVENTS];
+ u32 sr1_counters[STM32_CSI_NUM_SR1_EVENTS];
+
+ struct v4l2_subdev sd;
+ struct v4l2_async_notifier notifier;
+ struct media_pad pads[STM32_CSI_PAD_MAX];
+
+ /* Remote source */
+ struct v4l2_subdev *s_subdev;
+ u32 s_subdev_pad_nb;
+};
+
+struct stm32_csi_fmts {
+ u32 code;
+ u32 datatype;
+ u32 input_fmt;
+ u8 bpp;
+};
+
+#define FMT_MBUS_DT_DTFMT_BPP(mbus, dt, input, byteperpixel) \
+ { \
+ .code = MEDIA_BUS_FMT_##mbus, \
+ .datatype = MIPI_CSI2_DT_##dt, \
+ .input_fmt = STM32_CSI_INPUT_##input, \
+ .bpp = byteperpixel, \
+ }
+static const struct stm32_csi_fmts stm32_csi_formats[] = {
+ /* YUV 422 8 bit */
+ FMT_MBUS_DT_DTFMT_BPP(UYVY8_1X16, YUV422_8B, BPP8, 8),
+ FMT_MBUS_DT_DTFMT_BPP(YUYV8_1X16, YUV422_8B, BPP8, 8),
+ FMT_MBUS_DT_DTFMT_BPP(YVYU8_1X16, YUV422_8B, BPP8, 8),
+ FMT_MBUS_DT_DTFMT_BPP(VYUY8_1X16, YUV422_8B, BPP8, 8),
+
+ /* Raw Bayer */
+ /* 8 bit */
+ FMT_MBUS_DT_DTFMT_BPP(SBGGR8_1X8, RAW8, BPP8, 8),
+ FMT_MBUS_DT_DTFMT_BPP(SGBRG8_1X8, RAW8, BPP8, 8),
+ FMT_MBUS_DT_DTFMT_BPP(SGRBG8_1X8, RAW8, BPP8, 8),
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB8_1X8, RAW8, BPP8, 8),
+ /* 10 bit */
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB10_1X10, RAW10, BPP10, 10),
+ FMT_MBUS_DT_DTFMT_BPP(SGBRG10_1X10, RAW10, BPP10, 10),
+ FMT_MBUS_DT_DTFMT_BPP(SGRBG10_1X10, RAW10, BPP10, 10),
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB10_1X10, RAW10, BPP10, 10),
+ /* 12 bit */
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB12_1X12, RAW12, BPP12, 12),
+ FMT_MBUS_DT_DTFMT_BPP(SGBRG12_1X12, RAW12, BPP12, 12),
+ FMT_MBUS_DT_DTFMT_BPP(SGRBG12_1X12, RAW12, BPP12, 12),
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB12_1X12, RAW12, BPP12, 12),
+ /* 14 bit */
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB14_1X14, RAW14, BPP14, 14),
+ FMT_MBUS_DT_DTFMT_BPP(SGBRG14_1X14, RAW14, BPP14, 14),
+ FMT_MBUS_DT_DTFMT_BPP(SGRBG14_1X14, RAW14, BPP14, 14),
+ FMT_MBUS_DT_DTFMT_BPP(SRGGB14_1X14, RAW14, BPP14, 14),
+
+ /* RGB 565 */
+ FMT_MBUS_DT_DTFMT_BPP(RGB565_1X16, RGB565, BPP8, 8),
+
+ /* JPEG (datatype isn't used) */
+ FMT_MBUS_DT_DTFMT_BPP(JPEG_1X8, NULL, BPP8, 8),
+};
+
+struct stm32_csi_mbps_phy_reg {
+ unsigned int mbps;
+ unsigned int hsfreqrange;
+ unsigned int osc_freq_target;
+};
+
+/*
+ * Table describing configuration of the PHY depending on the
+ * intended Bit Rate. From table 5-8 Frequency Ranges and Defaults
+ * of the Synopsis DWC MIPI PHY databook
+ */
+static const struct stm32_csi_mbps_phy_reg snps_stm32mp25[] = {
+ { .mbps = 80, .hsfreqrange = 0x00, .osc_freq_target = 460 },
+ { .mbps = 90, .hsfreqrange = 0x10, .osc_freq_target = 460 },
+ { .mbps = 100, .hsfreqrange = 0x20, .osc_freq_target = 460 },
+ { .mbps = 110, .hsfreqrange = 0x30, .osc_freq_target = 460 },
+ { .mbps = 120, .hsfreqrange = 0x01, .osc_freq_target = 460 },
+ { .mbps = 130, .hsfreqrange = 0x11, .osc_freq_target = 460 },
+ { .mbps = 140, .hsfreqrange = 0x21, .osc_freq_target = 460 },
+ { .mbps = 150, .hsfreqrange = 0x31, .osc_freq_target = 460 },
+ { .mbps = 160, .hsfreqrange = 0x02, .osc_freq_target = 460 },
+ { .mbps = 170, .hsfreqrange = 0x12, .osc_freq_target = 460 },
+ { .mbps = 180, .hsfreqrange = 0x22, .osc_freq_target = 460 },
+ { .mbps = 190, .hsfreqrange = 0x32, .osc_freq_target = 460 },
+ { .mbps = 205, .hsfreqrange = 0x03, .osc_freq_target = 460 },
+ { .mbps = 220, .hsfreqrange = 0x13, .osc_freq_target = 460 },
+ { .mbps = 235, .hsfreqrange = 0x23, .osc_freq_target = 460 },
+ { .mbps = 250, .hsfreqrange = 0x33, .osc_freq_target = 460 },
+ { .mbps = 275, .hsfreqrange = 0x04, .osc_freq_target = 460 },
+ { .mbps = 300, .hsfreqrange = 0x14, .osc_freq_target = 460 },
+ { .mbps = 325, .hsfreqrange = 0x25, .osc_freq_target = 460 },
+ { .mbps = 350, .hsfreqrange = 0x35, .osc_freq_target = 460 },
+ { .mbps = 400, .hsfreqrange = 0x05, .osc_freq_target = 460 },
+ { .mbps = 450, .hsfreqrange = 0x16, .osc_freq_target = 460 },
+ { .mbps = 500, .hsfreqrange = 0x26, .osc_freq_target = 460 },
+ { .mbps = 550, .hsfreqrange = 0x37, .osc_freq_target = 460 },
+ { .mbps = 600, .hsfreqrange = 0x07, .osc_freq_target = 460 },
+ { .mbps = 650, .hsfreqrange = 0x18, .osc_freq_target = 460 },
+ { .mbps = 700, .hsfreqrange = 0x28, .osc_freq_target = 460 },
+ { .mbps = 750, .hsfreqrange = 0x39, .osc_freq_target = 460 },
+ { .mbps = 800, .hsfreqrange = 0x09, .osc_freq_target = 460 },
+ { .mbps = 850, .hsfreqrange = 0x19, .osc_freq_target = 460 },
+ { .mbps = 900, .hsfreqrange = 0x29, .osc_freq_target = 460 },
+ { .mbps = 950, .hsfreqrange = 0x3a, .osc_freq_target = 460 },
+ { .mbps = 1000, .hsfreqrange = 0x0a, .osc_freq_target = 460 },
+ { .mbps = 1050, .hsfreqrange = 0x1a, .osc_freq_target = 460 },
+ { .mbps = 1100, .hsfreqrange = 0x2a, .osc_freq_target = 460 },
+ { .mbps = 1150, .hsfreqrange = 0x3b, .osc_freq_target = 460 },
+ { .mbps = 1200, .hsfreqrange = 0x0b, .osc_freq_target = 460 },
+ { .mbps = 1250, .hsfreqrange = 0x1b, .osc_freq_target = 460 },
+ { .mbps = 1300, .hsfreqrange = 0x2b, .osc_freq_target = 460 },
+ { .mbps = 1350, .hsfreqrange = 0x3c, .osc_freq_target = 460 },
+ { .mbps = 1400, .hsfreqrange = 0x0c, .osc_freq_target = 460 },
+ { .mbps = 1450, .hsfreqrange = 0x1c, .osc_freq_target = 460 },
+ { .mbps = 1500, .hsfreqrange = 0x2c, .osc_freq_target = 460 },
+ { .mbps = 1550, .hsfreqrange = 0x3d, .osc_freq_target = 285 },
+ { .mbps = 1600, .hsfreqrange = 0x0d, .osc_freq_target = 295 },
+ { .mbps = 1650, .hsfreqrange = 0x1d, .osc_freq_target = 304 },
+ { .mbps = 1700, .hsfreqrange = 0x2e, .osc_freq_target = 313 },
+ { .mbps = 1750, .hsfreqrange = 0x3e, .osc_freq_target = 322 },
+ { .mbps = 1800, .hsfreqrange = 0x0e, .osc_freq_target = 331 },
+ { .mbps = 1850, .hsfreqrange = 0x1e, .osc_freq_target = 341 },
+ { .mbps = 1900, .hsfreqrange = 0x2f, .osc_freq_target = 350 },
+ { .mbps = 1950, .hsfreqrange = 0x3f, .osc_freq_target = 359 },
+ { .mbps = 2000, .hsfreqrange = 0x0f, .osc_freq_target = 368 },
+ { .mbps = 2050, .hsfreqrange = 0x40, .osc_freq_target = 377 },
+ { .mbps = 2100, .hsfreqrange = 0x41, .osc_freq_target = 387 },
+ { .mbps = 2150, .hsfreqrange = 0x42, .osc_freq_target = 396 },
+ { .mbps = 2200, .hsfreqrange = 0x43, .osc_freq_target = 405 },
+ { .mbps = 2250, .hsfreqrange = 0x44, .osc_freq_target = 414 },
+ { .mbps = 2300, .hsfreqrange = 0x45, .osc_freq_target = 423 },
+ { .mbps = 2350, .hsfreqrange = 0x46, .osc_freq_target = 432 },
+ { .mbps = 2400, .hsfreqrange = 0x47, .osc_freq_target = 442 },
+ { .mbps = 2450, .hsfreqrange = 0x48, .osc_freq_target = 451 },
+ { .mbps = 2500, .hsfreqrange = 0x49, .osc_freq_target = 460 },
+ { /* sentinel */ }
+};
+
+static const struct v4l2_mbus_framefmt fmt_default = {
+ .width = 640,
+ .height = 480,
+ .code = MEDIA_BUS_FMT_RGB565_1X16,
+ .field = V4L2_FIELD_NONE,
+ .colorspace = V4L2_COLORSPACE_REC709,
+ .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
+ .quantization = V4L2_QUANTIZATION_DEFAULT,
+ .xfer_func = V4L2_XFER_FUNC_DEFAULT,
+};
+
+static const struct stm32_csi_fmts *stm32_csi_code_to_fmt(unsigned int code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(stm32_csi_formats); i++)
+ if (stm32_csi_formats[i].code == code)
+ return &stm32_csi_formats[i];
+
+ return NULL;
+}
+
+static inline struct stm32_csi_dev *to_csidev(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct stm32_csi_dev, sd);
+}
+
+static int stm32_csi_setup_lane_merger(struct stm32_csi_dev *csidev)
+{
+ u32 lmcfgr = 0;
+ int i;
+
+ for (i = 0; i < csidev->num_lanes; i++) {
+ /* Check that lane ID is < max number of lane */
+ if (csidev->lanes[i] >= STM32_CSI_LANES_MAX) {
+ dev_err(csidev->dev, "Invalid lane id (%d)\n",
+ csidev->lanes[i]);
+ return -EINVAL;
+ }
+ lmcfgr |= ((csidev->lanes[i] + 1) << ((i * 4) +
+ STM32_CSI_LMCFGR_DLMAP_SHIFT));
+ }
+
+ lmcfgr |= (csidev->num_lanes << STM32_CSI_LMCFGR_LANENB_SHIFT);
+
+ writel_relaxed(lmcfgr, csidev->base + STM32_CSI_LMCFGR);
+
+ return 0;
+}
+
+static void stm32_csi_phy_reg_write(struct stm32_csi_dev *csidev,
+ u32 addr, u32 val)
+{
+ /* Based on sequence described at section 5.2.3.2 of DesignWave document */
+ /* For writing the 4-bit testcode MSBs */
+ /* Set testen to high */
+ writel_relaxed(STM32_CSI_PTCR1_TWM, csidev->base + STM32_CSI_PTCR1);
+
+ /* Set testclk to high */
+ writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0);
+
+ /* Place 0x00 in testdin */
+ writel_relaxed(STM32_CSI_PTCR1_TWM, csidev->base + STM32_CSI_PTCR1);
+
+ /*
+ * Set testclk to low (with the falling edge on testclk, the testdin
+ * signal content is latched internally)
+ */
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR0);
+
+ /* Set testen to low */
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR1);
+
+ /* Place the 8-bit word corresponding to the testcode MSBs in testdin */
+ writel_relaxed(((addr >> 8) & STM32_CSI_PTCR1_TDI_MASK) << STM32_CSI_PTCR1_TDI_SHIFT,
+ csidev->base + STM32_CSI_PTCR1);
+
+ /* Set testclk to high */
+ writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0);
+
+ /* For writing the 8-bit testcode LSBs */
+ /* Set testclk to low */
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR0);
+
+ /* Set testen to high */
+ writel_relaxed(STM32_CSI_PTCR1_TWM, csidev->base + STM32_CSI_PTCR1);
+
+ /* Set testclk to high */
+ writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0);
+
+ /* Place the 8-bit word test data in testdin */
+ writel_relaxed((addr & STM32_CSI_PTCR1_TDI_MASK) <<
+ STM32_CSI_PTCR1_TDI_SHIFT | STM32_CSI_PTCR1_TWM,
+ csidev->base + STM32_CSI_PTCR1);
+
+ /*
+ * Set testclk to low (with the falling edge on testclk, the testdin
+ * signal content is latched internally)
+ */
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR0);
+
+ /* Set testen to low */
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR1);
+
+ /* For writing the data */
+ /* Place the 8-bit word corresponding to the page offset in testdin */
+ writel_relaxed((val & STM32_CSI_PTCR1_TDI_MASK) << STM32_CSI_PTCR1_TDI_SHIFT,
+ csidev->base + STM32_CSI_PTCR1);
+
+ /* Set testclk to high (test data is programmed internally */
+ writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0);
+
+ /* Finish by setting testclk to low */
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR0);
+}
+
+static int stm32_csi_start(struct stm32_csi_dev *csidev,
+ struct v4l2_subdev_state *state)
+{
+ const struct stm32_csi_mbps_phy_reg *phy_regs;
+ struct v4l2_mbus_framefmt *sink_fmt;
+ const struct stm32_csi_fmts *fmt;
+ unsigned long phy_clk_frate;
+ unsigned int mbps;
+ u32 lanes_ie = 0;
+ u32 lanes_en = 0;
+ s64 link_freq;
+ int ret, i;
+ u32 ccfr;
+
+ dev_dbg(csidev->dev, "Starting the CSI2\n");
+
+ /* Get the bpp value on pad0 (input of CSI) */
+ sink_fmt = v4l2_subdev_state_get_format(state, STM32_CSI_PAD_SINK);
+ fmt = stm32_csi_code_to_fmt(sink_fmt->code);
+
+ /* Get the remote sensor link frequency */
+ if (!csidev->s_subdev)
+ return -EIO;
+
+ link_freq = v4l2_get_link_freq(csidev->s_subdev->ctrl_handler,
+ fmt->bpp, 2 * csidev->num_lanes);
+ if (link_freq < 0)
+ return link_freq;
+
+ /* MBPS is expressed in Mbps, hence link_freq / 100000 * 2 */
+ mbps = div_s64(link_freq, 500000);
+ dev_dbg(csidev->dev, "Computed Mbps: %u\n", mbps);
+
+ for (phy_regs = snps_stm32mp25; phy_regs->mbps != 0; phy_regs++)
+ if (phy_regs->mbps >= mbps)
+ break;
+
+ if (!phy_regs->mbps) {
+ dev_err(csidev->dev, "Unsupported PHY speed (%u Mbps)", mbps);
+ return -ERANGE;
+ }
+
+ dev_dbg(csidev->dev, "PHY settings: (%u Mbps, %u HS FRange, %u OSC Freq)\n",
+ phy_regs->mbps, phy_regs->hsfreqrange,
+ phy_regs->osc_freq_target);
+
+ /* Prepare lanes related configuration bits */
+ for (i = 0; i < csidev->num_lanes; i++) {
+ if (!csidev->lanes[i]) {
+ lanes_ie |= STM32_CSI_SR1_DL0_ERRORS;
+ lanes_en |= STM32_CSI_PCR_DL0EN;
+ } else {
+ lanes_ie |= STM32_CSI_SR1_DL1_ERRORS;
+ lanes_en |= STM32_CSI_PCR_DL1EN;
+ }
+ }
+
+ ret = pm_runtime_get_sync(csidev->dev);
+ if (ret < 0)
+ return ret;
+
+ /* Retrieve CSI2PHY clock rate to compute CCFR value */
+ phy_clk_frate = clk_get_rate(csidev->csi2phy);
+ if (!phy_clk_frate) {
+ pm_runtime_put(csidev->dev);
+ dev_err(csidev->dev, "CSI2PHY clock rate invalid (0)\n");
+ return ret;
+ }
+
+ ret = stm32_csi_setup_lane_merger(csidev);
+ if (ret) {
+ pm_runtime_put(csidev->dev);
+ return ret;
+ }
+
+ /* Enable the CSI */
+ writel_relaxed(STM32_CSI_CR_CSIEN, csidev->base + STM32_CSI_CR);
+
+ /* Enable some global CSI related interrupts - bits are same as SR0 */
+ writel_relaxed(STM32_CSI_SR0_ERRORS, csidev->base + STM32_CSI_IER0);
+
+ /* Enable lanes related error interrupts */
+ writel_relaxed(lanes_ie, csidev->base + STM32_CSI_IER1);
+
+ /* Initialization of the D-PHY */
+ /* Stop the D-PHY */
+ writel_relaxed(0, csidev->base + STM32_CSI_PRCR);
+
+ /* Keep the D-PHY in power down state */
+ writel_relaxed(0, csidev->base + STM32_CSI_PCR);
+
+ /* Enable testclr clock during 15ns */
+ writel_relaxed(STM32_CSI_PTCR0_TCKEN, csidev->base + STM32_CSI_PTCR0);
+ udelay(1);
+ writel_relaxed(0, csidev->base + STM32_CSI_PTCR0);
+
+ /* Set hsfreqrange */
+ phy_clk_frate /= 1000000;
+ ccfr = (phy_clk_frate - 17) * 4;
+ writel_relaxed((ccfr << STM32_CSI_PFCR_CCFR_SHIFT) |
+ (phy_regs->hsfreqrange << STM32_CSI_PFCR_HSFR_SHIFT),
+ csidev->base + STM32_CSI_PFCR);
+
+ /* set reg @08 deskew_polarity_rw 1'b1 */
+ stm32_csi_phy_reg_write(csidev, 0x08, 0x38);
+
+ /* set reg @0xE4 counter_for_des_en_config_if_rx 0x10 + DLL prog EN */
+ /* This is because 13<= cfgclkfreqrange[5:0]<=38 */
+ stm32_csi_phy_reg_write(csidev, 0xe4, 0x11);
+
+ /* set reg @0xe2 & reg @0xe3 value DLL target oscilation freq */
+ /* Based on the table page 77, osc_freq_target */
+ stm32_csi_phy_reg_write(csidev, 0xe2, phy_regs->osc_freq_target & 0xFF);
+ stm32_csi_phy_reg_write(csidev, 0xe3, (phy_regs->osc_freq_target >> 8) & 0x0F);
+
+ writel_relaxed(STM32_CSI_PFCR_DLD | readl_relaxed(csidev->base + STM32_CSI_PFCR),
+ csidev->base + STM32_CSI_PFCR);
+
+ /* Enable Lanes */
+ writel_relaxed(lanes_en | STM32_CSI_PCR_CLEN, csidev->base + STM32_CSI_PCR);
+ writel_relaxed(lanes_en | STM32_CSI_PCR_CLEN | STM32_CSI_PCR_PWRDOWN,
+ csidev->base + STM32_CSI_PCR);
+
+ writel_relaxed(STM32_CSI_PRCR_PEN, csidev->base + STM32_CSI_PRCR);
+
+ /* Remove the force */
+ writel_relaxed(0, csidev->base + STM32_CSI_PMCR);
+
+ return ret;
+}
+
+static void stm32_csi_stop(struct stm32_csi_dev *csidev)
+{
+ dev_dbg(csidev->dev, "Stopping the CSI2\n");
+
+ /* Disable the D-PHY */
+ writel_relaxed(0, csidev->base + STM32_CSI_PCR);
+
+ /* Disable ITs */
+ writel_relaxed(0, csidev->base + STM32_CSI_IER0);
+ writel_relaxed(0, csidev->base + STM32_CSI_IER1);
+
+ /* Disable the CSI */
+ writel_relaxed(0, csidev->base + STM32_CSI_CR);
+
+ pm_runtime_put(csidev->dev);
+}
+
+static int stm32_csi_start_vc(struct stm32_csi_dev *csidev,
+ struct v4l2_subdev_state *state, u32 vc)
+{
+ struct v4l2_mbus_framefmt *mbus_fmt;
+ const struct stm32_csi_fmts *fmt;
+ u32 cfgr1 = 0;
+ int ret = 0;
+ u32 status;
+
+ mbus_fmt = v4l2_subdev_state_get_format(state, STM32_CSI_PAD_SOURCE);
+ fmt = stm32_csi_code_to_fmt(mbus_fmt->code);
+
+ /* If the mbus code is JPEG, don't enable filtering */
+ if (mbus_fmt->code == MEDIA_BUS_FMT_JPEG_1X8) {
+ cfgr1 |= STM32_CSI_VCXCFGR1_ALLDT;
+ cfgr1 |= fmt->input_fmt << STM32_CSI_VCXCFGR1_CDTFT_SHIFT;
+ dev_dbg(csidev->dev, "VC%d: enable AllDT mode\n", vc);
+ } else {
+ cfgr1 |= fmt->datatype << STM32_CSI_VCXCFGR1_DT0_SHIFT;
+ cfgr1 |= fmt->input_fmt << STM32_CSI_VCXCFGR1_DT0FT_SHIFT;
+ cfgr1 |= STM32_CSI_VCXCFGR1_DT0EN;
+ dev_dbg(csidev->dev, "VC%d: enable DT0(0x%x)/DT0FT(0x%x)\n",
+ vc, fmt->datatype, fmt->input_fmt);
+ }
+ writel_relaxed(cfgr1, csidev->base + STM32_CSI_VCXCFGR1(vc));
+
+ /* Enable processing of the virtual-channel and wait for its status */
+ writel_relaxed(STM32_CSI_CR_VCXSTART(vc) | STM32_CSI_CR_CSIEN,
+ csidev->base + STM32_CSI_CR);
+
+ ret = readl_relaxed_poll_timeout(csidev->base + STM32_CSI_SR0,
+ status,
+ status & STM32_CSI_SR0_VCXSTATEF(vc),
+ 1000, 1000000);
+ if (ret) {
+ dev_err(csidev->dev, "failed to start VC(%d)\n", vc);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stm32_csi_stop_vc(struct stm32_csi_dev *csidev, u32 vc)
+{
+ int ret = 0;
+ u32 status;
+
+ /* Stop the Virtual Channel */
+ writel_relaxed(STM32_CSI_CR_VCXSTOP(vc) | STM32_CSI_CR_CSIEN,
+ csidev->base + STM32_CSI_CR);
+
+ ret = readl_relaxed_poll_timeout(csidev->base + STM32_CSI_SR0,
+ status,
+ !(status & STM32_CSI_SR0_VCXSTATEF(vc)),
+ 1000, 1000000);
+ if (ret) {
+ dev_err(csidev->dev, "failed to stop VC(%d)\n", vc);
+ return ret;
+ }
+
+ /* Disable all DTs */
+ writel_relaxed(0, csidev->base + STM32_CSI_VCXCFGR1(vc));
+ writel_relaxed(0, csidev->base + STM32_CSI_VCXCFGR2(vc));
+
+ return 0;
+}
+
+static int stm32_csi_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct stm32_csi_dev *csidev = to_csidev(sd);
+ int ret;
+
+ ret = v4l2_subdev_disable_streams(csidev->s_subdev,
+ csidev->s_subdev_pad_nb, BIT_ULL(0));
+ if (ret)
+ return ret;
+
+ /* Stop the VC0 */
+ ret = stm32_csi_stop_vc(csidev, 0);
+ if (ret)
+ dev_err(csidev->dev, "Failed to stop VC0\n");
+
+ stm32_csi_stop(csidev);
+
+ return 0;
+}
+
+static int stm32_csi_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state, u32 pad,
+ u64 streams_mask)
+{
+ struct stm32_csi_dev *csidev = to_csidev(sd);
+ int ret;
+
+ ret = stm32_csi_start(csidev, state);
+ if (ret)
+ return ret;
+
+ /* Configure & start the VC0 */
+ ret = stm32_csi_start_vc(csidev, state, 0);
+ if (ret) {
+ dev_err(csidev->dev, "Failed to start VC0\n");
+ stm32_csi_stop(csidev);
+ return ret;
+ }
+
+ ret = v4l2_subdev_enable_streams(csidev->s_subdev,
+ csidev->s_subdev_pad_nb, BIT_ULL(0));
+ if (ret) {
+ stm32_csi_stop_vc(csidev, 0);
+ stm32_csi_stop(csidev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stm32_csi_init_state(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ int i;
+
+ for (i = 0; i < sd->entity.num_pads; i++)
+ *v4l2_subdev_state_get_format(state, i) = fmt_default;
+
+ return 0;
+}
+
+static int stm32_csi_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index >= ARRAY_SIZE(stm32_csi_formats))
+ return -EINVAL;
+
+ code->code = stm32_csi_formats[code->index].code;
+ return 0;
+}
+
+static int stm32_csi_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_format *format)
+{
+ struct stm32_csi_dev *csidev = to_csidev(sd);
+ struct v4l2_mbus_framefmt *framefmt;
+ const struct stm32_csi_fmts *fmt;
+
+ fmt = stm32_csi_code_to_fmt(format->format.code);
+ if (!fmt) {
+ dev_dbg(csidev->dev, "Unsupported code %d, use default\n",
+ format->format.code);
+ format->format.code = fmt_default.code;
+ }
+
+ framefmt = v4l2_subdev_state_get_format(state, STM32_CSI_PAD_SINK);
+
+ if (format->pad == STM32_CSI_PAD_SOURCE)
+ format->format = *framefmt;
+ else
+ *framefmt = format->format;
+
+ framefmt = v4l2_subdev_state_get_format(state, STM32_CSI_PAD_SOURCE);
+ *framefmt = format->format;
+
+ return 0;
+}
+
+static int stm32_csi_log_status(struct v4l2_subdev *sd)
+{
+ struct stm32_csi_dev *csidev = to_csidev(sd);
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&csidev->slock, flags);
+
+ for (i = 0; i < STM32_CSI_NUM_SR0_EVENTS; i++) {
+ if (csidev->sr0_counters[i])
+ dev_info(csidev->dev, "%s events: %d\n",
+ stm32_csi_events_sr0[i].name,
+ csidev->sr0_counters[i]);
+ }
+
+ for (i = 0; i < STM32_CSI_NUM_SR1_EVENTS; i++) {
+ if (csidev->sr1_counters[i])
+ dev_info(csidev->dev, "%s events: %d\n",
+ stm32_csi_events_sr1[i].name,
+ csidev->sr1_counters[i]);
+ }
+
+ spin_unlock_irqrestore(&csidev->slock, flags);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops stm32_csi_core_ops = {
+ .log_status = stm32_csi_log_status,
+};
+
+static const struct v4l2_subdev_video_ops stm32_csi_video_ops = {
+ .s_stream = v4l2_subdev_s_stream_helper,
+};
+
+static const struct v4l2_subdev_pad_ops stm32_csi_pad_ops = {
+ .enum_mbus_code = stm32_csi_enum_mbus_code,
+ .set_fmt = stm32_csi_set_pad_format,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .enable_streams = stm32_csi_enable_streams,
+ .disable_streams = stm32_csi_disable_streams,
+};
+
+static const struct v4l2_subdev_ops stm32_csi_subdev_ops = {
+ .core = &stm32_csi_core_ops,
+ .pad = &stm32_csi_pad_ops,
+ .video = &stm32_csi_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops stm32_csi_subdev_internal_ops = {
+ .init_state = stm32_csi_init_state,
+};
+
+static int stm32_csi_async_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *s_subdev,
+ struct v4l2_async_connection *asd)
+{
+ struct v4l2_subdev *sd = notifier->sd;
+ struct stm32_csi_dev *csidev = to_csidev(sd);
+ int remote_pad;
+
+ remote_pad = media_entity_get_fwnode_pad(&s_subdev->entity,
+ s_subdev->fwnode,
+ MEDIA_PAD_FL_SOURCE);
+ if (remote_pad < 0) {
+ dev_err(csidev->dev, "Couldn't find output pad for subdev %s\n",
+ s_subdev->name);
+ return remote_pad;
+ }
+
+ csidev->s_subdev = s_subdev;
+ csidev->s_subdev_pad_nb = remote_pad;
+
+ return media_create_pad_link(&csidev->s_subdev->entity,
+ remote_pad, &csidev->sd.entity,
+ STM32_CSI_PAD_SINK,
+ MEDIA_LNK_FL_ENABLED |
+ MEDIA_LNK_FL_IMMUTABLE);
+}
+
+static const struct v4l2_async_notifier_operations stm32_csi_notifier_ops = {
+ .bound = stm32_csi_async_bound,
+};
+
+static irqreturn_t stm32_csi_irq_thread(int irq, void *arg)
+{
+ struct stm32_csi_dev *csidev = arg;
+ unsigned long flags;
+ u32 sr0, sr1;
+ int i;
+
+ sr0 = readl_relaxed(csidev->base + STM32_CSI_SR0);
+ sr1 = readl_relaxed(csidev->base + STM32_CSI_SR1);
+
+ /* Clear interrupt */
+ writel_relaxed(sr0 & STM32_CSI_SR0_ERRORS,
+ csidev->base + STM32_CSI_FCR0);
+ writel_relaxed(sr1 & STM32_CSI_SR1_ERRORS,
+ csidev->base + STM32_CSI_FCR1);
+
+ spin_lock_irqsave(&csidev->slock, flags);
+
+ for (i = 0; i < STM32_CSI_NUM_SR0_EVENTS; i++)
+ if (sr0 & stm32_csi_events_sr0[i].mask)
+ csidev->sr0_counters[i]++;
+
+ for (i = 0; i < STM32_CSI_NUM_SR1_EVENTS; i++)
+ if (sr1 & stm32_csi_events_sr1[i].mask)
+ csidev->sr1_counters[i]++;
+
+ spin_unlock_irqrestore(&csidev->slock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int stm32_csi_get_resources(struct stm32_csi_dev *csidev,
+ struct platform_device *pdev)
+{
+ int irq, ret;
+
+ csidev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+ if (IS_ERR(csidev->base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csidev->base),
+ "Failed to ioremap resource\n");
+
+ csidev->pclk = devm_clk_get(&pdev->dev, "pclk");
+ if (IS_ERR(csidev->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csidev->pclk),
+ "Couldn't get pclk\n");
+
+ csidev->txesc = devm_clk_get(&pdev->dev, "txesc");
+ if (IS_ERR(csidev->txesc))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csidev->txesc),
+ "Couldn't get txesc\n");
+
+ csidev->csi2phy = devm_clk_get(&pdev->dev, "csi2phy");
+ if (IS_ERR(csidev->csi2phy))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csidev->csi2phy),
+ "Couldn't get csi2phy\n");
+
+ csidev->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(csidev->rstc))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csidev->rstc),
+ "Couldn't get reset control\n");
+
+ csidev->supplies[0].supply = "vdd";
+ csidev->supplies[1].supply = "vdda18";
+ ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(csidev->supplies),
+ csidev->supplies);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to request regulator vdd\n");
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ stm32_csi_irq_thread, IRQF_ONESHOT,
+ dev_name(&pdev->dev), csidev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Unable to request irq");
+
+ return 0;
+}
+
+static int stm32_csi_parse_dt(struct stm32_csi_dev *csidev)
+{
+ struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
+ struct v4l2_async_connection *asd;
+ struct fwnode_handle *ep;
+ int ret;
+
+ /* Get bus characteristics from devicetree */
+ ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csidev->dev), 0, 0,
+ FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep) {
+ dev_err(csidev->dev, "Could not find the endpoint\n");
+ return -ENODEV;
+ }
+
+ ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep);
+ fwnode_handle_put(ep);
+ if (ret) {
+ dev_err(csidev->dev, "Could not parse v4l2 endpoint\n");
+ return ret;
+ }
+
+ csidev->num_lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes;
+ if (csidev->num_lanes > STM32_CSI_LANES_MAX) {
+ dev_err(csidev->dev, "Unsupported number of data-lanes: %d\n",
+ csidev->num_lanes);
+ return -EINVAL;
+ }
+
+ memcpy(csidev->lanes, v4l2_ep.bus.mipi_csi2.data_lanes,
+ sizeof(csidev->lanes));
+
+ ep = fwnode_graph_get_next_endpoint(dev_fwnode(csidev->dev), NULL);
+ if (!ep) {
+ dev_err(csidev->dev, "Failed to get next endpoint\n");
+ return -EINVAL;
+ }
+
+ v4l2_async_subdev_nf_init(&csidev->notifier, &csidev->sd);
+
+ asd = v4l2_async_nf_add_fwnode_remote(&csidev->notifier, ep,
+ struct v4l2_async_connection);
+
+ fwnode_handle_put(ep);
+
+ if (IS_ERR(asd)) {
+ dev_err(csidev->dev, "Failed to add fwnode remote subdev\n");
+ return PTR_ERR(asd);
+ }
+
+ csidev->notifier.ops = &stm32_csi_notifier_ops;
+
+ ret = v4l2_async_nf_register(&csidev->notifier);
+ if (ret) {
+ dev_err(csidev->dev, "Failed to register notifier\n");
+ v4l2_async_nf_cleanup(&csidev->notifier);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int stm32_csi_probe(struct platform_device *pdev)
+{
+ struct stm32_csi_dev *csidev;
+ int ret;
+
+ csidev = devm_kzalloc(&pdev->dev, sizeof(*csidev), GFP_KERNEL);
+ if (!csidev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, csidev);
+ csidev->dev = &pdev->dev;
+
+ spin_lock_init(&csidev->slock);
+
+ ret = stm32_csi_get_resources(csidev, pdev);
+ if (ret)
+ goto err_free_priv;
+
+ ret = stm32_csi_parse_dt(csidev);
+ if (ret)
+ goto err_free_priv;
+
+ csidev->sd.owner = THIS_MODULE;
+ csidev->sd.dev = &pdev->dev;
+ csidev->sd.internal_ops = &stm32_csi_subdev_internal_ops;
+ v4l2_subdev_init(&csidev->sd, &stm32_csi_subdev_ops);
+ v4l2_set_subdevdata(&csidev->sd, &pdev->dev);
+ snprintf(csidev->sd.name, sizeof(csidev->sd.name), "%s",
+ dev_name(&pdev->dev));
+
+ /* Create our media pads */
+ csidev->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+ csidev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ csidev->pads[STM32_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+ csidev->pads[STM32_CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+ ret = media_entity_pads_init(&csidev->sd.entity, STM32_CSI_PAD_MAX,
+ csidev->pads);
+ if (ret)
+ goto err_cleanup;
+
+ ret = v4l2_subdev_init_finalize(&csidev->sd);
+ if (ret < 0)
+ goto err_cleanup;
+
+ ret = v4l2_async_register_subdev(&csidev->sd);
+ if (ret < 0)
+ goto err_cleanup;
+
+ /* Reset device */
+ ret = reset_control_assert(csidev->rstc);
+ if (ret) {
+ ret = dev_err_probe(&pdev->dev, ret,
+ "Failed to assert the reset line\n");
+ goto err_cleanup;
+ }
+
+ usleep_range(3000, 5000);
+
+ ret = reset_control_deassert(csidev->rstc);
+ if (ret) {
+ ret = dev_err_probe(&pdev->dev, ret,
+ "Failed to deassert the reset line\n");
+ goto err_cleanup;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+
+ dev_info(&pdev->dev,
+ "Probed CSI with %u lanes\n", csidev->num_lanes);
+
+ return 0;
+
+err_cleanup:
+ v4l2_async_nf_cleanup(&csidev->notifier);
+err_free_priv:
+ return ret;
+}
+
+static void stm32_csi_remove(struct platform_device *pdev)
+{
+ struct stm32_csi_dev *csidev = platform_get_drvdata(pdev);
+
+ v4l2_async_unregister_subdev(&csidev->sd);
+
+ pm_runtime_disable(&pdev->dev);
+}
+
+static int stm32_csi_runtime_suspend(struct device *dev)
+{
+ struct stm32_csi_dev *csidev = dev_get_drvdata(dev);
+ int ret;
+
+ clk_disable_unprepare(csidev->csi2phy);
+ clk_disable_unprepare(csidev->txesc);
+ clk_disable_unprepare(csidev->pclk);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(csidev->supplies),
+ csidev->supplies);
+ if (ret < 0)
+ dev_err(dev, "cannot disable regulators %d\n", ret);
+
+ return 0;
+}
+
+static int stm32_csi_runtime_resume(struct device *dev)
+{
+ struct stm32_csi_dev *csidev = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(csidev->supplies),
+ csidev->supplies);
+ if (ret)
+ goto error_out;
+
+ ret = clk_prepare_enable(csidev->pclk);
+ if (ret)
+ goto error_disable_supplies;
+
+ ret = clk_prepare_enable(csidev->txesc);
+ if (ret)
+ goto error_disable_pclk;
+
+ ret = clk_prepare_enable(csidev->csi2phy);
+ if (ret)
+ goto error_disable_txesc;
+
+ return 0;
+
+error_disable_txesc:
+ clk_disable_unprepare(csidev->txesc);
+error_disable_pclk:
+ clk_disable_unprepare(csidev->pclk);
+error_disable_supplies:
+ ret = regulator_bulk_disable(ARRAY_SIZE(csidev->supplies), csidev->supplies);
+ if (ret < 0)
+ dev_err(dev, "cannot disable regulators %d\n", ret);
+error_out:
+ dev_err(csidev->dev, "Failed to resume: %d\n", ret);
+
+ return ret;
+}
+
+static const struct of_device_id stm32_csi_of_table[] = {
+ { .compatible = "st,stm32mp25-csi", },
+ { /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, stm32_csi_of_table);
+
+static const struct dev_pm_ops stm32_csi_pm_ops = {
+ RUNTIME_PM_OPS(stm32_csi_runtime_suspend,
+ stm32_csi_runtime_resume, NULL)
+};
+
+static struct platform_driver stm32_csi_driver = {
+ .driver = {
+ .name = "stm32-csi",
+ .of_match_table = stm32_csi_of_table,
+ .pm = pm_ptr(&stm32_csi_pm_ops),
+ },
+ .probe = stm32_csi_probe,
+ .remove = stm32_csi_remove,
+};
+
+module_platform_driver(stm32_csi_driver);
+
+MODULE_AUTHOR("Alain Volmat <alain.volmat@foss.st.com>");
+MODULE_DESCRIPTION("STM32 CSI controller");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 04/15] media: stm32: dcmipp: use v4l2_subdev_is_streaming
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (2 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 03/15] media: stm32: csi: addition of the STM32 CSI driver Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 05/15] media: stm32: dcmipp: replace s_stream with enable/disable_streams Alain Volmat
` (11 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Rely on v4l2_subdev_is_streaming in order to know if the subdev
is streaming or not instead of relying on a local variable.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c | 6 +-----
drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c | 5 +----
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
index 5a361ad6b023..50500112eab9 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
@@ -78,7 +78,6 @@ struct dcmipp_byteproc_device {
struct v4l2_subdev sd;
struct device *dev;
void __iomem *regs;
- bool streaming;
};
static const struct v4l2_mbus_framefmt fmt_default = {
@@ -239,11 +238,10 @@ static int dcmipp_byteproc_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *mf;
struct v4l2_rect *crop, *compose;
- if (byteproc->streaming)
+ if (v4l2_subdev_is_streaming(sd))
return -EBUSY;
mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
@@ -495,8 +493,6 @@ static int dcmipp_byteproc_s_stream(struct v4l2_subdev *sd, int enable)
}
}
- byteproc->streaming = enable;
-
return 0;
}
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
index 62c5c3331cfe..05e8897ae37a 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
@@ -129,7 +129,6 @@ struct dcmipp_par_device {
struct v4l2_subdev sd;
struct device *dev;
void __iomem *regs;
- bool streaming;
};
static const struct v4l2_mbus_framefmt fmt_default = {
@@ -230,7 +229,7 @@ static int dcmipp_par_set_fmt(struct v4l2_subdev *sd,
struct dcmipp_par_device *par = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *mf;
- if (par->streaming)
+ if (v4l2_subdev_is_streaming(sd))
return -EBUSY;
mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
@@ -370,8 +369,6 @@ static int dcmipp_par_s_stream(struct v4l2_subdev *sd, int enable)
reg_clear(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
}
- par->streaming = enable;
-
return ret;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 05/15] media: stm32: dcmipp: replace s_stream with enable/disable_streams
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (3 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 04/15] media: stm32: dcmipp: use v4l2_subdev_is_streaming Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 06/15] media: stm32: dcmipp: rename dcmipp_parallel into dcmipp_input Alain Volmat
` (10 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Replace s_stream ops with enable_streams and disable_streams.
At the same time, use v4l2_subdev_enable_streams and
v4l2_subdev_disable_streams functions instead of
direct s_stream calls.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 49 ++++------
.../st/stm32/stm32-dcmipp/dcmipp-byteproc.c | 98 +++++++++++--------
.../st/stm32/stm32-dcmipp/dcmipp-parallel.c | 107 ++++++++++++---------
3 files changed, 139 insertions(+), 115 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
index 0f6918f4db38..48596592bfd5 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
@@ -112,6 +112,7 @@ struct dcmipp_bytecap_device {
u32 sequence;
struct media_pipeline pipe;
struct v4l2_subdev *s_subdev;
+ u32 s_subdev_pad_nb;
enum dcmipp_state state;
@@ -337,33 +338,6 @@ static const struct v4l2_ioctl_ops dcmipp_bytecap_ioctl_ops = {
.vidioc_streamoff = vb2_ioctl_streamoff,
};
-static int dcmipp_pipeline_s_stream(struct dcmipp_bytecap_device *vcap,
- int state)
-{
- struct media_pad *pad;
- int ret;
-
- /*
- * Get source subdev - since link is IMMUTABLE, pointer is cached
- * within the dcmipp_bytecap_device structure
- */
- if (!vcap->s_subdev) {
- pad = media_pad_remote_pad_first(&vcap->vdev.entity.pads[0]);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
- return -EINVAL;
- vcap->s_subdev = media_entity_to_v4l2_subdev(pad->entity);
- }
-
- ret = v4l2_subdev_call(vcap->s_subdev, video, s_stream, state);
- if (ret < 0) {
- dev_err(vcap->dev, "failed to %s streaming (%d)\n",
- state ? "start" : "stop", ret);
- return ret;
- }
-
- return 0;
-}
-
static void dcmipp_start_capture(struct dcmipp_bytecap_device *vcap,
struct dcmipp_buf *buf)
{
@@ -395,11 +369,24 @@ static int dcmipp_bytecap_start_streaming(struct vb2_queue *vq,
struct dcmipp_bytecap_device *vcap = vb2_get_drv_priv(vq);
struct media_entity *entity = &vcap->vdev.entity;
struct dcmipp_buf *buf;
+ struct media_pad *pad;
int ret;
vcap->sequence = 0;
memset(&vcap->count, 0, sizeof(vcap->count));
+ /*
+ * Get source subdev - since link is IMMUTABLE, pointer is cached
+ * within the dcmipp_bytecap_device structure
+ */
+ if (!vcap->s_subdev) {
+ pad = media_pad_remote_pad_first(&vcap->vdev.entity.pads[0]);
+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ return -EINVAL;
+ vcap->s_subdev = media_entity_to_v4l2_subdev(pad->entity);
+ vcap->s_subdev_pad_nb = pad->index;
+ }
+
ret = pm_runtime_resume_and_get(vcap->dev);
if (ret < 0) {
dev_err(vcap->dev, "%s: Failed to start streaming, cannot get sync (%d)\n",
@@ -414,7 +401,8 @@ static int dcmipp_bytecap_start_streaming(struct vb2_queue *vq,
goto err_pm_put;
}
- ret = dcmipp_pipeline_s_stream(vcap, 1);
+ ret = v4l2_subdev_enable_streams(vcap->s_subdev,
+ vcap->s_subdev_pad_nb, BIT_ULL(0));
if (ret)
goto err_media_pipeline_stop;
@@ -482,7 +470,10 @@ static void dcmipp_bytecap_stop_streaming(struct vb2_queue *vq)
int ret;
u32 status;
- dcmipp_pipeline_s_stream(vcap, 0);
+ ret = v4l2_subdev_disable_streams(vcap->s_subdev,
+ vcap->s_subdev_pad_nb, BIT_ULL(0));
+ if (ret)
+ dev_warn(vcap->dev, "Failed to disable stream\n");
/* Stop the media pipeline */
media_pipeline_stop(vcap->vdev.entity.pads);
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
index 50500112eab9..a19c8235af56 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
@@ -380,30 +380,19 @@ static int dcmipp_byteproc_set_selection(struct v4l2_subdev *sd,
return 0;
}
-static const struct v4l2_subdev_pad_ops dcmipp_byteproc_pad_ops = {
- .enum_mbus_code = dcmipp_byteproc_enum_mbus_code,
- .enum_frame_size = dcmipp_byteproc_enum_frame_size,
- .get_fmt = v4l2_subdev_get_fmt,
- .set_fmt = dcmipp_byteproc_set_fmt,
- .get_selection = dcmipp_byteproc_get_selection,
- .set_selection = dcmipp_byteproc_set_selection,
-};
-
static int dcmipp_byteproc_configure_scale_crop
- (struct dcmipp_byteproc_device *byteproc)
+ (struct dcmipp_byteproc_device *byteproc,
+ struct v4l2_subdev_state *state)
{
const struct dcmipp_byteproc_pix_map *vpix;
- struct v4l2_subdev_state *state;
struct v4l2_mbus_framefmt *sink_fmt;
u32 hprediv, vprediv;
struct v4l2_rect *compose, *crop;
u32 val = 0;
- state = v4l2_subdev_lock_and_get_active_state(&byteproc->sd);
sink_fmt = v4l2_subdev_state_get_format(state, 0);
compose = v4l2_subdev_state_get_compose(state, 0);
crop = v4l2_subdev_state_get_crop(state, 1);
- v4l2_subdev_unlock_state(state);
/* find output format bpp */
vpix = dcmipp_byteproc_pix_map_by_code(sink_fmt->code);
@@ -458,46 +447,73 @@ static int dcmipp_byteproc_configure_scale_crop
return 0;
}
-static int dcmipp_byteproc_s_stream(struct v4l2_subdev *sd, int enable)
+static int dcmipp_byteproc_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
{
struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
struct v4l2_subdev *s_subdev;
- struct media_pad *pad;
- int ret = 0;
+ struct media_pad *s_pad;
+ int ret;
/* Get source subdev */
- pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
+ if (!s_pad || !is_media_entity_v4l2_subdev(s_pad->entity))
return -EINVAL;
- s_subdev = media_entity_to_v4l2_subdev(pad->entity);
-
- if (enable) {
- ret = dcmipp_byteproc_configure_scale_crop(byteproc);
- if (ret)
- return ret;
-
- ret = v4l2_subdev_call(s_subdev, video, s_stream, enable);
- if (ret < 0) {
- dev_err(byteproc->dev,
- "failed to start source subdev streaming (%d)\n",
- ret);
- return ret;
- }
- } else {
- ret = v4l2_subdev_call(s_subdev, video, s_stream, enable);
- if (ret < 0) {
- dev_err(byteproc->dev,
- "failed to stop source subdev streaming (%d)\n",
- ret);
- return ret;
- }
+ s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
+
+ ret = dcmipp_byteproc_configure_scale_crop(byteproc, state);
+ if (ret)
+ return ret;
+
+ ret = v4l2_subdev_enable_streams(s_subdev, s_pad->index, BIT_ULL(0));
+ if (ret < 0) {
+ dev_err(byteproc->dev,
+ "failed to start source subdev streaming (%d)\n", ret);
+ return ret;
}
return 0;
}
+static int dcmipp_byteproc_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ struct dcmipp_byteproc_device *byteproc = v4l2_get_subdevdata(sd);
+ struct v4l2_subdev *s_subdev;
+ struct media_pad *s_pad;
+ int ret;
+
+ /* Get source subdev */
+ s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
+ if (!s_pad || !is_media_entity_v4l2_subdev(s_pad->entity))
+ return -EINVAL;
+ s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
+
+ ret = v4l2_subdev_disable_streams(s_subdev, s_pad->index, BIT_ULL(0));
+ if (ret < 0) {
+ dev_err(byteproc->dev,
+ "failed to start source subdev streaming (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops dcmipp_byteproc_pad_ops = {
+ .enum_mbus_code = dcmipp_byteproc_enum_mbus_code,
+ .enum_frame_size = dcmipp_byteproc_enum_frame_size,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = dcmipp_byteproc_set_fmt,
+ .get_selection = dcmipp_byteproc_get_selection,
+ .set_selection = dcmipp_byteproc_set_selection,
+ .enable_streams = dcmipp_byteproc_enable_streams,
+ .disable_streams = dcmipp_byteproc_disable_streams,
+};
+
static const struct v4l2_subdev_video_ops dcmipp_byteproc_video_ops = {
- .s_stream = dcmipp_byteproc_s_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_ops dcmipp_byteproc_ops = {
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
index 05e8897ae37a..ffb71c9fc947 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
@@ -260,18 +260,11 @@ static int dcmipp_par_set_fmt(struct v4l2_subdev *sd,
return 0;
}
-static const struct v4l2_subdev_pad_ops dcmipp_par_pad_ops = {
- .enum_mbus_code = dcmipp_par_enum_mbus_code,
- .enum_frame_size = dcmipp_par_enum_frame_size,
- .get_fmt = v4l2_subdev_get_fmt,
- .set_fmt = dcmipp_par_set_fmt,
-};
-
-static int dcmipp_par_configure(struct dcmipp_par_device *par)
+static int dcmipp_par_configure(struct dcmipp_par_device *par,
+ struct v4l2_subdev_state *state)
{
u32 val = 0;
const struct dcmipp_par_pix_map *vpix;
- struct v4l2_subdev_state *state;
struct v4l2_mbus_framefmt *sink_fmt;
struct v4l2_mbus_framefmt *src_fmt;
@@ -305,10 +298,8 @@ static int dcmipp_par_configure(struct dcmipp_par_device *par)
}
/* Set format */
- state = v4l2_subdev_lock_and_get_active_state(&par->sd);
sink_fmt = v4l2_subdev_state_get_format(state, 0);
src_fmt = v4l2_subdev_state_get_format(state, 1);
- v4l2_subdev_unlock_state(state);
vpix = dcmipp_par_pix_map_by_code(sink_fmt->code, src_fmt->code);
if (!vpix) {
@@ -327,53 +318,79 @@ static int dcmipp_par_configure(struct dcmipp_par_device *par)
return 0;
}
-static int dcmipp_par_s_stream(struct v4l2_subdev *sd, int enable)
+static int dcmipp_par_enable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
{
struct dcmipp_par_device *par =
container_of(sd, struct dcmipp_par_device, sd);
struct v4l2_subdev *s_subdev;
- struct media_pad *pad;
- int ret = 0;
+ struct media_pad *s_pad;
+ int ret;
/* Get source subdev */
- pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
- if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
+ s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
+ if (!s_pad || !is_media_entity_v4l2_subdev(s_pad->entity))
return -EINVAL;
- s_subdev = media_entity_to_v4l2_subdev(pad->entity);
-
- if (enable) {
- ret = dcmipp_par_configure(par);
- if (ret)
- return ret;
-
- /* Enable parallel interface */
- reg_set(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
-
- ret = v4l2_subdev_call(s_subdev, video, s_stream, enable);
- if (ret < 0) {
- dev_err(par->dev,
- "failed to start source subdev streaming (%d)\n",
- ret);
- return ret;
- }
- } else {
- ret = v4l2_subdev_call(s_subdev, video, s_stream, enable);
- if (ret < 0) {
- dev_err(par->dev,
- "failed to stop source subdev streaming (%d)\n",
- ret);
- return ret;
- }
+ s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
+
+ ret = dcmipp_par_configure(par);
+ if (ret)
+ return ret;
+
+ /* Enable parallel interface */
+ reg_set(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
- /* Disable parallel interface */
- reg_clear(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+ ret = v4l2_subdev_enable_streams(s_subdev, s_pad->index, BIT_ULL(0));
+ if (ret < 0) {
+ dev_err(par->dev,
+ "failed to start source subdev streaming (%d)\n", ret);
+ return ret;
}
- return ret;
+ return 0;
}
+static int dcmipp_par_disable_streams(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ u32 pad, u64 streams_mask)
+{
+ struct dcmipp_par_device *par =
+ container_of(sd, struct dcmipp_par_device, sd);
+ struct v4l2_subdev *s_subdev;
+ struct media_pad *s_pad;
+ int ret;
+
+ /* Get source subdev */
+ s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
+ if (!s_pad || !is_media_entity_v4l2_subdev(s_pad->entity))
+ return -EINVAL;
+ s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
+
+ ret = v4l2_subdev_disable_streams(s_subdev, s_pad->index, BIT_ULL(0));
+ if (ret < 0) {
+ dev_err(par->dev,
+ "failed to stop source subdev streaming (%d)\n", ret);
+ return ret;
+ }
+
+ /* Disable parallel interface */
+ reg_clear(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_pad_ops dcmipp_par_pad_ops = {
+ .enum_mbus_code = dcmipp_par_enum_mbus_code,
+ .enum_frame_size = dcmipp_par_enum_frame_size,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = dcmipp_par_set_fmt,
+ .enable_streams = dcmipp_par_enable_streams,
+ .disable_streams = dcmipp_par_disable_streams,
+};
+
static const struct v4l2_subdev_video_ops dcmipp_par_video_ops = {
- .s_stream = dcmipp_par_s_stream,
+ .s_stream = v4l2_subdev_s_stream_helper,
};
static const struct v4l2_subdev_ops dcmipp_par_ops = {
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 06/15] media: stm32: dcmipp: rename dcmipp_parallel into dcmipp_input
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (4 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 05/15] media: stm32: dcmipp: replace s_stream with enable/disable_streams Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 07/15] media: stm32: dcmipp: add support for csi input into dcmipp-input Alain Volmat
` (9 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
In preparation of the introduction of dcmipp csi input support, rename
the dcmipp_parallel subdev into a generic dcmipp_input which will be in
charge of handling both parallel input & csi input.
Only structures / variables / functions and file naming are changed without
any functional modifications.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../media/platform/st/stm32/stm32-dcmipp/Makefile | 2 +-
.../platform/st/stm32/stm32-dcmipp/dcmipp-common.h | 4 +-
.../platform/st/stm32/stm32-dcmipp/dcmipp-core.c | 12 +-
.../{dcmipp-parallel.c => dcmipp-input.c} | 178 ++++++++++-----------
4 files changed, 98 insertions(+), 98 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/Makefile b/drivers/media/platform/st/stm32/stm32-dcmipp/Makefile
index 8920d9388a21..159105fb40b8 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/Makefile
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-stm32-dcmipp-y := dcmipp-core.o dcmipp-common.o dcmipp-parallel.o dcmipp-byteproc.o dcmipp-bytecap.o
+stm32-dcmipp-y := dcmipp-core.o dcmipp-common.o dcmipp-input.o dcmipp-byteproc.o dcmipp-bytecap.o
obj-$(CONFIG_VIDEO_STM32_DCMIPP) += stm32-dcmipp.o
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
index 7a7cf43baf24..fe5f97233f5e 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
@@ -199,11 +199,11 @@ static inline void __reg_clear(struct device *dev, void __iomem *base, u32 reg,
}
/* DCMIPP subdev init / release entry points */
-struct dcmipp_ent_device *dcmipp_par_ent_init(struct device *dev,
+struct dcmipp_ent_device *dcmipp_inp_ent_init(struct device *dev,
const char *entity_name,
struct v4l2_device *v4l2_dev,
void __iomem *regs);
-void dcmipp_par_ent_release(struct dcmipp_ent_device *ved);
+void dcmipp_inp_ent_release(struct dcmipp_ent_device *ved);
struct dcmipp_ent_device *
dcmipp_byteproc_ent_init(struct device *dev, const char *entity_name,
struct v4l2_device *v4l2_dev, void __iomem *regs);
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
index 7f771ea49b78..50b9b964fbc4 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
@@ -95,9 +95,9 @@ struct dcmipp_pipeline_config {
static const struct dcmipp_ent_config stm32mp13_ent_config[] = {
{
- .name = "dcmipp_parallel",
- .init = dcmipp_par_ent_init,
- .release = dcmipp_par_ent_release,
+ .name = "dcmipp_input",
+ .init = dcmipp_inp_ent_init,
+ .release = dcmipp_inp_ent_release,
},
{
.name = "dcmipp_dump_postproc",
@@ -111,12 +111,12 @@ static const struct dcmipp_ent_config stm32mp13_ent_config[] = {
},
};
-#define ID_PARALLEL 0
+#define ID_INPUT 0
#define ID_DUMP_BYTEPROC 1
#define ID_DUMP_CAPTURE 2
static const struct dcmipp_ent_link stm32mp13_ent_links[] = {
- DCMIPP_ENT_LINK(ID_PARALLEL, 1, ID_DUMP_BYTEPROC, 0,
+ DCMIPP_ENT_LINK(ID_INPUT, 1, ID_DUMP_BYTEPROC, 0,
MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
DCMIPP_ENT_LINK(ID_DUMP_BYTEPROC, 1, ID_DUMP_CAPTURE, 0,
MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
@@ -309,7 +309,7 @@ static int dcmipp_graph_notify_bound(struct v4l2_async_notifier *notifier,
}
/* Parallel input device detected, connect it to parallel subdev */
- sink = dcmipp->entity[ID_PARALLEL];
+ sink = dcmipp->entity[ID_INPUT];
sink->bus.flags = vep.bus.parallel.flags;
sink->bus.bus_width = vep.bus.parallel.bus_width;
sink->bus.data_shift = vep.bus.parallel.data_shift;
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
similarity index 66%
rename from drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
rename to drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
index ffb71c9fc947..106f2a559812 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-parallel.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
@@ -34,7 +34,7 @@
#define IS_SINK(pad) (!(pad))
#define IS_SRC(pad) ((pad))
-struct dcmipp_par_pix_map {
+struct dcmipp_inp_pix_map {
unsigned int code_sink;
unsigned int code_src;
u8 prcr_format;
@@ -48,7 +48,7 @@ struct dcmipp_par_pix_map {
.prcr_format = DCMIPP_PRCR_FORMAT_##prcr, \
.prcr_swapcycles = swap, \
}
-static const struct dcmipp_par_pix_map dcmipp_par_pix_map_list[] = {
+static const struct dcmipp_inp_pix_map dcmipp_inp_pix_map_list[] = {
/* RGB565 */
PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_2X8_LE, RGB565_2X8_LE, RGB565, 1),
PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_2X8_BE, RGB565_2X8_LE, RGB565, 0),
@@ -74,18 +74,18 @@ static const struct dcmipp_par_pix_map dcmipp_par_pix_map_list[] = {
* Search through the pix_map table, skipping two consecutive entry with the
* same code
*/
-static inline const struct dcmipp_par_pix_map *dcmipp_par_pix_map_by_index
+static inline const struct dcmipp_inp_pix_map *dcmipp_inp_pix_map_by_index
(unsigned int index,
unsigned int pad)
{
unsigned int i = 0;
u32 prev_code = 0, cur_code;
- while (i < ARRAY_SIZE(dcmipp_par_pix_map_list)) {
+ while (i < ARRAY_SIZE(dcmipp_inp_pix_map_list)) {
if (IS_SRC(pad))
- cur_code = dcmipp_par_pix_map_list[i].code_src;
+ cur_code = dcmipp_inp_pix_map_list[i].code_src;
else
- cur_code = dcmipp_par_pix_map_list[i].code_sink;
+ cur_code = dcmipp_inp_pix_map_list[i].code_sink;
if (cur_code == prev_code) {
i++;
@@ -99,32 +99,32 @@ static inline const struct dcmipp_par_pix_map *dcmipp_par_pix_map_by_index
index--;
}
- if (i >= ARRAY_SIZE(dcmipp_par_pix_map_list))
+ if (i >= ARRAY_SIZE(dcmipp_inp_pix_map_list))
return NULL;
- return &dcmipp_par_pix_map_list[i];
+ return &dcmipp_inp_pix_map_list[i];
}
-static inline const struct dcmipp_par_pix_map *dcmipp_par_pix_map_by_code
+static inline const struct dcmipp_inp_pix_map *dcmipp_inp_pix_map_by_code
(u32 code_sink, u32 code_src)
{
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(dcmipp_par_pix_map_list); i++) {
- if ((dcmipp_par_pix_map_list[i].code_sink == code_sink &&
- dcmipp_par_pix_map_list[i].code_src == code_src) ||
- (dcmipp_par_pix_map_list[i].code_sink == code_src &&
- dcmipp_par_pix_map_list[i].code_src == code_sink) ||
- (dcmipp_par_pix_map_list[i].code_sink == code_sink &&
+ for (i = 0; i < ARRAY_SIZE(dcmipp_inp_pix_map_list); i++) {
+ if ((dcmipp_inp_pix_map_list[i].code_sink == code_sink &&
+ dcmipp_inp_pix_map_list[i].code_src == code_src) ||
+ (dcmipp_inp_pix_map_list[i].code_sink == code_src &&
+ dcmipp_inp_pix_map_list[i].code_src == code_sink) ||
+ (dcmipp_inp_pix_map_list[i].code_sink == code_sink &&
code_src == 0) ||
(code_sink == 0 &&
- dcmipp_par_pix_map_list[i].code_src == code_src))
- return &dcmipp_par_pix_map_list[i];
+ dcmipp_inp_pix_map_list[i].code_src == code_src))
+ return &dcmipp_inp_pix_map_list[i];
}
return NULL;
}
-struct dcmipp_par_device {
+struct dcmipp_inp_device {
struct dcmipp_ent_device ved;
struct v4l2_subdev sd;
struct device *dev;
@@ -142,7 +142,7 @@ static const struct v4l2_mbus_framefmt fmt_default = {
.xfer_func = DCMIPP_XFER_FUNC_DEFAULT,
};
-static int dcmipp_par_init_state(struct v4l2_subdev *sd,
+static int dcmipp_inp_init_state(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state)
{
unsigned int i;
@@ -157,12 +157,12 @@ static int dcmipp_par_init_state(struct v4l2_subdev *sd,
return 0;
}
-static int dcmipp_par_enum_mbus_code(struct v4l2_subdev *sd,
+static int dcmipp_inp_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
- const struct dcmipp_par_pix_map *vpix =
- dcmipp_par_pix_map_by_index(code->index, code->pad);
+ const struct dcmipp_inp_pix_map *vpix =
+ dcmipp_inp_pix_map_by_index(code->index, code->pad);
if (!vpix)
return -EINVAL;
@@ -172,17 +172,17 @@ static int dcmipp_par_enum_mbus_code(struct v4l2_subdev *sd,
return 0;
}
-static int dcmipp_par_enum_frame_size(struct v4l2_subdev *sd,
+static int dcmipp_inp_enum_frame_size(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_size_enum *fse)
{
- const struct dcmipp_par_pix_map *vpix;
+ const struct dcmipp_inp_pix_map *vpix;
if (fse->index)
return -EINVAL;
/* Only accept code in the pix map table */
- vpix = dcmipp_par_pix_map_by_code(IS_SINK(fse->pad) ? fse->code : 0,
+ vpix = dcmipp_inp_pix_map_by_code(IS_SINK(fse->pad) ? fse->code : 0,
IS_SRC(fse->pad) ? fse->code : 0);
if (!vpix)
return -EINVAL;
@@ -195,20 +195,20 @@ static int dcmipp_par_enum_frame_size(struct v4l2_subdev *sd,
return 0;
}
-static void dcmipp_par_adjust_fmt(struct dcmipp_par_device *par,
+static void dcmipp_inp_adjust_fmt(struct dcmipp_inp_device *inp,
struct v4l2_mbus_framefmt *fmt, __u32 pad)
{
- const struct dcmipp_par_pix_map *vpix;
+ const struct dcmipp_inp_pix_map *vpix;
/* Only accept code in the pix map table */
- vpix = dcmipp_par_pix_map_by_code(IS_SINK(pad) ? fmt->code : 0,
+ vpix = dcmipp_inp_pix_map_by_code(IS_SINK(pad) ? fmt->code : 0,
IS_SRC(pad) ? fmt->code : 0);
if (!vpix)
fmt->code = fmt_default.code;
/* Exclude JPEG if BT656 bus is selected */
if (vpix && vpix->code_sink == MEDIA_BUS_FMT_JPEG_1X8 &&
- par->ved.bus_type == V4L2_MBUS_BT656)
+ inp->ved.bus_type == V4L2_MBUS_BT656)
fmt->code = fmt_default.code;
fmt->width = clamp_t(u32, fmt->width, DCMIPP_FRAME_MIN_WIDTH,
@@ -222,11 +222,11 @@ static void dcmipp_par_adjust_fmt(struct dcmipp_par_device *par,
dcmipp_colorimetry_clamp(fmt);
}
-static int dcmipp_par_set_fmt(struct v4l2_subdev *sd,
+static int dcmipp_inp_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
- struct dcmipp_par_device *par = v4l2_get_subdevdata(sd);
+ struct dcmipp_inp_device *inp = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *mf;
if (v4l2_subdev_is_streaming(sd))
@@ -235,10 +235,10 @@ static int dcmipp_par_set_fmt(struct v4l2_subdev *sd,
mf = v4l2_subdev_state_get_format(sd_state, fmt->pad);
/* Set the new format */
- dcmipp_par_adjust_fmt(par, &fmt->format, fmt->pad);
+ dcmipp_inp_adjust_fmt(inp, &fmt->format, fmt->pad);
- dev_dbg(par->dev, "%s: format update: old:%dx%d (0x%x, %d, %d, %d, %d) new:%dx%d (0x%x, %d, %d, %d, %d)\n",
- par->sd.name,
+ dev_dbg(inp->dev, "%s: format update: old:%dx%d (0x%x, %d, %d, %d, %d) new:%dx%d (0x%x, %d, %d, %d, %d)\n",
+ inp->sd.name,
/* old */
mf->width, mf->height, mf->code,
mf->colorspace, mf->quantization,
@@ -254,30 +254,30 @@ static int dcmipp_par_set_fmt(struct v4l2_subdev *sd,
if (IS_SINK(fmt->pad)) {
mf = v4l2_subdev_state_get_format(sd_state, 1);
*mf = fmt->format;
- dcmipp_par_adjust_fmt(par, mf, 1);
+ dcmipp_inp_adjust_fmt(inp, mf, 1);
}
return 0;
}
-static int dcmipp_par_configure(struct dcmipp_par_device *par,
+static int dcmipp_inp_configure(struct dcmipp_inp_device *inp,
struct v4l2_subdev_state *state)
{
u32 val = 0;
- const struct dcmipp_par_pix_map *vpix;
+ const struct dcmipp_inp_pix_map *vpix;
struct v4l2_mbus_framefmt *sink_fmt;
struct v4l2_mbus_framefmt *src_fmt;
/* Set vertical synchronization polarity */
- if (par->ved.bus.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+ if (inp->ved.bus.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
val |= DCMIPP_PRCR_VSPOL;
/* Set horizontal synchronization polarity */
- if (par->ved.bus.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+ if (inp->ved.bus.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
val |= DCMIPP_PRCR_HSPOL;
/* Set pixel clock polarity */
- if (par->ved.bus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+ if (inp->ved.bus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
val |= DCMIPP_PRCR_PCKPOL;
/*
@@ -287,23 +287,23 @@ static int dcmipp_par_configure(struct dcmipp_par_device *par,
* SAV=0xff000080 & EAV=0xff00009d.
* With DCMIPP this means LSC=SAV=0x80 & LEC=EAV=0x9d.
*/
- if (par->ved.bus_type == V4L2_MBUS_BT656) {
+ if (inp->ved.bus_type == V4L2_MBUS_BT656) {
val |= DCMIPP_PRCR_ESS;
/* Unmask all codes */
- reg_write(par, DCMIPP_PRESUR, 0xffffffff);/* FEC:LEC:LSC:FSC */
+ reg_write(inp, DCMIPP_PRESUR, 0xffffffff);/* FEC:LEC:LSC:FSC */
/* Trig on LSC=0x80 & LEC=0x9d codes, ignore FSC and FEC */
- reg_write(par, DCMIPP_PRESCR, 0xff9d80ff);/* FEC:LEC:LSC:FSC */
+ reg_write(inp, DCMIPP_PRESCR, 0xff9d80ff);/* FEC:LEC:LSC:FSC */
}
/* Set format */
sink_fmt = v4l2_subdev_state_get_format(state, 0);
src_fmt = v4l2_subdev_state_get_format(state, 1);
- vpix = dcmipp_par_pix_map_by_code(sink_fmt->code, src_fmt->code);
+ vpix = dcmipp_inp_pix_map_by_code(sink_fmt->code, src_fmt->code);
if (!vpix) {
- dev_err(par->dev, "Invalid sink/src format configuration\n");
+ dev_err(inp->dev, "Invalid sink/src format configuration\n");
return -EINVAL;
}
@@ -313,17 +313,17 @@ static int dcmipp_par_configure(struct dcmipp_par_device *par,
if (vpix->prcr_swapcycles)
val |= DCMIPP_PRCR_SWAPCYCLES;
- reg_write(par, DCMIPP_PRCR, val);
+ reg_write(inp, DCMIPP_PRCR, val);
return 0;
}
-static int dcmipp_par_enable_streams(struct v4l2_subdev *sd,
+static int dcmipp_inp_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
u32 pad, u64 streams_mask)
{
- struct dcmipp_par_device *par =
- container_of(sd, struct dcmipp_par_device, sd);
+ struct dcmipp_inp_device *inp =
+ container_of(sd, struct dcmipp_inp_device, sd);
struct v4l2_subdev *s_subdev;
struct media_pad *s_pad;
int ret;
@@ -334,16 +334,16 @@ static int dcmipp_par_enable_streams(struct v4l2_subdev *sd,
return -EINVAL;
s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
- ret = dcmipp_par_configure(par);
+ ret = dcmipp_inp_configure(inp);
if (ret)
return ret;
/* Enable parallel interface */
- reg_set(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+ reg_set(inp, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
ret = v4l2_subdev_enable_streams(s_subdev, s_pad->index, BIT_ULL(0));
if (ret < 0) {
- dev_err(par->dev,
+ dev_err(inp->dev,
"failed to start source subdev streaming (%d)\n", ret);
return ret;
}
@@ -351,12 +351,12 @@ static int dcmipp_par_enable_streams(struct v4l2_subdev *sd,
return 0;
}
-static int dcmipp_par_disable_streams(struct v4l2_subdev *sd,
+static int dcmipp_inp_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
u32 pad, u64 streams_mask)
{
- struct dcmipp_par_device *par =
- container_of(sd, struct dcmipp_par_device, sd);
+ struct dcmipp_inp_device *inp =
+ container_of(sd, struct dcmipp_inp_device, sd);
struct v4l2_subdev *s_subdev;
struct media_pad *s_pad;
int ret;
@@ -369,86 +369,86 @@ static int dcmipp_par_disable_streams(struct v4l2_subdev *sd,
ret = v4l2_subdev_disable_streams(s_subdev, s_pad->index, BIT_ULL(0));
if (ret < 0) {
- dev_err(par->dev,
+ dev_err(inp->dev,
"failed to stop source subdev streaming (%d)\n", ret);
return ret;
}
/* Disable parallel interface */
- reg_clear(par, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+ reg_clear(inp, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
return 0;
}
-static const struct v4l2_subdev_pad_ops dcmipp_par_pad_ops = {
- .enum_mbus_code = dcmipp_par_enum_mbus_code,
- .enum_frame_size = dcmipp_par_enum_frame_size,
+static const struct v4l2_subdev_pad_ops dcmipp_inp_pad_ops = {
+ .enum_mbus_code = dcmipp_inp_enum_mbus_code,
+ .enum_frame_size = dcmipp_inp_enum_frame_size,
.get_fmt = v4l2_subdev_get_fmt,
- .set_fmt = dcmipp_par_set_fmt,
- .enable_streams = dcmipp_par_enable_streams,
- .disable_streams = dcmipp_par_disable_streams,
+ .set_fmt = dcmipp_inp_set_fmt,
+ .enable_streams = dcmipp_inp_enable_streams,
+ .disable_streams = dcmipp_inp_disable_streams,
};
-static const struct v4l2_subdev_video_ops dcmipp_par_video_ops = {
+static const struct v4l2_subdev_video_ops dcmipp_inp_video_ops = {
.s_stream = v4l2_subdev_s_stream_helper,
};
-static const struct v4l2_subdev_ops dcmipp_par_ops = {
- .pad = &dcmipp_par_pad_ops,
- .video = &dcmipp_par_video_ops,
+static const struct v4l2_subdev_ops dcmipp_inp_ops = {
+ .pad = &dcmipp_inp_pad_ops,
+ .video = &dcmipp_inp_video_ops,
};
-static void dcmipp_par_release(struct v4l2_subdev *sd)
+static void dcmipp_inp_release(struct v4l2_subdev *sd)
{
- struct dcmipp_par_device *par =
- container_of(sd, struct dcmipp_par_device, sd);
+ struct dcmipp_inp_device *inp =
+ container_of(sd, struct dcmipp_inp_device, sd);
- kfree(par);
+ kfree(inp);
}
-static const struct v4l2_subdev_internal_ops dcmipp_par_int_ops = {
- .init_state = dcmipp_par_init_state,
- .release = dcmipp_par_release,
+static const struct v4l2_subdev_internal_ops dcmipp_inp_int_ops = {
+ .init_state = dcmipp_inp_init_state,
+ .release = dcmipp_inp_release,
};
-void dcmipp_par_ent_release(struct dcmipp_ent_device *ved)
+void dcmipp_inp_ent_release(struct dcmipp_ent_device *ved)
{
- struct dcmipp_par_device *par =
- container_of(ved, struct dcmipp_par_device, ved);
+ struct dcmipp_inp_device *inp =
+ container_of(ved, struct dcmipp_inp_device, ved);
- dcmipp_ent_sd_unregister(ved, &par->sd);
+ dcmipp_ent_sd_unregister(ved, &inp->sd);
}
-struct dcmipp_ent_device *dcmipp_par_ent_init(struct device *dev,
+struct dcmipp_ent_device *dcmipp_inp_ent_init(struct device *dev,
const char *entity_name,
struct v4l2_device *v4l2_dev,
void __iomem *regs)
{
- struct dcmipp_par_device *par;
+ struct dcmipp_inp_device *inp;
const unsigned long pads_flag[] = {
MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE,
};
int ret;
- /* Allocate the par struct */
- par = kzalloc(sizeof(*par), GFP_KERNEL);
- if (!par)
+ /* Allocate the inp struct */
+ inp = kzalloc(sizeof(*inp), GFP_KERNEL);
+ if (!inp)
return ERR_PTR(-ENOMEM);
- par->regs = regs;
+ inp->regs = regs;
/* Initialize ved and sd */
- ret = dcmipp_ent_sd_register(&par->ved, &par->sd, v4l2_dev,
+ ret = dcmipp_ent_sd_register(&inp->ved, &inp->sd, v4l2_dev,
entity_name, MEDIA_ENT_F_VID_IF_BRIDGE,
ARRAY_SIZE(pads_flag), pads_flag,
- &dcmipp_par_int_ops, &dcmipp_par_ops,
+ &dcmipp_inp_int_ops, &dcmipp_inp_ops,
NULL, NULL);
if (ret) {
- kfree(par);
+ kfree(inp);
return ERR_PTR(ret);
}
- par->dev = dev;
+ inp->dev = dev;
- return &par->ved;
+ return &inp->ved;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 07/15] media: stm32: dcmipp: add support for csi input into dcmipp-input
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (5 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 06/15] media: stm32: dcmipp: rename dcmipp_parallel into dcmipp_input Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 08/15] media: stm32: dcmipp: add bayer 10~14 bits formats Alain Volmat
` (8 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
On stm32mp25, the dcmipp can accept data coming from a CSI bus in
addition to the parallel interface. Add this support into
dcmipp-input subdev.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../platform/st/stm32/stm32-dcmipp/dcmipp-input.c | 134 +++++++++++++++++----
1 file changed, 110 insertions(+), 24 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
index 106f2a559812..7e5311b67d7e 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
@@ -9,6 +9,7 @@
*/
#include <linux/v4l2-mediabus.h>
+#include <media/mipi-csi2.h>
#include <media/v4l2-event.h>
#include <media/v4l2-subdev.h>
@@ -19,6 +20,9 @@
#define DCMIPP_PRCR_FORMAT_YUV422 0x1e
#define DCMIPP_PRCR_FORMAT_RGB565 0x22
#define DCMIPP_PRCR_FORMAT_RAW8 0x2a
+#define DCMIPP_PRCR_FORMAT_RAW10 0x2b
+#define DCMIPP_PRCR_FORMAT_RAW12 0x2c
+#define DCMIPP_PRCR_FORMAT_RAW14 0x2d
#define DCMIPP_PRCR_FORMAT_G8 0x4a
#define DCMIPP_PRCR_FORMAT_BYTE_STREAM 0x5a
#define DCMIPP_PRCR_ESS BIT(4)
@@ -31,43 +35,75 @@
#define DCMIPP_PRESCR 0x108
#define DCMIPP_PRESUR 0x10c
+#define DCMIPP_CMCR 0x204
+#define DCMIPP_CMCR_INSEL BIT(0)
+
+#define DCMIPP_P0FSCR 0x404
+#define DCMIPP_P0FSCR_DTMODE_MASK GENMASK(17, 16)
+#define DCMIPP_P0FSCR_DTMODE_SHIFT 16
+#define DCMIPP_P0FSCR_DTMODE_DTIDA 0x00
+#define DCMIPP_P0FSCR_DTMODE_ALLDT 0x03
+#define DCMIPP_P0FSCR_DTIDA_MASK GENMASK(5, 0)
+#define DCMIPP_P0FSCR_DTIDA_SHIFT 0
+
#define IS_SINK(pad) (!(pad))
#define IS_SRC(pad) ((pad))
struct dcmipp_inp_pix_map {
unsigned int code_sink;
unsigned int code_src;
+ /* Parallel related information */
u8 prcr_format;
u8 prcr_swapcycles;
+ /* CSI related information */
+ unsigned int dt;
};
-#define PIXMAP_SINK_SRC_PRCR_SWAP(sink, src, prcr, swap) \
+#define PIXMAP_SINK_SRC_PRCR_SWAP(sink, src, prcr, swap, data_type) \
{ \
.code_sink = MEDIA_BUS_FMT_##sink, \
.code_src = MEDIA_BUS_FMT_##src, \
.prcr_format = DCMIPP_PRCR_FORMAT_##prcr, \
.prcr_swapcycles = swap, \
+ .dt = data_type, \
}
static const struct dcmipp_inp_pix_map dcmipp_inp_pix_map_list[] = {
/* RGB565 */
- PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_2X8_LE, RGB565_2X8_LE, RGB565, 1),
- PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_2X8_BE, RGB565_2X8_LE, RGB565, 0),
+ PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_2X8_LE, RGB565_2X8_LE, RGB565, 1, MIPI_CSI2_DT_RGB565),
+ PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_2X8_BE, RGB565_2X8_LE, RGB565, 0, MIPI_CSI2_DT_RGB565),
+ PIXMAP_SINK_SRC_PRCR_SWAP(RGB565_1X16, RGB565_1X16, RGB565, 0, MIPI_CSI2_DT_RGB565),
/* YUV422 */
- PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_2X8, YUYV8_2X8, YUV422, 1),
- PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_2X8, UYVY8_2X8, YUV422, 0),
- PIXMAP_SINK_SRC_PRCR_SWAP(UYVY8_2X8, UYVY8_2X8, YUV422, 1),
- PIXMAP_SINK_SRC_PRCR_SWAP(UYVY8_2X8, YUYV8_2X8, YUV422, 0),
- PIXMAP_SINK_SRC_PRCR_SWAP(YVYU8_2X8, YVYU8_2X8, YUV422, 1),
- PIXMAP_SINK_SRC_PRCR_SWAP(VYUY8_2X8, VYUY8_2X8, YUV422, 1),
+ PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_2X8, YUYV8_2X8, YUV422, 1, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_1X16, YUYV8_1X16, YUV422, 0, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_2X8, UYVY8_2X8, YUV422, 0, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(UYVY8_2X8, UYVY8_2X8, YUV422, 1, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(UYVY8_1X16, UYVY8_1X16, YUV422, 0, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(UYVY8_2X8, YUYV8_2X8, YUV422, 0, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(YVYU8_2X8, YVYU8_2X8, YUV422, 1, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(YVYU8_1X16, YVYU8_1X16, YUV422, 0, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(VYUY8_2X8, VYUY8_2X8, YUV422, 1, MIPI_CSI2_DT_YUV422_8B),
+ PIXMAP_SINK_SRC_PRCR_SWAP(VYUY8_1X16, VYUY8_1X16, YUV422, 0, MIPI_CSI2_DT_YUV422_8B),
/* GREY */
- PIXMAP_SINK_SRC_PRCR_SWAP(Y8_1X8, Y8_1X8, G8, 0),
+ PIXMAP_SINK_SRC_PRCR_SWAP(Y8_1X8, Y8_1X8, G8, 0, MIPI_CSI2_DT_RAW8),
/* Raw Bayer */
- PIXMAP_SINK_SRC_PRCR_SWAP(SBGGR8_1X8, SBGGR8_1X8, RAW8, 0),
- PIXMAP_SINK_SRC_PRCR_SWAP(SGBRG8_1X8, SGBRG8_1X8, RAW8, 0),
- PIXMAP_SINK_SRC_PRCR_SWAP(SGRBG8_1X8, SGRBG8_1X8, RAW8, 0),
- PIXMAP_SINK_SRC_PRCR_SWAP(SRGGB8_1X8, SRGGB8_1X8, RAW8, 0),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SBGGR8_1X8, SBGGR8_1X8, RAW8, 0, MIPI_CSI2_DT_RAW8),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGBRG8_1X8, SGBRG8_1X8, RAW8, 0, MIPI_CSI2_DT_RAW8),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGRBG8_1X8, SGRBG8_1X8, RAW8, 0, MIPI_CSI2_DT_RAW8),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SRGGB8_1X8, SRGGB8_1X8, RAW8, 0, MIPI_CSI2_DT_RAW8),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SBGGR10_1X10, SBGGR10_1X10, RAW10, 0, MIPI_CSI2_DT_RAW10),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGBRG10_1X10, SGBRG10_1X10, RAW10, 0, MIPI_CSI2_DT_RAW10),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGRBG10_1X10, SGRBG10_1X10, RAW10, 0, MIPI_CSI2_DT_RAW10),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SRGGB10_1X10, SRGGB10_1X10, RAW10, 0, MIPI_CSI2_DT_RAW10),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SBGGR12_1X12, SBGGR12_1X12, RAW12, 0, MIPI_CSI2_DT_RAW12),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGBRG12_1X12, SGBRG12_1X12, RAW12, 0, MIPI_CSI2_DT_RAW12),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGRBG12_1X12, SGRBG12_1X12, RAW12, 0, MIPI_CSI2_DT_RAW12),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SRGGB12_1X12, SRGGB12_1X12, RAW12, 0, MIPI_CSI2_DT_RAW12),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SBGGR14_1X14, SBGGR14_1X14, RAW14, 0, MIPI_CSI2_DT_RAW14),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGBRG14_1X14, SGBRG14_1X14, RAW14, 0, MIPI_CSI2_DT_RAW14),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SGRBG14_1X14, SGRBG14_1X14, RAW14, 0, MIPI_CSI2_DT_RAW14),
+ PIXMAP_SINK_SRC_PRCR_SWAP(SRGGB14_1X14, SRGGB14_1X14, RAW14, 0, MIPI_CSI2_DT_RAW14),
/* JPEG */
- PIXMAP_SINK_SRC_PRCR_SWAP(JPEG_1X8, JPEG_1X8, BYTE_STREAM, 0),
+ PIXMAP_SINK_SRC_PRCR_SWAP(JPEG_1X8, JPEG_1X8, BYTE_STREAM, 0, 0),
};
/*
@@ -260,8 +296,8 @@ static int dcmipp_inp_set_fmt(struct v4l2_subdev *sd,
return 0;
}
-static int dcmipp_inp_configure(struct dcmipp_inp_device *inp,
- struct v4l2_subdev_state *state)
+static int dcmipp_inp_configure_parallel(struct dcmipp_inp_device *inp,
+ struct v4l2_subdev_state *state)
{
u32 val = 0;
const struct dcmipp_inp_pix_map *vpix;
@@ -315,6 +351,52 @@ static int dcmipp_inp_configure(struct dcmipp_inp_device *inp,
reg_write(inp, DCMIPP_PRCR, val);
+ /* Select the DCMIPP parallel interface */
+ reg_write(inp, DCMIPP_CMCR, 0);
+
+ /* Enable parallel interface */
+ reg_set(inp, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+
+ return 0;
+}
+
+static int dcmipp_inp_configure_csi(struct dcmipp_inp_device *inp,
+ struct v4l2_subdev_state *state)
+{
+ const struct dcmipp_inp_pix_map *vpix;
+ struct v4l2_mbus_framefmt *sink_fmt;
+ struct v4l2_mbus_framefmt *src_fmt;
+
+ /* Get format information */
+ sink_fmt = v4l2_subdev_state_get_format(state, 0);
+ src_fmt = v4l2_subdev_state_get_format(state, 1);
+
+ vpix = dcmipp_inp_pix_map_by_code(sink_fmt->code, src_fmt->code);
+ if (!vpix) {
+ dev_err(inp->dev, "Invalid sink/src format configuration\n");
+ return -EINVAL;
+ }
+
+ /* Apply configuration on each input pipe */
+ reg_clear(inp, DCMIPP_P0FSCR,
+ DCMIPP_P0FSCR_DTMODE_MASK | DCMIPP_P0FSCR_DTIDA_MASK);
+
+ /* In case of JPEG we don't know the DT so we allow all data */
+ /*
+ * TODO - check instead dt == 0 for the time being to allow other
+ * unknown data-type
+ */
+ if (!vpix->dt)
+ reg_set(inp, DCMIPP_P0FSCR,
+ DCMIPP_P0FSCR_DTMODE_ALLDT << DCMIPP_P0FSCR_DTMODE_SHIFT);
+ else
+ reg_set(inp, DCMIPP_P0FSCR,
+ vpix->dt << DCMIPP_P0FSCR_DTIDA_SHIFT |
+ DCMIPP_P0FSCR_DTMODE_DTIDA);
+
+ /* Select the DCMIPP CSI interface */
+ reg_write(inp, DCMIPP_CMCR, DCMIPP_CMCR_INSEL);
+
return 0;
}
@@ -326,7 +408,7 @@ static int dcmipp_inp_enable_streams(struct v4l2_subdev *sd,
container_of(sd, struct dcmipp_inp_device, sd);
struct v4l2_subdev *s_subdev;
struct media_pad *s_pad;
- int ret;
+ int ret = 0;
/* Get source subdev */
s_pad = media_pad_remote_pad_first(&sd->entity.pads[0]);
@@ -334,13 +416,14 @@ static int dcmipp_inp_enable_streams(struct v4l2_subdev *sd,
return -EINVAL;
s_subdev = media_entity_to_v4l2_subdev(s_pad->entity);
- ret = dcmipp_inp_configure(inp);
+ if (inp->ved.bus_type == V4L2_MBUS_PARALLEL ||
+ inp->ved.bus_type == V4L2_MBUS_BT656)
+ ret = dcmipp_inp_configure_parallel(inp, state);
+ else if (inp->ved.bus_type == V4L2_MBUS_CSI2_DPHY)
+ ret = dcmipp_inp_configure_csi(inp, state);
if (ret)
return ret;
- /* Enable parallel interface */
- reg_set(inp, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
-
ret = v4l2_subdev_enable_streams(s_subdev, s_pad->index, BIT_ULL(0));
if (ret < 0) {
dev_err(inp->dev,
@@ -374,8 +457,11 @@ static int dcmipp_inp_disable_streams(struct v4l2_subdev *sd,
return ret;
}
- /* Disable parallel interface */
- reg_clear(inp, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+ if (inp->ved.bus_type == V4L2_MBUS_PARALLEL ||
+ inp->ved.bus_type == V4L2_MBUS_BT656) {
+ /* Disable parallel interface */
+ reg_clear(inp, DCMIPP_PRCR, DCMIPP_PRCR_ENABLE);
+ }
return 0;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 08/15] media: stm32: dcmipp: add bayer 10~14 bits formats
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (6 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 07/15] media: stm32: dcmipp: add support for csi input into dcmipp-input Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 09/15] media: stm32: dcmipp: add 1X16 RGB / YUV formats support Alain Volmat
` (7 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Add support for bayer formats from 10 to 14 bits.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 12 ++++++++++++
.../media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c | 12 ++++++++++++
2 files changed, 24 insertions(+)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
index 48596592bfd5..d6fad99e44bb 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
@@ -65,6 +65,18 @@ static const struct dcmipp_bytecap_pix_map dcmipp_bytecap_pix_map_list[] = {
PIXMAP_MBUS_PFMT(SGBRG8_1X8, SGBRG8),
PIXMAP_MBUS_PFMT(SGRBG8_1X8, SGRBG8),
PIXMAP_MBUS_PFMT(SRGGB8_1X8, SRGGB8),
+ PIXMAP_MBUS_PFMT(SBGGR10_1X10, SBGGR10),
+ PIXMAP_MBUS_PFMT(SGBRG10_1X10, SGBRG10),
+ PIXMAP_MBUS_PFMT(SGRBG10_1X10, SGRBG10),
+ PIXMAP_MBUS_PFMT(SRGGB10_1X10, SRGGB10),
+ PIXMAP_MBUS_PFMT(SBGGR12_1X12, SBGGR12),
+ PIXMAP_MBUS_PFMT(SGBRG12_1X12, SGBRG12),
+ PIXMAP_MBUS_PFMT(SGRBG12_1X12, SGRBG12),
+ PIXMAP_MBUS_PFMT(SRGGB12_1X12, SRGGB12),
+ PIXMAP_MBUS_PFMT(SBGGR14_1X14, SBGGR14),
+ PIXMAP_MBUS_PFMT(SGBRG14_1X14, SGBRG14),
+ PIXMAP_MBUS_PFMT(SGRBG14_1X14, SGRBG14),
+ PIXMAP_MBUS_PFMT(SRGGB14_1X14, SRGGB14),
PIXMAP_MBUS_PFMT(JPEG_1X8, JPEG),
};
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
index a19c8235af56..72f1bb4c64ad 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
@@ -57,6 +57,18 @@ static const struct dcmipp_byteproc_pix_map dcmipp_byteproc_pix_map_list[] = {
PIXMAP_MBUS_BPP(SGBRG8_1X8, 1),
PIXMAP_MBUS_BPP(SGRBG8_1X8, 1),
PIXMAP_MBUS_BPP(SRGGB8_1X8, 1),
+ PIXMAP_MBUS_BPP(SBGGR10_1X10, 2),
+ PIXMAP_MBUS_BPP(SGBRG10_1X10, 2),
+ PIXMAP_MBUS_BPP(SGRBG10_1X10, 2),
+ PIXMAP_MBUS_BPP(SRGGB10_1X10, 2),
+ PIXMAP_MBUS_BPP(SBGGR12_1X12, 2),
+ PIXMAP_MBUS_BPP(SGBRG12_1X12, 2),
+ PIXMAP_MBUS_BPP(SGRBG12_1X12, 2),
+ PIXMAP_MBUS_BPP(SRGGB12_1X12, 2),
+ PIXMAP_MBUS_BPP(SBGGR14_1X14, 2),
+ PIXMAP_MBUS_BPP(SGBRG14_1X14, 2),
+ PIXMAP_MBUS_BPP(SGRBG14_1X14, 2),
+ PIXMAP_MBUS_BPP(SRGGB14_1X14, 2),
PIXMAP_MBUS_BPP(JPEG_1X8, 1),
};
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 09/15] media: stm32: dcmipp: add 1X16 RGB / YUV formats support
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (7 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 08/15] media: stm32: dcmipp: add bayer 10~14 bits formats Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 10/15] media: stm32: dcmipp: avoid duplicated format on enum in bytecap Alain Volmat
` (6 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Add 1X16 RGB & YUV formats support within bytecap & byteproc.
Slightly change the link_validate function to be able to validate
against either 1X16 or 2X8 variant of a format.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 23 ++++++++++++++++------
.../st/stm32/stm32-dcmipp/dcmipp-byteproc.c | 5 +++++
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
index d6fad99e44bb..99732d19dc4d 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
@@ -56,10 +56,15 @@ struct dcmipp_bytecap_pix_map {
static const struct dcmipp_bytecap_pix_map dcmipp_bytecap_pix_map_list[] = {
PIXMAP_MBUS_PFMT(RGB565_2X8_LE, RGB565),
+ PIXMAP_MBUS_PFMT(RGB565_1X16, RGB565),
PIXMAP_MBUS_PFMT(YUYV8_2X8, YUYV),
+ PIXMAP_MBUS_PFMT(YUYV8_1X16, YUYV),
PIXMAP_MBUS_PFMT(YVYU8_2X8, YVYU),
+ PIXMAP_MBUS_PFMT(YVYU8_1X16, YVYU),
PIXMAP_MBUS_PFMT(UYVY8_2X8, UYVY),
+ PIXMAP_MBUS_PFMT(UYVY8_1X16, UYVY),
PIXMAP_MBUS_PFMT(VYUY8_2X8, VYUY),
+ PIXMAP_MBUS_PFMT(VYUY8_1X16, VYUY),
PIXMAP_MBUS_PFMT(Y8_1X8, GREY),
PIXMAP_MBUS_PFMT(SBGGR8_1X8, SBGGR8),
PIXMAP_MBUS_PFMT(SGBRG8_1X8, SGBRG8),
@@ -819,8 +824,7 @@ static int dcmipp_bytecap_link_validate(struct media_link *link)
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
.pad = link->source->index,
};
- const struct dcmipp_bytecap_pix_map *vpix;
- int ret;
+ int ret, i;
ret = v4l2_subdev_call(source_sd, pad, get_fmt, NULL, &source_fmt);
if (ret < 0)
@@ -834,10 +838,17 @@ static int dcmipp_bytecap_link_validate(struct media_link *link)
return -EINVAL;
}
- vpix = dcmipp_bytecap_pix_map_by_pixelformat(vcap->format.pixelformat);
- if (source_fmt.format.code != vpix->code) {
- dev_err(vcap->dev, "Wrong mbus_code 0x%x, (0x%x expected)\n",
- vpix->code, source_fmt.format.code);
+ for (i = 0; i < ARRAY_SIZE(dcmipp_bytecap_pix_map_list); i++) {
+ if (dcmipp_bytecap_pix_map_list[i].pixelformat ==
+ vcap->format.pixelformat &&
+ dcmipp_bytecap_pix_map_list[i].code ==
+ source_fmt.format.code)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(dcmipp_bytecap_pix_map_list)) {
+ dev_err(vcap->dev, "mbus code 0x%x do not match capture device format (0x%x)\n",
+ vcap->format.pixelformat, source_fmt.format.code);
return -EINVAL;
}
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
index 72f1bb4c64ad..3c742a546441 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
@@ -48,10 +48,15 @@ struct dcmipp_byteproc_pix_map {
}
static const struct dcmipp_byteproc_pix_map dcmipp_byteproc_pix_map_list[] = {
PIXMAP_MBUS_BPP(RGB565_2X8_LE, 2),
+ PIXMAP_MBUS_BPP(RGB565_1X16, 2),
PIXMAP_MBUS_BPP(YUYV8_2X8, 2),
+ PIXMAP_MBUS_BPP(YUYV8_1X16, 2),
PIXMAP_MBUS_BPP(YVYU8_2X8, 2),
+ PIXMAP_MBUS_BPP(YVYU8_1X16, 2),
PIXMAP_MBUS_BPP(UYVY8_2X8, 2),
+ PIXMAP_MBUS_BPP(UYVY8_1X16, 2),
PIXMAP_MBUS_BPP(VYUY8_2X8, 2),
+ PIXMAP_MBUS_BPP(VYUY8_1X16, 2),
PIXMAP_MBUS_BPP(Y8_1X8, 1),
PIXMAP_MBUS_BPP(SBGGR8_1X8, 1),
PIXMAP_MBUS_BPP(SGBRG8_1X8, 1),
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 10/15] media: stm32: dcmipp: avoid duplicated format on enum in bytecap
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (8 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 09/15] media: stm32: dcmipp: add 1X16 RGB / YUV formats support Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 11/15] media: stm32: dcmipp: fill media ctl hw_revision field Alain Volmat
` (5 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Avoid duplication of enumerated pixelformat on the bytecap
video capture device. Indeed, since the bytecap format list
contains both CSI & parallel 16bits formats, ensure that same
pixelformat are not reported twice when performing enumeration
of supported formats.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 42 +++++++++++-----------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
index 99732d19dc4d..8f5f69a3afc4 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-bytecap.c
@@ -268,34 +268,34 @@ static int dcmipp_bytecap_enum_fmt_vid_cap(struct file *file, void *priv,
{
const struct dcmipp_bytecap_pix_map *vpix;
unsigned int index = f->index;
- unsigned int i;
+ unsigned int i, prev_pixelformat = 0;
- if (f->mbus_code) {
- /*
- * If a media bus code is specified, only enumerate formats
- * compatible with it.
- */
- for (i = 0; i < ARRAY_SIZE(dcmipp_bytecap_pix_map_list); i++) {
- vpix = &dcmipp_bytecap_pix_map_list[i];
- if (vpix->code != f->mbus_code)
- continue;
+ /*
+ * List up all formats (or only ones matching f->mbus_code), taking
+ * care of removing duplicated entries (due to support of both
+ * parallel & csi 16 bits formats
+ */
+ for (i = 0; i < ARRAY_SIZE(dcmipp_bytecap_pix_map_list); i++) {
+ vpix = &dcmipp_bytecap_pix_map_list[i];
+ /* Skip formats not matching requested mbus code */
+ if (f->mbus_code && vpix->code != f->mbus_code)
+ continue;
- if (index == 0)
- break;
+ /* Skip duplicated pixelformat */
+ if (vpix->pixelformat == prev_pixelformat)
+ continue;
- index--;
- }
+ prev_pixelformat = vpix->pixelformat;
- if (i == ARRAY_SIZE(dcmipp_bytecap_pix_map_list))
- return -EINVAL;
- } else {
- /* Otherwise, enumerate all formats. */
- if (f->index >= ARRAY_SIZE(dcmipp_bytecap_pix_map_list))
- return -EINVAL;
+ if (index == 0)
+ break;
- vpix = &dcmipp_bytecap_pix_map_list[f->index];
+ index--;
}
+ if (i == ARRAY_SIZE(dcmipp_bytecap_pix_map_list))
+ return -EINVAL;
+
f->pixelformat = vpix->pixelformat;
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 11/15] media: stm32: dcmipp: fill media ctl hw_revision field
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (9 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 10/15] media: stm32: dcmipp: avoid duplicated format on enum in bytecap Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP Alain Volmat
` (4 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Add hw_revision field information of the media controller so that
application can distinguish between variants of DCMIPP implementations.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
index 50b9b964fbc4..d2cc19bb40d7 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
@@ -87,6 +87,7 @@ struct dcmipp_pipeline_config {
size_t num_ents;
const struct dcmipp_ent_link *links;
size_t num_links;
+ u32 hw_revision;
};
/* --------------------------------------------------------------------------
@@ -122,11 +123,13 @@ static const struct dcmipp_ent_link stm32mp13_ent_links[] = {
MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
};
+#define DCMIPP_STM32MP13_VERR 0x10
static const struct dcmipp_pipeline_config stm32mp13_pipe_cfg = {
.ents = stm32mp13_ent_config,
.num_ents = ARRAY_SIZE(stm32mp13_ent_config),
.links = stm32mp13_ent_links,
- .num_links = ARRAY_SIZE(stm32mp13_ent_links)
+ .num_links = ARRAY_SIZE(stm32mp13_ent_links),
+ .hw_revision = DCMIPP_STM32MP13_VERR
};
#define LINK_FLAG_TO_STR(f) ((f) == 0 ? "" :\
@@ -496,6 +499,7 @@ static int dcmipp_probe(struct platform_device *pdev)
/* Initialize media device */
strscpy(dcmipp->mdev.model, DCMIPP_MDEV_MODEL_NAME,
sizeof(dcmipp->mdev.model));
+ dcmipp->mdev.hw_revision = pipe_cfg->hw_revision;
dcmipp->mdev.dev = &pdev->dev;
media_device_init(&dcmipp->mdev);
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (10 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 11/15] media: stm32: dcmipp: fill media ctl hw_revision field Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 13:41 ` Krzysztof Kozlowski
2024-10-08 11:18 ` [PATCH 13/15] media: stm32: dcmipp: add core support for the stm32mp25 Alain Volmat
` (3 subsequent siblings)
15 siblings, 1 reply; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Addition of the stm32mp25 compatible for the DCMIPP.
The stm32mp25 distinguish with the stm32mp13 by the fact that:
- supports also csi inputs in addition to parallel inputs
- requires an addition csi clock to be present
The commit also adds access-controllers, an optional property that
allows a peripheral to refer to one or more domain access controller(s).
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../devicetree/bindings/media/st,stm32-dcmipp.yaml | 53 +++++++++++++++++++---
1 file changed, 47 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
index 87731f3ce7bd..bda28fef0b78 100644
--- a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
+++ b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
@@ -10,9 +10,40 @@ maintainers:
- Hugues Fruchet <hugues.fruchet@foss.st.com>
- Alain Volmat <alain.volmat@foss.st.com>
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - st,stm32mp13-dcmipp
+ then:
+ properties:
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ maxItems: 1
+
+ port:
+ properties:
+ endpoint:
+ properties:
+ bus-type:
+ enum: [5, 6]
+ else:
+ properties:
+ clocks:
+ minItems: 2
+
+ clock-names:
+ minItems: 2
+
properties:
compatible:
- const: st,stm32mp13-dcmipp
+ enum:
+ - st,stm32mp13-dcmipp
+ - st,stm32mp25-dcmipp
reg:
maxItems: 1
@@ -21,11 +52,24 @@ properties:
maxItems: 1
clocks:
- maxItems: 1
+ items:
+ - description: bus clock
+ - description: csi clock
+ minItems: 1
+
+ clock-names:
+ items:
+ - const: kclk
+ - const: mclk
+ minItems: 1
resets:
maxItems: 1
+ access-controllers:
+ minItems: 1
+ maxItems: 2
+
port:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
@@ -39,7 +83,7 @@ properties:
properties:
bus-type:
- enum: [5, 6]
+ enum: [4, 5, 6]
default: 5
bus-width:
@@ -50,9 +94,6 @@ properties:
hsync-active: true
vsync-active: true
- required:
- - pclk-sample
-
required:
- compatible
- reg
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 13/15] media: stm32: dcmipp: add core support for the stm32mp25
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (11 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 14/15] arm64: dts: st: add csi & dcmipp node in stm32mp25 Alain Volmat
` (2 subsequent siblings)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
The stm32mp25 supports both parallel & csi inputs.
An additional clock control is necessary.
Skeleton of the subdev structures for the stm32mp25 is added,
identical for the time being to the stm32mp13 however more subdeves
will be added in further commits.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
.../platform/st/stm32/stm32-dcmipp/dcmipp-core.c | 98 ++++++++++++++++++----
1 file changed, 80 insertions(+), 18 deletions(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
index d2cc19bb40d7..0087f9017f02 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
@@ -40,6 +40,7 @@ struct dcmipp_device {
/* Hardware resources */
void __iomem *regs;
+ struct clk *mclk;
struct clk *kclk;
/* The pipeline configuration */
@@ -132,6 +133,40 @@ static const struct dcmipp_pipeline_config stm32mp13_pipe_cfg = {
.hw_revision = DCMIPP_STM32MP13_VERR
};
+static const struct dcmipp_ent_config stm32mp25_ent_config[] = {
+ {
+ .name = "dcmipp_input",
+ .init = dcmipp_inp_ent_init,
+ .release = dcmipp_inp_ent_release,
+ },
+ {
+ .name = "dcmipp_dump_postproc",
+ .init = dcmipp_byteproc_ent_init,
+ .release = dcmipp_byteproc_ent_release,
+ },
+ {
+ .name = "dcmipp_dump_capture",
+ .init = dcmipp_bytecap_ent_init,
+ .release = dcmipp_bytecap_ent_release,
+ },
+};
+
+static const struct dcmipp_ent_link stm32mp25_ent_links[] = {
+ DCMIPP_ENT_LINK(ID_INPUT, 1, ID_DUMP_BYTEPROC, 0,
+ MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
+ DCMIPP_ENT_LINK(ID_DUMP_BYTEPROC, 1, ID_DUMP_CAPTURE, 0,
+ MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE),
+};
+
+#define DCMIPP_STM32MP25_VERR 0x30
+static const struct dcmipp_pipeline_config stm32mp25_pipe_cfg = {
+ .ents = stm32mp25_ent_config,
+ .num_ents = ARRAY_SIZE(stm32mp25_ent_config),
+ .links = stm32mp25_ent_links,
+ .num_links = ARRAY_SIZE(stm32mp25_ent_links),
+ .hw_revision = DCMIPP_STM32MP25_VERR
+};
+
#define LINK_FLAG_TO_STR(f) ((f) == 0 ? "" :\
(f) == MEDIA_LNK_FL_ENABLED ? "ENABLED" :\
(f) == MEDIA_LNK_FL_IMMUTABLE ? "IMMUTABLE" :\
@@ -212,6 +247,7 @@ static int dcmipp_create_subdevs(struct dcmipp_device *dcmipp)
static const struct of_device_id dcmipp_of_match[] = {
{ .compatible = "st,stm32mp13-dcmipp", .data = &stm32mp13_pipe_cfg },
+ { .compatible = "st,stm32mp25-dcmipp", .data = &stm32mp25_pipe_cfg },
{ /* end node */ },
};
MODULE_DEVICE_TABLE(of, dcmipp_of_match);
@@ -261,13 +297,22 @@ static int dcmipp_graph_notify_bound(struct v4l2_async_notifier *notifier,
{
struct dcmipp_device *dcmipp = notifier_to_dcmipp(notifier);
unsigned int ret;
- int src_pad;
+ int src_pad, i;
struct dcmipp_ent_device *sink;
- struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_PARALLEL };
+ struct v4l2_fwnode_endpoint vep = { 0 };
struct fwnode_handle *ep;
+ enum v4l2_mbus_type supported_types[] = {
+ V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656, V4L2_MBUS_CSI2_DPHY
+ };
+ int supported_types_nb = ARRAY_SIZE(supported_types);
dev_dbg(dcmipp->dev, "Subdev \"%s\" bound\n", subdev->name);
+ /* Only MP25 supports CSI input */
+ if (!of_device_is_compatible(dcmipp->dev->of_node,
+ "st,stm32mp25-dcmipp"))
+ supported_types_nb--;
+
/*
* Link this sub-device to DCMIPP, it could be
* a parallel camera sensor or a CSI-2 to parallel bridge
@@ -284,21 +329,23 @@ static int dcmipp_graph_notify_bound(struct v4l2_async_notifier *notifier,
return -ENODEV;
}
- /* Check for parallel bus-type first, then bt656 */
- ret = v4l2_fwnode_endpoint_parse(ep, &vep);
- if (ret) {
- vep.bus_type = V4L2_MBUS_BT656;
+ /* Check for supported MBUS type */
+ for (i = 0; i < supported_types_nb; i++) {
+ vep.bus_type = supported_types[i];
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
- if (ret) {
- dev_err(dcmipp->dev, "Could not parse the endpoint\n");
- fwnode_handle_put(ep);
- return ret;
- }
+ if (!ret)
+ break;
}
fwnode_handle_put(ep);
- if (vep.bus.parallel.bus_width == 0) {
+ if (ret) {
+ dev_err(dcmipp->dev, "Could not parse the endpoint\n");
+ return ret;
+ }
+
+ if (vep.bus_type != V4L2_MBUS_CSI2_DPHY &&
+ vep.bus.parallel.bus_width == 0) {
dev_err(dcmipp->dev, "Invalid parallel interface bus-width\n");
return -ENODEV;
}
@@ -311,11 +358,13 @@ static int dcmipp_graph_notify_bound(struct v4l2_async_notifier *notifier,
return -ENODEV;
}
- /* Parallel input device detected, connect it to parallel subdev */
+ /* Connect input device to the dcmipp_input subdev */
sink = dcmipp->entity[ID_INPUT];
- sink->bus.flags = vep.bus.parallel.flags;
- sink->bus.bus_width = vep.bus.parallel.bus_width;
- sink->bus.data_shift = vep.bus.parallel.data_shift;
+ if (vep.bus_type != V4L2_MBUS_CSI2_DPHY) {
+ sink->bus.flags = vep.bus.parallel.flags;
+ sink->bus.bus_width = vep.bus.parallel.bus_width;
+ sink->bus.data_shift = vep.bus.parallel.data_shift;
+ }
sink->bus_type = vep.bus_type;
ret = media_create_pad_link(&subdev->entity, src_pad, sink->ent, 0,
MEDIA_LNK_FL_IMMUTABLE |
@@ -414,7 +463,7 @@ static int dcmipp_graph_init(struct dcmipp_device *dcmipp)
static int dcmipp_probe(struct platform_device *pdev)
{
struct dcmipp_device *dcmipp;
- struct clk *kclk;
+ struct clk *kclk, *mclk;
const struct dcmipp_pipeline_config *pipe_cfg;
struct reset_control *rstc;
int irq;
@@ -474,12 +523,20 @@ static int dcmipp_probe(struct platform_device *pdev)
return ret;
}
- kclk = devm_clk_get(&pdev->dev, NULL);
+ kclk = devm_clk_get(&pdev->dev, "kclk");
if (IS_ERR(kclk))
return dev_err_probe(&pdev->dev, PTR_ERR(kclk),
"Unable to get kclk\n");
dcmipp->kclk = kclk;
+ if (!of_device_is_compatible(pdev->dev.of_node, "st,stm32mp13-dcmipp")) {
+ mclk = devm_clk_get(&pdev->dev, "mclk");
+ if (IS_ERR(mclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(mclk),
+ "Unable to get mclk\n");
+ dcmipp->mclk = mclk;
+ }
+
dcmipp->entity = devm_kcalloc(&pdev->dev, dcmipp->pipe_cfg->num_ents,
sizeof(*dcmipp->entity), GFP_KERNEL);
if (!dcmipp->entity)
@@ -542,6 +599,7 @@ static int dcmipp_runtime_suspend(struct device *dev)
struct dcmipp_device *dcmipp = dev_get_drvdata(dev);
clk_disable_unprepare(dcmipp->kclk);
+ clk_disable_unprepare(dcmipp->mclk);
return 0;
}
@@ -551,6 +609,10 @@ static int dcmipp_runtime_resume(struct device *dev)
struct dcmipp_device *dcmipp = dev_get_drvdata(dev);
int ret;
+ ret = clk_prepare_enable(dcmipp->mclk);
+ if (ret)
+ dev_err(dev, "%s: Failed to prepare_enable mclk\n", __func__);
+
ret = clk_prepare_enable(dcmipp->kclk);
if (ret)
dev_err(dev, "%s: Failed to prepare_enable kclk\n", __func__);
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 14/15] arm64: dts: st: add csi & dcmipp node in stm32mp25
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (12 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 13/15] media: stm32: dcmipp: add core support for the stm32mp25 Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1 Alain Volmat
2024-10-08 14:56 ` [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Rob Herring (Arm)
15 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Add nodes describing the csi and dcmipp controllers handling the
camera pipeline on the stm32mp25x.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
arch/arm64/boot/dts/st/stm32mp251.dtsi | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
index 1167cf63d7e8..6f8cabf2c598 100644
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
@@ -518,6 +518,29 @@ i2c8: i2c@46040000 {
status = "disabled";
};
+ csi: csi@48020000 {
+ compatible = "st,stm32mp25-csi";
+ reg = <0x48020000 0x2000>;
+ interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&rcc CSI_R>;
+ clocks = <&rcc CK_KER_CSI>, <&rcc CK_KER_CSITXESC>,
+ <&rcc CK_KER_CSIPHY>;
+ clock-names = "pclk", "txesc", "csi2phy";
+ access-controllers = <&rifsc 86>;
+ status = "disabled";
+ };
+
+ dcmipp: dcmipp@48030000 {
+ compatible = "st,stm32mp25-dcmipp";
+ reg = <0x48030000 0x1000>;
+ interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&rcc DCMIPP_R>;
+ clocks = <&rcc CK_BUS_DCMIPP>, <&rcc CK_KER_CSI>;
+ clock-names = "kclk", "mclk";
+ access-controllers = <&rifsc 87>;
+ status = "disabled";
+ };
+
sdmmc1: mmc@48220000 {
compatible = "st,stm32mp25-sdmmc2", "arm,pl18x", "arm,primecell";
arm,primecell-periphid = <0x00353180>;
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (13 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 14/15] arm64: dts: st: add csi & dcmipp node in stm32mp25 Alain Volmat
@ 2024-10-08 11:18 ` Alain Volmat
2024-10-08 13:42 ` Krzysztof Kozlowski
2024-10-08 14:56 ` [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Rob Herring (Arm)
15 siblings, 1 reply; 24+ messages in thread
From: Alain Volmat @ 2024-10-08 11:18 UTC (permalink / raw)
To: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel
Cc: linux-media, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Alain Volmat
Enable the camera pipeline with a imx335 sensor connected to the
dcmipp via the csi interface.
Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
---
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 87 ++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
index 214191a8322b..599af4801d82 100644
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
@@ -27,6 +27,38 @@ chosen {
stdout-path = "serial0:115200n8";
};
+ clocks {
+ clk_ext_camera: clk-ext-camera {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ };
+ };
+
+ imx335_2v9: imx335-2v9 {
+ compatible = "regulator-fixed";
+ regulator-name = "imx335-avdd";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-always-on;
+ };
+
+ imx335_1v8: imx335-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "imx335-ovdd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ imx335_1v2: imx335-1v2 {
+ compatible = "regulator-fixed";
+ regulator-name = "imx335-dvdd";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x1 0x0>;
@@ -50,6 +82,40 @@ &arm_wdt {
status = "okay";
};
+&csi {
+ vdd-supply = <&scmi_vddcore>;
+ vdda18-supply = <&scmi_v1v8>;
+ status = "okay";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ csi_sink: endpoint {
+ remote-endpoint = <&imx335_ep>;
+ data-lanes = <0 1>;
+ bus-type = <4>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ csi_source: endpoint {
+ remote-endpoint = <&dcmipp_0>;
+ };
+ };
+ };
+};
+
+&dcmipp {
+ status = "okay";
+ port {
+ dcmipp_0: endpoint {
+ remote-endpoint = <&csi_source>;
+ bus-type = <4>;
+ };
+ };
+};
+
ðernet2 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <ð2_rgmii_pins_a>;
@@ -81,6 +147,27 @@ &i2c2 {
i2c-scl-falling-time-ns = <13>;
clock-frequency = <400000>;
status = "okay";
+
+ imx335: imx335@1a {
+ compatible = "sony,imx335";
+ reg = <0x1a>;
+ clocks = <&clk_ext_camera>;
+ avdd-supply = <&imx335_2v9>;
+ ovdd-supply = <&imx335_1v8>;
+ dvdd-supply = <&imx335_1v2>;
+ reset-gpios = <&gpioi 7 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
+ powerdown-gpios = <&gpioi 0 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
+ status = "okay";
+
+ port {
+ imx335_ep: endpoint {
+ remote-endpoint = <&csi_sink>;
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ link-frequencies = /bits/ 64 <594000000>;
+ };
+ };
+ };
};
&i2c8 {
--
2.25.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description
2024-10-08 11:18 ` [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description Alain Volmat
@ 2024-10-08 12:36 ` Rob Herring (Arm)
2024-10-08 13:23 ` Krzysztof Kozlowski
1 sibling, 0 replies; 24+ messages in thread
From: Rob Herring (Arm) @ 2024-10-08 12:36 UTC (permalink / raw)
To: Alain Volmat
Cc: Hans Verkuil, linux-media, devicetree, linux-stm32,
Mauro Carvalho Chehab, Maxime Coquelin, Conor Dooley,
Hugues Fruchet, linux-kernel, Philipp Zabel, Sakari Ailus,
Alexandre Torgue, linux-arm-kernel, Krzysztof Kozlowski
On Tue, 08 Oct 2024 13:18:04 +0200, Alain Volmat wrote:
> Addition of the stm32 csi controller driver
>
> Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> ---
> .../devicetree/bindings/media/st,stm32-csi.yaml | 129 +++++++++++++++++++++
> 1 file changed, 129 insertions(+)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/st,stm32-csi.example.dtb: csi@48020000: ports:port@0:endpoint:data-lanes:0: 0 is not of type 'array'
from schema $id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/media/st,stm32-csi.example.dtb: csi@48020000: ports:port@0:endpoint:data-lanes:1: 1 is not of type 'array'
from schema $id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20241008-csi_dcmipp_mp25-v1-2-e3fd0ed54b31@foss.st.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description
2024-10-08 11:18 ` [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description Alain Volmat
2024-10-08 12:36 ` Rob Herring (Arm)
@ 2024-10-08 13:23 ` Krzysztof Kozlowski
2024-11-05 7:42 ` Alain Volmat
1 sibling, 1 reply; 24+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 13:23 UTC (permalink / raw)
To: Alain Volmat
Cc: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-media,
linux-stm32, linux-arm-kernel, linux-kernel, devicetree
On Tue, Oct 08, 2024 at 01:18:04PM +0200, Alain Volmat wrote:
> Addition of the stm32 csi controller driver
This is supposed to be about hardware, not driver. Missing full stop.
>
> Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> ---
> .../devicetree/bindings/media/st,stm32-csi.yaml | 129 +++++++++++++++++++++
Use compatible as filename.
> 1 file changed, 129 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/media/st,stm32-csi.yaml b/Documentation/devicetree/bindings/media/st,stm32-csi.yaml
> new file mode 100644
> index 000000000000..71e7c51be58c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/st,stm32-csi.yaml
> @@ -0,0 +1,129 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: STMicroelectronics STM32 CSI controller
> +
> +description:
> + The STM32 CSI controller allows connecting a CSI based
> + camera to the DCMIPP camera pipeline.
> +
> +maintainers:
> + - Alain Volmat <alain.volmat@foss.st.com>
> +
> +properties:
> + compatible:
> + enum:
> + - st,stm32mp25-csi
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 3
> +
> + clock-names:
> + items:
> + - const: pclk
> + - const: txesc
> + - const: csi2phy
> +
> + resets:
> + maxItems: 1
> +
> + vdd-supply:
> + description: Digital core power supply (0.91V)
> +
> + vdda18-supply:
> + description: System analog power supply (1.8V)
> +
> + access-controllers:
> + minItems: 1
> + maxItems: 2
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> +
> + properties:
> + port@0:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> + description:
> + Input port node
> +
> + properties:
> + endpoint:
> + $ref: video-interfaces.yaml#
> + unevaluatedProperties: false
> +
> + properties:
> + data-lanes:
> + description:
> + Indicate the number of data-lanes and their mapping.
> +
> + items:
Drop
... and test your patches. Mailing list is not the place to test them.
Your machine is.
> + minItems: 1
> + items:
> + - const: 1
> + - const: 2
> +
> + required:
> + - data-lanes
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description:
> + Output port node
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - clocks
> + - clock-names
> + - resets
> + - ports
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP
2024-10-08 11:18 ` [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP Alain Volmat
@ 2024-10-08 13:41 ` Krzysztof Kozlowski
2024-11-05 7:43 ` Alain Volmat
0 siblings, 1 reply; 24+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 13:41 UTC (permalink / raw)
To: Alain Volmat
Cc: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-media,
linux-stm32, linux-arm-kernel, linux-kernel, devicetree
On Tue, Oct 08, 2024 at 01:18:14PM +0200, Alain Volmat wrote:
> Addition of the stm32mp25 compatible for the DCMIPP.
"Add"
See submitting patches.
> The stm32mp25 distinguish with the stm32mp13 by the fact that:
> - supports also csi inputs in addition to parallel inputs
> - requires an addition csi clock to be present
>
> The commit also adds access-controllers, an optional property that
"Add", see submitting patches.
> allows a peripheral to refer to one or more domain access controller(s).
>
> Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> ---
> .../devicetree/bindings/media/st,stm32-dcmipp.yaml | 53 +++++++++++++++++++---
> 1 file changed, 47 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
> index 87731f3ce7bd..bda28fef0b78 100644
> --- a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
> +++ b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
> @@ -10,9 +10,40 @@ maintainers:
> - Hugues Fruchet <hugues.fruchet@foss.st.com>
> - Alain Volmat <alain.volmat@foss.st.com>
>
> +allOf:
Please put allOf: like in example schema, so after required:.
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1
2024-10-08 11:18 ` [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1 Alain Volmat
@ 2024-10-08 13:42 ` Krzysztof Kozlowski
2024-11-05 7:45 ` Alain Volmat
0 siblings, 1 reply; 24+ messages in thread
From: Krzysztof Kozlowski @ 2024-10-08 13:42 UTC (permalink / raw)
To: Alain Volmat
Cc: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-media,
linux-stm32, linux-arm-kernel, linux-kernel, devicetree
On Tue, Oct 08, 2024 at 01:18:17PM +0200, Alain Volmat wrote:
> Enable the camera pipeline with a imx335 sensor connected to the
> dcmipp via the csi interface.
>
> Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> ---
> arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 87 ++++++++++++++++++++++++++++++
> 1 file changed, 87 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
> index 214191a8322b..599af4801d82 100644
> --- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
> +++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
> @@ -27,6 +27,38 @@ chosen {
> stdout-path = "serial0:115200n8";
> };
>
> + clocks {
> + clk_ext_camera: clk-ext-camera {
> + #clock-cells = <0>;
> + compatible = "fixed-clock";
> + clock-frequency = <24000000>;
> + };
> + };
> +
> + imx335_2v9: imx335-2v9 {
Please use name for all fixed regulators which matches current format
recommendation: 'regulator-[0-9]v[0-9]'
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml?h=v6.11-rc1#n46
> + compatible = "regulator-fixed";
> + regulator-name = "imx335-avdd";
> + regulator-min-microvolt = <2900000>;
> + regulator-max-microvolt = <2900000>;
> + regulator-always-on;
> + };
> +
> + imx335_1v8: imx335-1v8 {
> + compatible = "regulator-fixed";
> + regulator-name = "imx335-ovdd";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-always-on;
> + };
> +
> + imx335_1v2: imx335-1v2 {
> + compatible = "regulator-fixed";
> + regulator-name = "imx335-dvdd";
> + regulator-min-microvolt = <1200000>;
> + regulator-max-microvolt = <1200000>;
> + regulator-always-on;
> + };
> +
> memory@80000000 {
> device_type = "memory";
> reg = <0x0 0x80000000 0x1 0x0>;
> @@ -50,6 +82,40 @@ &arm_wdt {
> status = "okay";
> };
>
> +&csi {
> + vdd-supply = <&scmi_vddcore>;
> + vdda18-supply = <&scmi_v1v8>;
> + status = "okay";
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + port@0 {
> + reg = <0>;
> + csi_sink: endpoint {
> + remote-endpoint = <&imx335_ep>;
> + data-lanes = <0 1>;
> + bus-type = <4>;
> + };
> + };
> + port@1 {
> + reg = <1>;
> + csi_source: endpoint {
> + remote-endpoint = <&dcmipp_0>;
> + };
> + };
> + };
> +};
> +
> +&dcmipp {
> + status = "okay";
> + port {
> + dcmipp_0: endpoint {
> + remote-endpoint = <&csi_source>;
> + bus-type = <4>;
> + };
> + };
> +};
> +
> ðernet2 {
> pinctrl-names = "default", "sleep";
> pinctrl-0 = <ð2_rgmii_pins_a>;
> @@ -81,6 +147,27 @@ &i2c2 {
> i2c-scl-falling-time-ns = <13>;
> clock-frequency = <400000>;
> status = "okay";
> +
> + imx335: imx335@1a {
Node names should be generic. See also an explanation and list of
examples (not exhaustive) in DT specification:
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
> + compatible = "sony,imx335";
> + reg = <0x1a>;
> + clocks = <&clk_ext_camera>;
> + avdd-supply = <&imx335_2v9>;
> + ovdd-supply = <&imx335_1v8>;
> + dvdd-supply = <&imx335_1v2>;
> + reset-gpios = <&gpioi 7 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
> + powerdown-gpios = <&gpioi 0 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
> + status = "okay";
Why? Didi you disable it anywhere?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
` (14 preceding siblings ...)
2024-10-08 11:18 ` [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1 Alain Volmat
@ 2024-10-08 14:56 ` Rob Herring (Arm)
15 siblings, 0 replies; 24+ messages in thread
From: Rob Herring (Arm) @ 2024-10-08 14:56 UTC (permalink / raw)
To: Alain Volmat
Cc: linux-kernel, stable, Philipp Zabel, Alexandre Torgue,
linux-media, Hugues Fruchet, Mauro Carvalho Chehab,
Krzysztof Kozlowski, Maxime Coquelin, linux-stm32, Hans Verkuil,
Sakari Ailus, devicetree, Conor Dooley, linux-arm-kernel
On Tue, 08 Oct 2024 13:18:02 +0200, Alain Volmat wrote:
> This series introduces the camera pipeline support for the
> STM32MP25 SOC. The STM32MP25 has 3 pipelines, fed from a
> single camera input which can be either parallel or csi.
>
> This series adds the basic support for the 1st pipe (dump)
> which, in term of features is same as the one featured on
> the STM32MP13 SOC. It focuses on introduction of the
> CSI input stage for the DCMIPP, and the CSI specific new
> control code for the DCMIPP.
> One of the subdev of the DCMIPP, dcmipp_parallel is now
> renamed as dcmipp_input since it allows to not only control
> the parallel but also the csi interface.
>
> Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> ---
> Alain Volmat (15):
> media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value
> dt-bindings: media: addition of stm32 csi driver description
> media: stm32: csi: addition of the STM32 CSI driver
> media: stm32: dcmipp: use v4l2_subdev_is_streaming
> media: stm32: dcmipp: replace s_stream with enable/disable_streams
> media: stm32: dcmipp: rename dcmipp_parallel into dcmipp_input
> media: stm32: dcmipp: add support for csi input into dcmipp-input
> media: stm32: dcmipp: add bayer 10~14 bits formats
> media: stm32: dcmipp: add 1X16 RGB / YUV formats support
> media: stm32: dcmipp: avoid duplicated format on enum in bytecap
> media: stm32: dcmipp: fill media ctl hw_revision field
> dt-bindings: media: addition of stm32mp25 compatible of DCMIPP
> media: stm32: dcmipp: add core support for the stm32mp25
> arm64: dts: st: add csi & dcmipp node in stm32mp25
> arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1
>
> .../devicetree/bindings/media/st,stm32-csi.yaml | 129 +++
> .../devicetree/bindings/media/st,stm32-dcmipp.yaml | 53 +-
> MAINTAINERS | 8 +
> arch/arm64/boot/dts/st/stm32mp251.dtsi | 23 +
> arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 87 ++
> drivers/media/platform/st/stm32/Kconfig | 14 +
> drivers/media/platform/st/stm32/Makefile | 1 +
> drivers/media/platform/st/stm32/stm32-csi.c | 1150 ++++++++++++++++++++
> .../media/platform/st/stm32/stm32-dcmipp/Makefile | 2 +-
> .../st/stm32/stm32-dcmipp/dcmipp-bytecap.c | 128 ++-
> .../st/stm32/stm32-dcmipp/dcmipp-byteproc.c | 119 +-
> .../platform/st/stm32/stm32-dcmipp/dcmipp-common.h | 4 +-
> .../platform/st/stm32/stm32-dcmipp/dcmipp-core.c | 116 +-
> .../platform/st/stm32/stm32-dcmipp/dcmipp-input.c | 540 +++++++++
> .../st/stm32/stm32-dcmipp/dcmipp-parallel.c | 440 --------
> 15 files changed, 2238 insertions(+), 576 deletions(-)
> ---
> base-commit: 9852d85ec9d492ebef56dc5f229416c925758edc
> change-id: 20241007-csi_dcmipp_mp25-7779601f57da
>
> Best regards,
> --
> Alain Volmat <alain.volmat@foss.st.com>
>
>
>
My bot found new DTB warnings on the .dts files added or changed in this
series.
Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.
If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:
pip3 install dtschema --upgrade
New warnings running 'make CHECK_DTBS=y st/stm32mp257f-ev1.dtb' for 20241008-csi_dcmipp_mp25-v1-0-e3fd0ed54b31@foss.st.com:
arch/arm64/boot/dts/st/stm32mp257f-ev1.dtb: imx335@1a: 'powerdown-gpios' does not match any of the regexes: 'pinctrl-[0-9]+'
from schema $id: http://devicetree.org/schemas/media/i2c/sony,imx335.yaml#
arch/arm64/boot/dts/st/stm32mp257f-ev1.dtb: csi@48020000: ports:port@0:endpoint:data-lanes:0: 0 is not of type 'array'
from schema $id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
arch/arm64/boot/dts/st/stm32mp257f-ev1.dtb: csi@48020000: ports:port@0:endpoint:data-lanes:1: 1 is not of type 'array'
from schema $id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description
2024-10-08 13:23 ` Krzysztof Kozlowski
@ 2024-11-05 7:42 ` Alain Volmat
0 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-11-05 7:42 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-media,
linux-stm32, linux-arm-kernel, linux-kernel, devicetree
Hi Krzysztof,
On Tue, Oct 08, 2024 at 03:23:10PM +0200, Krzysztof Kozlowski wrote:
> On Tue, Oct 08, 2024 at 01:18:04PM +0200, Alain Volmat wrote:
> > Addition of the stm32 csi controller driver
>
> This is supposed to be about hardware, not driver. Missing full stop.
Ok, commit message corrected in the upcoming v2.
>
> >
> > Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> > ---
> > .../devicetree/bindings/media/st,stm32-csi.yaml | 129 +++++++++++++++++++++
>
> Use compatible as filename.
Fixed
>
> > 1 file changed, 129 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/media/st,stm32-csi.yaml b/Documentation/devicetree/bindings/media/st,stm32-csi.yaml
> > new file mode 100644
> > index 000000000000..71e7c51be58c
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/st,stm32-csi.yaml
> > @@ -0,0 +1,129 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/media/st,stm32-csi.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: STMicroelectronics STM32 CSI controller
> > +
> > +description:
> > + The STM32 CSI controller allows connecting a CSI based
> > + camera to the DCMIPP camera pipeline.
> > +
> > +maintainers:
> > + - Alain Volmat <alain.volmat@foss.st.com>
> > +
> > +properties:
> > + compatible:
> > + enum:
> > + - st,stm32mp25-csi
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + interrupts:
> > + maxItems: 1
> > +
> > + clocks:
> > + maxItems: 3
> > +
> > + clock-names:
> > + items:
> > + - const: pclk
> > + - const: txesc
> > + - const: csi2phy
> > +
> > + resets:
> > + maxItems: 1
> > +
> > + vdd-supply:
> > + description: Digital core power supply (0.91V)
> > +
> > + vdda18-supply:
> > + description: System analog power supply (1.8V)
> > +
> > + access-controllers:
> > + minItems: 1
> > + maxItems: 2
> > +
> > + ports:
> > + $ref: /schemas/graph.yaml#/properties/ports
> > +
> > + properties:
> > + port@0:
> > + $ref: /schemas/graph.yaml#/$defs/port-base
> > + unevaluatedProperties: false
> > + description:
> > + Input port node
> > +
> > + properties:
> > + endpoint:
> > + $ref: video-interfaces.yaml#
> > + unevaluatedProperties: false
> > +
> > + properties:
> > + data-lanes:
> > + description:
> > + Indicate the number of data-lanes and their mapping.
> > +
> > + items:
>
> Drop
Done
>
> ... and test your patches. Mailing list is not the place to test them.
> Your machine is.
I did, however my dtschema was too old hence not reporting the issue.
Once updated I now got the error reported and fixed that.
>
> > + minItems: 1
> > + items:
> > + - const: 1
> > + - const: 2
> > +
> > + required:
> > + - data-lanes
> > +
> > + port@1:
> > + $ref: /schemas/graph.yaml#/properties/port
> > + description:
> > + Output port node
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - interrupts
> > + - clocks
> > + - clock-names
> > + - resets
> > + - ports
>
> Best regards,
> Krzysztof
>
Regards,
Alain
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP
2024-10-08 13:41 ` Krzysztof Kozlowski
@ 2024-11-05 7:43 ` Alain Volmat
0 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-11-05 7:43 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-media,
linux-stm32, linux-arm-kernel, linux-kernel, devicetree
Hi Krzysztof,
On Tue, Oct 08, 2024 at 03:41:59PM +0200, Krzysztof Kozlowski wrote:
> On Tue, Oct 08, 2024 at 01:18:14PM +0200, Alain Volmat wrote:
> > Addition of the stm32mp25 compatible for the DCMIPP.
>
> "Add"
> See submitting patches.
Commit message corrected in the v2.
>
> > The stm32mp25 distinguish with the stm32mp13 by the fact that:
> > - supports also csi inputs in addition to parallel inputs
> > - requires an addition csi clock to be present
> >
> > The commit also adds access-controllers, an optional property that
>
> "Add", see submitting patches.
Here as well.
>
> > allows a peripheral to refer to one or more domain access controller(s).
> >
> > Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> > ---
> > .../devicetree/bindings/media/st,stm32-dcmipp.yaml | 53 +++++++++++++++++++---
> > 1 file changed, 47 insertions(+), 6 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
> > index 87731f3ce7bd..bda28fef0b78 100644
> > --- a/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
> > +++ b/Documentation/devicetree/bindings/media/st,stm32-dcmipp.yaml
> > @@ -10,9 +10,40 @@ maintainers:
> > - Hugues Fruchet <hugues.fruchet@foss.st.com>
> > - Alain Volmat <alain.volmat@foss.st.com>
> >
> > +allOf:
>
> Please put allOf: like in example schema, so after required:.
Done in v2.
>
> > + - if:
> > + properties:
> > + compatible:
> > + contains:
> > + enum:
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1
2024-10-08 13:42 ` Krzysztof Kozlowski
@ 2024-11-05 7:45 ` Alain Volmat
0 siblings, 0 replies; 24+ messages in thread
From: Alain Volmat @ 2024-11-05 7:45 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Hugues Fruchet, Mauro Carvalho Chehab, Maxime Coquelin,
Alexandre Torgue, Hans Verkuil, Sakari Ailus, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Philipp Zabel, linux-media,
linux-stm32, linux-arm-kernel, linux-kernel, devicetree
Hi Krzysztof,
On Tue, Oct 08, 2024 at 03:42:42PM +0200, Krzysztof Kozlowski wrote:
> On Tue, Oct 08, 2024 at 01:18:17PM +0200, Alain Volmat wrote:
> > Enable the camera pipeline with a imx335 sensor connected to the
> > dcmipp via the csi interface.
> >
> > Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
> > ---
> > arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 87 ++++++++++++++++++++++++++++++
> > 1 file changed, 87 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
> > index 214191a8322b..599af4801d82 100644
> > --- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
> > +++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
> > @@ -27,6 +27,38 @@ chosen {
> > stdout-path = "serial0:115200n8";
> > };
> >
> > + clocks {
> > + clk_ext_camera: clk-ext-camera {
> > + #clock-cells = <0>;
> > + compatible = "fixed-clock";
> > + clock-frequency = <24000000>;
> > + };
> > + };
> > +
> > + imx335_2v9: imx335-2v9 {
>
> Please use name for all fixed regulators which matches current format
> recommendation: 'regulator-[0-9]v[0-9]'
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml?h=v6.11-rc1#n46
Done in v2 for all 3 fixed-regulators.
>
> > + compatible = "regulator-fixed";
> > + regulator-name = "imx335-avdd";
> > + regulator-min-microvolt = <2900000>;
> > + regulator-max-microvolt = <2900000>;
> > + regulator-always-on;
> > + };
> > +
> > + imx335_1v8: imx335-1v8 {
> > + compatible = "regulator-fixed";
> > + regulator-name = "imx335-ovdd";
> > + regulator-min-microvolt = <1800000>;
> > + regulator-max-microvolt = <1800000>;
> > + regulator-always-on;
> > + };
> > +
> > + imx335_1v2: imx335-1v2 {
> > + compatible = "regulator-fixed";
> > + regulator-name = "imx335-dvdd";
> > + regulator-min-microvolt = <1200000>;
> > + regulator-max-microvolt = <1200000>;
> > + regulator-always-on;
> > + };
> > +
> > memory@80000000 {
> > device_type = "memory";
> > reg = <0x0 0x80000000 0x1 0x0>;
> > @@ -50,6 +82,40 @@ &arm_wdt {
> > status = "okay";
> > };
> >
> > +&csi {
> > + vdd-supply = <&scmi_vddcore>;
> > + vdda18-supply = <&scmi_v1v8>;
> > + status = "okay";
> > + ports {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + port@0 {
> > + reg = <0>;
> > + csi_sink: endpoint {
> > + remote-endpoint = <&imx335_ep>;
> > + data-lanes = <0 1>;
> > + bus-type = <4>;
> > + };
> > + };
> > + port@1 {
> > + reg = <1>;
> > + csi_source: endpoint {
> > + remote-endpoint = <&dcmipp_0>;
> > + };
> > + };
> > + };
> > +};
> > +
> > +&dcmipp {
> > + status = "okay";
> > + port {
> > + dcmipp_0: endpoint {
> > + remote-endpoint = <&csi_source>;
> > + bus-type = <4>;
> > + };
> > + };
> > +};
> > +
> > ðernet2 {
> > pinctrl-names = "default", "sleep";
> > pinctrl-0 = <ð2_rgmii_pins_a>;
> > @@ -81,6 +147,27 @@ &i2c2 {
> > i2c-scl-falling-time-ns = <13>;
> > clock-frequency = <400000>;
> > status = "okay";
> > +
> > + imx335: imx335@1a {
>
> Node names should be generic. See also an explanation and list of
> examples (not exhaustive) in DT specification:
> https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
Changed to camera@1a.
>
> > + compatible = "sony,imx335";
> > + reg = <0x1a>;
> > + clocks = <&clk_ext_camera>;
> > + avdd-supply = <&imx335_2v9>;
> > + ovdd-supply = <&imx335_1v8>;
> > + dvdd-supply = <&imx335_1v2>;
> > + reset-gpios = <&gpioi 7 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
> > + powerdown-gpios = <&gpioi 0 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
> > + status = "okay";
>
> Why? Didi you disable it anywhere?
status property dropped in v2. powerdown-gpios property dropped as
well since not necessary nor described in the sensor yaml.
reset-gpios polarity is as well corrected in v2, following an change
within the imx335 sensor.
>
> Best regards,
> Krzysztof
>
Regards,
Alain
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2024-11-05 7:48 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-08 11:18 [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Alain Volmat
2024-10-08 11:18 ` [PATCH 01/15] media: stm32: dcmipp: correct dma_set_mask_and_coherent mask value Alain Volmat
2024-10-08 11:18 ` [PATCH 02/15] dt-bindings: media: addition of stm32 csi driver description Alain Volmat
2024-10-08 12:36 ` Rob Herring (Arm)
2024-10-08 13:23 ` Krzysztof Kozlowski
2024-11-05 7:42 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 03/15] media: stm32: csi: addition of the STM32 CSI driver Alain Volmat
2024-10-08 11:18 ` [PATCH 04/15] media: stm32: dcmipp: use v4l2_subdev_is_streaming Alain Volmat
2024-10-08 11:18 ` [PATCH 05/15] media: stm32: dcmipp: replace s_stream with enable/disable_streams Alain Volmat
2024-10-08 11:18 ` [PATCH 06/15] media: stm32: dcmipp: rename dcmipp_parallel into dcmipp_input Alain Volmat
2024-10-08 11:18 ` [PATCH 07/15] media: stm32: dcmipp: add support for csi input into dcmipp-input Alain Volmat
2024-10-08 11:18 ` [PATCH 08/15] media: stm32: dcmipp: add bayer 10~14 bits formats Alain Volmat
2024-10-08 11:18 ` [PATCH 09/15] media: stm32: dcmipp: add 1X16 RGB / YUV formats support Alain Volmat
2024-10-08 11:18 ` [PATCH 10/15] media: stm32: dcmipp: avoid duplicated format on enum in bytecap Alain Volmat
2024-10-08 11:18 ` [PATCH 11/15] media: stm32: dcmipp: fill media ctl hw_revision field Alain Volmat
2024-10-08 11:18 ` [PATCH 12/15] dt-bindings: media: addition of stm32mp25 compatible of DCMIPP Alain Volmat
2024-10-08 13:41 ` Krzysztof Kozlowski
2024-11-05 7:43 ` Alain Volmat
2024-10-08 11:18 ` [PATCH 13/15] media: stm32: dcmipp: add core support for the stm32mp25 Alain Volmat
2024-10-08 11:18 ` [PATCH 14/15] arm64: dts: st: add csi & dcmipp node in stm32mp25 Alain Volmat
2024-10-08 11:18 ` [PATCH 15/15] arm64: dts: st: enable imx335/csi/dcmipp pipeline on stm32mp257f-ev1 Alain Volmat
2024-10-08 13:42 ` Krzysztof Kozlowski
2024-11-05 7:45 ` Alain Volmat
2024-10-08 14:56 ` [PATCH 00/15] media: stm32: introduction of CSI / DCMIPP for STM32MP25 Rob Herring (Arm)
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).