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:
parent
7d0e95eb82
commit
525011d84a
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue