]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
media: staging: imx: configure src_mux in csi_start
authorMichael Tretter <m.tretter@pengutronix.de>
Fri, 7 Nov 2025 10:34:34 +0000 (11:34 +0100)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Wed, 25 Mar 2026 17:42:18 +0000 (18:42 +0100)
After media_pipeline_start() was called, the media graph is assumed to
be validated. It won't be validated again if a second stream starts.

The imx-media-csi driver, however, changes hardware configuration in the
link_validate() callback. This can result in started streams with
misconfigured hardware.

In the concrete example, the ipu2_csi1 is driven by a parallel video
input. After the media pipeline has been started with this
configuration, a second stream is configured to use ipu1_csi0 with
MIPI-CSI input from imx6-mipi-csi2. This may require the reconfiguration
of ipu1_csi0 with ipu_set_csi_src_mux(). Since the media pipeline is
already running, link_validate won't be called, and the ipu1_csi0 won't
be reconfigured. The resulting video is broken, because the ipu1_csi0 is
misconfigured, but no error is reported.

Move ipu_set_csi_src_mux from csi_link_validate to csi_start to ensure
that input to ipu1_csi0 is configured correctly when starting the
stream. This is a local reconfiguration in ipu1_csi0 and is possible
while the media pipeline is running.

Since csi_start() is called with priv->lock already locked,
csi_set_src() must not lock priv->lock again. Thus, the mutex_lock() is
dropped.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
Fixes: 4a34ec8e470c ("[media] media: imx: Add CSI subdev driver")
Cc: stable@vger.kernel.org
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/staging/media/imx/imx-media-csi.c

index dc594b286f733e050a3c743e8e588693fcd86fb0..ef22a083f8eb1e6bca54e59b317ef9f631711674 100644 (file)
@@ -744,6 +744,28 @@ static int csi_setup(struct csi_priv *priv,
        return 0;
 }
 
+static void csi_set_src(struct csi_priv *priv,
+                       struct v4l2_mbus_config *mbus_cfg)
+{
+       bool is_csi2;
+
+       is_csi2 = !is_parallel_bus(mbus_cfg);
+       if (is_csi2) {
+               /*
+                * NOTE! It seems the virtual channels from the mipi csi-2
+                * receiver are used only for routing by the video mux's,
+                * or for hard-wired routing to the CSI's. Once the stream
+                * enters the CSI's however, they are treated internally
+                * in the IPU as virtual channel 0.
+                */
+               ipu_csi_set_mipi_datatype(priv->csi, 0,
+                                         &priv->format_mbus[CSI_SINK_PAD]);
+       }
+
+       /* select either parallel or MIPI-CSI2 as input to CSI */
+       ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);
+}
+
 static int csi_start(struct csi_priv *priv)
 {
        struct v4l2_mbus_config mbus_cfg = { .type = 0 };
@@ -760,6 +782,8 @@ static int csi_start(struct csi_priv *priv)
        input_fi = &priv->frame_interval[CSI_SINK_PAD];
        output_fi = &priv->frame_interval[priv->active_output_pad];
 
+       csi_set_src(priv, &mbus_cfg);
+
        /* start upstream */
        ret = v4l2_subdev_call(priv->src_sd, video, s_stream, 1);
        ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
@@ -1130,7 +1154,6 @@ static int csi_link_validate(struct v4l2_subdev *sd,
 {
        struct csi_priv *priv = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_config mbus_cfg = { .type = 0 };
-       bool is_csi2;
        int ret;
 
        ret = v4l2_subdev_link_validate_default(sd, link,
@@ -1145,25 +1168,6 @@ static int csi_link_validate(struct v4l2_subdev *sd,
                return ret;
        }
 
-       mutex_lock(&priv->lock);
-
-       is_csi2 = !is_parallel_bus(&mbus_cfg);
-       if (is_csi2) {
-               /*
-                * NOTE! It seems the virtual channels from the mipi csi-2
-                * receiver are used only for routing by the video mux's,
-                * or for hard-wired routing to the CSI's. Once the stream
-                * enters the CSI's however, they are treated internally
-                * in the IPU as virtual channel 0.
-                */
-               ipu_csi_set_mipi_datatype(priv->csi, 0,
-                                         &priv->format_mbus[CSI_SINK_PAD]);
-       }
-
-       /* select either parallel or MIPI-CSI2 as input to CSI */
-       ipu_set_csi_src_mux(priv->ipu, priv->csi_id, is_csi2);
-
-       mutex_unlock(&priv->lock);
        return ret;
 }