On Fri Aug 21 08:38:07 2026 +0200, Alain Volmat wrote:
> When used with parallel input, the DCMIPP is expecting data to come
> in YUYV order (for all DUMP/MAIN and AUX pipes).  Not doing so will
> lead to bad color generated by the pipes when processing is done.
> The DUMP pipe is also doing by default a swap since, while it accepts
> YUYV data, it will by default generate UYVY data.
> 
> Current implementation is not correct for parallel input since it is
> performing a cycle swap on the input side and since the dump pipe is
> also internally doing a swap, the data captured from the dump pipe are
> correct, while the data captured from the main / aux pipes are not.
> 
> To correct this, only perform cycle swap when it is necessary, hence
> changing from YUYV to UYVY for example, and for all parallel YUV MBUS,
> add the P0PPCR based SWAPYUV to put back the data into the ordering of
> the input.
> 
> Keep previous behavior when the SWAPYUV is not available (such as
> stm32mp13).
> 
> Signed-off-by: Alain Volmat <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 .../st/stm32/stm32-dcmipp/dcmipp-byteproc.c        | 16 ++++++++++++-
 .../platform/st/stm32/stm32-dcmipp/dcmipp-common.h |  1 +
 .../platform/st/stm32/stm32-dcmipp/dcmipp-core.c   |  3 ++-
 .../platform/st/stm32/stm32-dcmipp/dcmipp-input.c  | 28 +++++++++++++++-------
 4 files changed, 38 insertions(+), 10 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 5fcd5123136f..f61618e12322 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-byteproc.c
@@ -25,6 +25,7 @@
 #define DCMIPP_P0SCSZR_HSIZE_SHIFT     0
 #define DCMIPP_P0SCSZR_VSIZE_SHIFT     16
 #define DCMIPP_P0PPCR  0x5c0
+#define DCMIPP_P0PPCR_SWAPYUV          BIT(0)
 #define DCMIPP_P0PPCR_BSM_1_2          0x1
 #define DCMIPP_P0PPCR_BSM_1_4          0x2
 #define DCMIPP_P0PPCR_BSM_2_4          0x3
@@ -428,9 +429,11 @@ static int dcmipp_byteproc_configure_scale_crop
        if (!vpix)
                return -EINVAL;
 
-       /* clear decimation/crop */
+       /* clear decimation/crop/swap yuv */
        reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_BSM_MASK);
        reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_LSM);
+       if (byteproc->ved.dcmipp->pipe_cfg->has_swapyuv)
+               reg_clear(byteproc, DCMIPP_P0PPCR, DCMIPP_P0PPCR_SWAPYUV);
        reg_write(byteproc, DCMIPP_P0SCSTR, 0);
        reg_write(byteproc, DCMIPP_P0SCSZR, 0);
 
@@ -451,6 +454,17 @@ static int dcmipp_byteproc_configure_scale_crop
        if (vprediv == 2)
                val |= DCMIPP_P0PPCR_LSM | DCMIPP_P0PPCR_OELS;
 
+       /*
+        * Perform a SWAP YUV if input is parallel since in this mode
+        * the DCMIPP will swap YUV by default
+        */
+       if (byteproc->ved.dcmipp->pipe_cfg->has_swapyuv &&
+           (sink_fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
+            sink_fmt->code == MEDIA_BUS_FMT_YVYU8_2X8 ||
+            sink_fmt->code == MEDIA_BUS_FMT_UYVY8_2X8 ||
+            sink_fmt->code == MEDIA_BUS_FMT_VYUY8_2X8))
+               val |= DCMIPP_P0PPCR_SWAPYUV;
+
        /* decimate using bytes and lines skipping */
        if (val) {
                reg_set(byteproc, DCMIPP_P0PPCR, val);
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 b94a9c87f56e..b491ce00c656 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-common.h
@@ -118,6 +118,7 @@ struct dcmipp_pipeline_config {
        u32 hw_revision;
        bool has_csi2;
        bool needs_mclk;
+       bool has_swapyuv;
 };
 
 /**
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 8f7e131238fc..a4dc9da70cd6 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c
@@ -108,7 +108,8 @@ static const struct dcmipp_pipeline_config 
stm32mp25_pipe_cfg = {
        .num_links      = ARRAY_SIZE(stm32mp25_ent_links),
        .hw_revision    = DCMIPP_STM32MP25_VERR,
        .has_csi2       = true,
-       .needs_mclk     = true
+       .needs_mclk     = true,
+       .has_swapyuv    = true
 };
 
 #define LINK_FLAG_TO_STR(f) ((f) == 0 ? "" :\
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 564f37e2e1dd..75421035cfad 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
@@ -80,15 +80,15 @@ static const struct dcmipp_inp_pix_map 
dcmipp_inp_pix_map_list[] = {
        PIXMAP_SINK_SRC_PRCR_SWAP(RGB888_3X8, RGB888_3X8, RGB888, 0, 
MIPI_CSI2_DT_RGB888),
        PIXMAP_SINK_SRC_PRCR_SWAP(RGB888_1X24, RGB888_1X24, RGB888, 0, 
MIPI_CSI2_DT_RGB888),
        /* YUV422 */
-       PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_2X8, YUYV8_2X8, YUV422, 1, 
MIPI_CSI2_DT_YUV422_8B),
+       PIXMAP_SINK_SRC_PRCR_SWAP(YUYV8_2X8, YUYV8_2X8, YUV422, 0, 
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(YUYV8_2X8, UYVY8_2X8, YUV422, 1, 
MIPI_CSI2_DT_YUV422_8B),
+       PIXMAP_SINK_SRC_PRCR_SWAP(UYVY8_2X8, UYVY8_2X8, YUV422, 0, 
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(UYVY8_2X8, YUYV8_2X8, YUV422, 1, 
MIPI_CSI2_DT_YUV422_8B),
+       PIXMAP_SINK_SRC_PRCR_SWAP(YVYU8_2X8, YVYU8_2X8, YUV422, 0, 
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_2X8, VYUY8_2X8, YUV422, 0, 
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, MIPI_CSI2_DT_RAW8),
@@ -356,8 +356,20 @@ static int dcmipp_inp_configure_parallel(struct 
dcmipp_inp_device *inp,
        val |= vpix->prcr_format << DCMIPP_PRCR_FORMAT_SHIFT;
 
        /* swap cycles */
-       if (vpix->prcr_swapcycles)
-               val |= DCMIPP_PRCR_SWAPCYCLES;
+       /*
+        * Table dcmipp_inp_pix_map_list take into consideration that SWAPYUV
+        * bit is available when dealing with 16bit YUV formats. If it is not
+        * available (such as on stm32mp13), swapcycle setting should be
+        * reversed
+        */
+       if (!inp->ved.dcmipp->pipe_cfg->has_swapyuv &&
+           (src_fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
+            src_fmt->code == MEDIA_BUS_FMT_YVYU8_2X8 ||
+            src_fmt->code == MEDIA_BUS_FMT_UYVY8_2X8 ||
+            src_fmt->code == MEDIA_BUS_FMT_VYUY8_2X8))
+               val |= (!vpix->prcr_swapcycles ? DCMIPP_PRCR_SWAPCYCLES : 0);
+       else
+               val |= (vpix->prcr_swapcycles ? DCMIPP_PRCR_SWAPCYCLES : 0);
 
        reg_write(inp, DCMIPP_PRCR, val);
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to