On Thu Dec 12 10:17:31 2024 +0100, Alain Volmat wrote:
> 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.vol...@foss.st.com>
> Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>

Patch committed.

Thanks,
Hans Verkuil

 .../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 689eb4c72e18..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, state);
+       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;
 }

Reply via email to