media: stm32: dcmi: only call s_stream on the source subdev

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>
This commit is contained in:
Alain Volmat 2023-07-21 14:03:15 +02:00 committed by Mauro Carvalho Chehab
parent 7d0e95eb82
commit 525011d84a
1 changed files with 14 additions and 49 deletions

View 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;
}