media: stm32: dcmi: only call s_stream on the source subdev
authorAlain Volmat <alain.volmat@foss.st.com>
Fri, 21 Jul 2023 12:03:15 +0000 (14:03 +0200)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Thu, 10 Aug 2023 05:58:36 +0000 (07:58 +0200)
Avoid calling s_stream on each subdev until reaching the sensor and
instead call s_stream on the source subdev only (which will in turn
do whatever needed to start the stream).

Signed-off-by: Alain Volmat <alain.volmat@foss.st.com>
Reviewed-by: Hugues FRUCHET <hugues.fruchet@foss.st.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
drivers/media/platform/st/stm32/stm32-dcmi.c

index b026876..8cb4fdc 100644 (file)
@@ -134,6 +134,7 @@ struct stm32_dcmi {
        struct video_device             *vdev;
        struct v4l2_async_notifier      notifier;
        struct v4l2_subdev              *source;
+       struct v4l2_subdev              *s_subdev;
        struct v4l2_format              fmt;
        struct v4l2_rect                crop;
        bool                            do_crop;
@@ -692,51 +693,6 @@ static int dcmi_pipeline_s_fmt(struct stm32_dcmi *dcmi,
        return 0;
 }
 
-static int dcmi_pipeline_s_stream(struct stm32_dcmi *dcmi, int state)
-{
-       struct media_entity *entity = &dcmi->vdev->entity;
-       struct v4l2_subdev *subdev;
-       struct media_pad *pad;
-       int ret;
-
-       /* Start/stop all entities within pipeline */
-       while (1) {
-               pad = &entity->pads[0];
-               if (!(pad->flags & MEDIA_PAD_FL_SINK))
-                       break;
-
-               pad = media_pad_remote_pad_first(pad);
-               if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
-                       break;
-
-               entity = pad->entity;
-               subdev = media_entity_to_v4l2_subdev(entity);
-
-               ret = v4l2_subdev_call(subdev, video, s_stream, state);
-               if (ret < 0 && ret != -ENOIOCTLCMD) {
-                       dev_err(dcmi->dev, "%s: \"%s\" failed to %s streaming (%d)\n",
-                               __func__, subdev->name,
-                               state ? "start" : "stop", ret);
-                       return ret;
-               }
-
-               dev_dbg(dcmi->dev, "\"%s\" is %s\n",
-                       subdev->name, state ? "started" : "stopped");
-       }
-
-       return 0;
-}
-
-static int dcmi_pipeline_start(struct stm32_dcmi *dcmi)
-{
-       return dcmi_pipeline_s_stream(dcmi, 1);
-}
-
-static void dcmi_pipeline_stop(struct stm32_dcmi *dcmi)
-{
-       dcmi_pipeline_s_stream(dcmi, 0);
-}
-
 static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
        struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq);
@@ -758,9 +714,12 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
                goto err_pm_put;
        }
 
-       ret = dcmi_pipeline_start(dcmi);
-       if (ret)
+       ret = v4l2_subdev_call(dcmi->s_subdev, video, s_stream, 1);
+       if (ret < 0) {
+               dev_err(dcmi->dev, "%s: Failed to start source subdev, error (%d)\n",
+                       __func__, ret);
                goto err_media_pipeline_stop;
+       }
 
        spin_lock_irq(&dcmi->irqlock);
 
@@ -862,7 +821,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
        return 0;
 
 err_pipeline_stop:
-       dcmi_pipeline_stop(dcmi);
+       v4l2_subdev_call(dcmi->s_subdev, video, s_stream, 0);
 
 err_media_pipeline_stop:
        video_device_pipeline_stop(dcmi->vdev);
@@ -889,8 +848,12 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
 {
        struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq);
        struct dcmi_buf *buf, *node;
+       int ret;
 
-       dcmi_pipeline_stop(dcmi);
+       ret = v4l2_subdev_call(dcmi->s_subdev, video, s_stream, 0);
+       if (ret < 0)
+               dev_err(dcmi->dev, "%s: Failed to stop source subdev, error (%d)\n",
+                       __func__, ret);
 
        video_device_pipeline_stop(dcmi->vdev);
 
@@ -1876,6 +1839,8 @@ static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier,
                dev_dbg(dcmi->dev, "DCMI is now linked to \"%s\"\n",
                        subdev->name);
 
+       dcmi->s_subdev = subdev;
+
        return ret;
 }