On Fri Aug 21 08:38:08 2026 +0200, Alain Volmat wrote:
> The STM32MP25 has CSI input and 2 additional pixel pipes in addition
> to the byte pipe. Each pipe can select which data to receive based
> on CSI VC/DT selection.
> The multi-stream support of DCMIPP will be added in a future commit,
> however, to start putting proper control method, the input subset
> has now 3 SRC pads, one per pipe available.
> Currently, and until multi-stream support is added, same data is
> sent to all pipes.
> 
> Signed-off-by: Alain Volmat <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 .../platform/st/stm32/stm32-dcmipp/dcmipp-input.c  | 86 +++++++++++++++-------
 1 file changed, 58 insertions(+), 28 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 75421035cfad..220e03ea38aa 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-input.c
@@ -43,12 +43,18 @@
 #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_P1FSCR  0x804
+#define DCMIPP_P2FSCR  0xC04
+#define DCMIPP_PXFSCR_DTMODE_MASK      GENMASK(17, 16)
+#define DCMIPP_PXFSCR_DTMODE_SHIFT     16
+#define DCMIPP_PXFSCR_DTMODE_DTIDA     0x00
 #define DCMIPP_P0FSCR_DTMODE_ALLDT     0x03
-#define DCMIPP_P0FSCR_DTIDA_MASK       GENMASK(5, 0)
-#define DCMIPP_P0FSCR_DTIDA_SHIFT      0
+#define DCMIPP_PXFSCR_DTIDA_MASK       GENMASK(5, 0)
+#define DCMIPP_PXFSCR_DTIDA_SHIFT      0
+
+#define DCMIPP_PXFSCR(a) (((a) == 0) ? DCMIPP_P0FSCR :\
+                         ((a) == 1) ? DCMIPP_P1FSCR :\
+                          DCMIPP_P2FSCR)
 
 #define IS_SINK(pad) (!(pad))
 #define IS_SRC(pad)  ((pad))
