Commit 525011d8 authored by Alain Volmat's avatar Alain Volmat Committed by Mauro Carvalho Chehab
Browse files

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: default avatarAlain Volmat <alain.volmat@foss.st.com>
Reviewed-by: default avatarHugues FRUCHET <hugues.fruchet@foss.st.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent 7d0e95eb
Loading
Loading
Loading
Loading
+14 −49
Original line number Diff line number Diff line
@@ -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;
}