Re: [PATCH 7/8] media: qcom: camss: drive streams-aware transmitters through the streams API

From: Loic Poulain

Date: Mon Sep 14 2026 - 13:02:03 EST


Hi Hitesh,

On Mon, Sep 14, 2026 at 3:34 PM Hitesh Patel <hitesh@xxxxxxxxxxxxxx> wrote:
>
> video_start_streaming() and video_stop_streaming() drive every subdev
> of the pipeline through video.s_stream. That op is per subdev, and
> the core allows one transition per subdev, so a transmitter that is
> shared by two independent pipelines can only be started once and is
> stopped by the first pipeline that stops.
>
> A GMSL deserializer with two CSI-2 output ports, one camera routed to
> each, is exactly that case: the same subdev sits at the head of two
> pipelines that otherwise share nothing (each has its own CSIPHY, CSID
> and VFE). The second camera never starts, and stopping either one
> kills the other.
>
> Such transmitters implement the V4L2 streams API and advertise it
> with V4L2_SUBDEV_FL_STREAMS. For those, enable or disable only the
> streams routed to the source pad the pipeline arrived through, using
> v4l2_subdev_enable_streams()/v4l2_subdev_disable_streams(). The core
> refcounts enabled streams per pad, so the two pipelines no longer
> interfere. Enabling streams on a source pad propagates upstream to
> the sensor by itself, so the walk ends there rather than starting
> the rest of the chain a second time through s_stream.
>
> Subdevs without the flag keep using video.s_stream exactly as
> before.
>
> Signed-off-by: Hitesh Patel <hitesh@xxxxxxxxxxxxxx>

I would like to point out that Gjorgji has recently posted a CAMSS
stream API series [1]. Would that series address your use case, or are
there requirements that it does not cover? It would be good to
understand whether there is an opportunity for a common solution.

[1] https://lore.kernel.org/all/20260911062213.195007-1-gjorgji.rosikopulos@xxxxxxxxxxxxxxxx/


> ---
> .../media/platform/qcom/camss/camss-video.c | 56 +++++++++++++++++++
> 1 file changed, 56 insertions(+)
>
> diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c
> index 16c5f3748..90f22ce76 100644
> --- a/drivers/media/platform/qcom/camss/camss-video.c
> +++ b/drivers/media/platform/qcom/camss/camss-video.c
> @@ -249,6 +249,32 @@ static int video_prepare_streaming(struct vb2_queue *q)
> return ret;
> }
>
> +/*
> + * video_source_pad_streams - Streams routed to a subdev source pad
> + * @sd: Streams-aware subdevice
> + * @pad: Source pad index on @sd
> + *
> + * Return the mask of streams of the active routes ending on @pad.
> + */
> +static u64 video_source_pad_streams(struct v4l2_subdev *sd, u32 pad)
> +{
> + struct v4l2_subdev_state *state;
> + struct v4l2_subdev_route *route;
> + u64 mask = 0;
> +
> + state = v4l2_subdev_lock_and_get_active_state(sd);
> + if (!state)
> + return 0;
> +
> + for_each_active_route(&state->routing, route)
> + if (route->source_pad == pad)
> + mask |= BIT_ULL(route->source_stream);
> +
> + v4l2_subdev_unlock_state(state);
> +
> + return mask;
> +}
> +
> /*
> * video_subdev_set_stream - Start or stop a subdev of the pipeline
> * @video: CAMSS video device
> @@ -324,6 +350,20 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count)
> entity = pad->entity;
> subdev = media_entity_to_v4l2_subdev(entity);
>
> + if (subdev->flags & V4L2_SUBDEV_FL_STREAMS) {
> + u64 mask = video_source_pad_streams(subdev, pad->index);
> +
> + if (!mask)
> + break;
> +
> + ret = v4l2_subdev_enable_streams(subdev, pad->index,
> + mask);
> + if (ret && ret != -EALREADY)
> + goto error;
> +
> + break;
> + }
> +
> ret = video_subdev_set_stream(video, subdev, true);
> if (ret < 0 && ret != -ENOIOCTLCMD)
> goto error;
> @@ -362,6 +402,22 @@ static void video_stop_streaming(struct vb2_queue *q)
> entity = pad->entity;
> subdev = media_entity_to_v4l2_subdev(entity);
>
> + if (subdev->flags & V4L2_SUBDEV_FL_STREAMS) {
> + u64 mask = video_source_pad_streams(subdev, pad->index);
> +
> + if (!mask)
> + break;
> +
> + ret = v4l2_subdev_disable_streams(subdev, pad->index,
> + mask);
> + if (ret && ret != -EALREADY)
> + dev_err(video->camss->dev,
> + "Failed to disable streams %#llx on %s:%u: %d\n",
> + mask, subdev->name, pad->index, ret);
> +
> + break;
> + }
> +
> ret = video_subdev_set_stream(video, subdev, false);
> if (ret) {
> dev_err(video->camss->dev, "Video pipeline stop failed: %d\n", ret);
> --
> 2.43.0
>