@@ -274,6 +280,7 @@ static int dcmipp_inp_set_fmt(struct v4l2_subdev *sd,
 {
        struct dcmipp_inp_device *inp = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *mf;
+       int pad;
 
        if (v4l2_subdev_is_streaming(sd))
                return -EBUSY;
@@ -298,9 +305,11 @@ static int dcmipp_inp_set_fmt(struct v4l2_subdev *sd,
 
        /* When setting the sink format, report that format on the src pad */
        if (IS_SINK(fmt->pad)) {
-               mf = v4l2_subdev_state_get_format(sd_state, 1);
-               *mf = fmt->format;
-               dcmipp_inp_adjust_fmt(inp, mf, 1);
+               for (pad = 1; pad < sd->entity.num_pads; pad++) {
+                       mf = v4l2_subdev_state_get_format(sd_state, pad);
+                       *mf = fmt->format;
+                       dcmipp_inp_adjust_fmt(inp, mf, pad);
+               }
        }
 
        return 0;
@@ -383,7 +392,8 @@ static int dcmipp_inp_configure_parallel(struct 
dcmipp_inp_device *inp,
 }
 
 static int dcmipp_inp_configure_csi(struct dcmipp_inp_device *inp,
-                                   struct v4l2_subdev_state *state)
+                                   struct v4l2_subdev_state *state,
+                                   u32 pad)
 {
        const struct dcmipp_inp_pix_map *vpix;
        struct v4l2_mbus_framefmt *sink_fmt;
@@ -391,7 +401,7 @@ static int dcmipp_inp_configure_csi(struct 
dcmipp_inp_device *inp,
 
        /* Get format information */
        sink_fmt = v4l2_subdev_state_get_format(state, 0);
-       src_fmt = v4l2_subdev_state_get_format(state, 1);
+       src_fmt = v4l2_subdev_state_get_format(state, pad);
 
        vpix = dcmipp_inp_pix_map_by_code(sink_fmt->code, src_fmt->code);
        if (!vpix) {
@@ -399,22 +409,28 @@ static int dcmipp_inp_configure_csi(struct 
dcmipp_inp_device *inp,
                return -EINVAL;
        }
 
-       /* Apply configuration on each input pipe */
-       reg_clear(inp, DCMIPP_P0FSCR,
-                 DCMIPP_P0FSCR_DTMODE_MASK | DCMIPP_P0FSCR_DTIDA_MASK);
+       /* Perform the configuration on the related pad/pipe */
+       reg_clear(inp, DCMIPP_PXFSCR(pad - 1),
+                 DCMIPP_PXFSCR_DTMODE_MASK | DCMIPP_PXFSCR_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
+       if (!vpix->dt) {
+               if (pad != 1) {
+                       dev_err(inp->dev, "JPEG only available on pipe 0\n");
+                       return -EINVAL;
+               }
+               /* Only available on Pipe #0 */
                reg_set(inp, DCMIPP_P0FSCR,
-                       vpix->dt << DCMIPP_P0FSCR_DTIDA_SHIFT |
-                       DCMIPP_P0FSCR_DTMODE_DTIDA);
+                       DCMIPP_P0FSCR_DTMODE_ALLDT << 
DCMIPP_PXFSCR_DTMODE_SHIFT);
+       } else {
+               reg_set(inp, DCMIPP_PXFSCR(pad - 1),
+                       vpix->dt << DCMIPP_PXFSCR_DTIDA_SHIFT |
+                       DCMIPP_PXFSCR_DTMODE_DTIDA);
+       }
 
        /* Select the DCMIPP CSI interface */
        reg_write(inp, DCMIPP_CMCR, DCMIPP_CMCR_INSEL);
@@ -432,20 +448,24 @@ static int dcmipp_inp_enable_streams(struct v4l2_subdev 
*sd,
        struct media_pad *s_pad;
        int ret = 0;
 
-       /* 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);
-
        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);
+               ret = dcmipp_inp_configure_csi(inp, state, pad);
        if (ret)
                return ret;
 
+       /* If there where no other pad enabled, then enable the source subdev */
+       if (sd->enabled_pads)
+               return 0;
+
+       /* 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_enable_streams(s_subdev, s_pad->index, BIT_ULL(0));
        if (ret < 0) {
                dev_err(inp->dev,
@@ -466,6 +486,10 @@ static int dcmipp_inp_disable_streams(struct v4l2_subdev 
*sd,
        struct media_pad *s_pad;
        int ret;
 
+       /* Don't do anything if there are still other pads enabled */
+       if ((sd->enabled_pads & ~BIT(pad)))
+               return 0;
+
        /* 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))
@@ -533,8 +557,10 @@ struct dcmipp_ent_device *dcmipp_inp_ent_init(const char 
*entity_name,
        struct dcmipp_inp_device *inp;
        const unsigned long pads_flag[] = {
                MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE,
+               MEDIA_PAD_FL_SOURCE, MEDIA_PAD_FL_SOURCE,
        };
        struct device *dev = dcmipp->dev;
+       u16 num_pads = ARRAY_SIZE(pads_flag);
        int ret;
 
        /* Allocate the inp struct */
@@ -543,18 +569,22 @@ struct dcmipp_ent_device *dcmipp_inp_ent_init(const char 
*entity_name,
                return ERR_PTR(-ENOMEM);
 
        inp->regs = dcmipp->regs;
+       inp->ved.dcmipp = dcmipp;
+
+       /* For DCMIPP without CSI2, there is only a single pipe hence 2 pads */
+       if (!inp->ved.dcmipp->pipe_cfg->has_csi2)
+               num_pads = 2;
 
        /* Initialize ved and sd */
        ret = dcmipp_ent_sd_register(&inp->ved, &inp->sd, &dcmipp->v4l2_dev,
                                     entity_name, MEDIA_ENT_F_VID_IF_BRIDGE,
-                                    ARRAY_SIZE(pads_flag), pads_flag,
+                                    num_pads, pads_flag,
                                     &dcmipp_inp_int_ops, &dcmipp_inp_ops,
                                     NULL, NULL);
        if (ret) {
                kfree(inp);
                return ERR_PTR(ret);
        }
-       inp->ved.dcmipp = dcmipp;
 
        inp->dev = dev;
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to