lkml.org 
[lkml]   [2024]   [Jan]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [RFC PATCH] media: v4l: implement virtual channels
From
Hi!

On 10/01/2024 14:51, Cosmin Tanislav wrote:
> With experimental support for multiple streams per pad being added, the
> pieces are in place to support a virtual channel id per stream.
>
> This is necessary because stream ids cannot be directly mapped to a virtual
> channel id, since the same virtual channel id can be assigned to multiple
> streams of data, each with a different data type.
>
> To implement this, the following steps have been taken.
>
> Add subdev ioctls for getting and setting the virtual channel for a
> specific pad and stream.
>
> Add pad .get_vc() and .set_vc() ops.
>
> Add the virtual channel to the stream config in V4L2 subdev central state.
>
> Add a default .get_vc() implementation that retrieves the virtual channel
> from the central state, or, if that is not supported, default to virtual
> channel 0.

Why do you need this?

The design idea with streams was that the streams are not tied to CSI-2
streams (or to any specific HW). The CSI-2 virtual channels should be
handled by the drivers internally, and they should not be visible to the
userspace at all.

Tomi

> Signed-off-by: Cosmin Tanislav <demonsingur@gmail.com>
> ---
> drivers/media/v4l2-core/v4l2-subdev.c | 57 +++++++++++++++++++++++++++
> include/media/v4l2-subdev.h | 39 ++++++++++++++++++
> include/uapi/linux/v4l2-subdev.h | 18 +++++++++
> 3 files changed, 114 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
> index be86b906c985..8945bfd0fe12 100644
> --- a/drivers/media/v4l2-core/v4l2-subdev.c
> +++ b/drivers/media/v4l2-core/v4l2-subdev.c
> @@ -535,6 +535,9 @@ subdev_ioctl_get_state(struct v4l2_subdev *sd, struct v4l2_subdev_fh *subdev_fh,
> case VIDIOC_SUBDEV_S_ROUTING:
> which = ((struct v4l2_subdev_routing *)arg)->which;
> break;
> + case VIDIOC_SUBDEV_G_VC:
> + case VIDIOC_SUBDEV_S_VC:
> + which = ((struct v4l2_subdev_vc *)arg)->which;
> }
>
> return which == V4L2_SUBDEV_FORMAT_TRY ?
> @@ -969,6 +972,26 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
> routing->which, &krouting);
> }
>
> + case VIDIOC_SUBDEV_G_VC: {
> + struct v4l2_subdev_vc *vc = arg;
> +
> + if (!client_supports_streams)
> + vc->stream = 0;
> +
> + memset(vc->reserved, 0, sizeof(vc->reserved));
> + return v4l2_subdev_call(sd, pad, get_vc, state, vc);
> + }
> +
> + case VIDIOC_SUBDEV_S_VC: {
> + struct v4l2_subdev_vc *vc = arg;
> +
> + if (!client_supports_streams)
> + vc->stream = 0;
> +
> + memset(vc->reserved, 0, sizeof(vc->reserved));
> + return v4l2_subdev_call(sd, pad, set_vc, state, vc);
> + }
> +
> case VIDIOC_SUBDEV_G_CLIENT_CAP: {
> struct v4l2_subdev_client_capability *client_cap = arg;
>
> @@ -1602,6 +1625,20 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
> }
> EXPORT_SYMBOL_GPL(v4l2_subdev_get_fmt);
>
> +int v4l2_subdev_get_vc(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
> + struct v4l2_subdev_vc *vc)
> +{
> + u32 vc_id = 0;
> +
> + if (sd->flags & V4L2_SUBDEV_FL_STREAMS)
> + vc_id = v4l2_subdev_state_get_stream_vc(state, vc->pad, vc->stream);
> +
> + vc->vc = vc_id;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_subdev_get_vc);
> +
> int v4l2_subdev_set_routing(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> const struct v4l2_subdev_krouting *routing)
> @@ -1745,6 +1782,26 @@ v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state,
> }
> EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_compose);
>
> +u32 v4l2_subdev_state_get_stream_vc(struct v4l2_subdev_state *state,
> + unsigned int pad, u32 stream)
> +{
> + struct v4l2_subdev_stream_configs *stream_configs;
> + unsigned int i;
> +
> + lockdep_assert_held(state->lock);
> +
> + stream_configs = &state->stream_configs;
> +
> + for (i = 0; i < stream_configs->num_configs; ++i) {
> + if (stream_configs->configs[i].pad == pad &&
> + stream_configs->configs[i].stream == stream)
> + return stream_configs->configs[i].vc;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_vc);
> +
> int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing,
> u32 pad, u32 stream, u32 *other_pad,
> u32 *other_stream)
> diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
> index c1f90c1223a7..ed1fdd79c2bb 100644
> --- a/include/media/v4l2-subdev.h
> +++ b/include/media/v4l2-subdev.h
> @@ -722,6 +722,7 @@ struct v4l2_subdev_stream_config {
> u32 stream;
> bool enabled;
>
> + u32 vc;
> struct v4l2_mbus_framefmt fmt;
> struct v4l2_rect crop;
> struct v4l2_rect compose;
> @@ -858,6 +859,12 @@ struct v4l2_subdev_pad_ops {
> int (*set_fmt)(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format);
> + int (*get_vc)(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_vc *vc);
> + int (*set_vc)(struct v4l2_subdev *sd,
> + struct v4l2_subdev_state *state,
> + struct v4l2_subdev_vc *vc);
> int (*get_selection)(struct v4l2_subdev *sd,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_selection *sel);
> @@ -1494,6 +1501,23 @@ v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)
> int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format);
>
> +/**
> + * v4l2_subdev_get_vc() - Fill virtual channel based on state
> + * @sd: subdevice
> + * @state: subdevice state
> + * @vc: pointer to &struct v4l2_subdev_vc
> + *
> + * Fill @vc->vc field based on the information in the @vc struct.
> + *
> + * This function can be used by the subdev drivers which support active state to
> + * implement v4l2_subdev_pad_ops.get_vc if the subdev driver does not need to
> + * do anything special in their get_vc op.
> + *
> + * Returns 0 on success, error value otherwise.
> + */
> +int v4l2_subdev_get_vc(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
> + struct v4l2_subdev_vc *vc);
> +
> /**
> * v4l2_subdev_set_routing() - Set given routing to subdev state
> * @sd: The subdevice
> @@ -1585,6 +1609,21 @@ struct v4l2_rect *
> v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state,
> unsigned int pad, u32 stream);
>
> +/**
> + * v4l2_subdev_state_get_stream_vc() - Get the virtual channel of a stream
> + * @state: subdevice state
> + * @pad: pad id
> + * @stream: stream id
> + *
> + * This returns the virtual channel for the given pad + stream in the
> + * subdev state.
> + *
> + * If the state does not contain the given pad + stream, 0 is returned.
> + */
> +u32
> +v4l2_subdev_state_get_stream_vc(struct v4l2_subdev_state *state,
> + unsigned int pad, u32 stream);
> +
> /**
> * v4l2_subdev_routing_find_opposite_end() - Find the opposite stream
> * @routing: routing used to find the opposite side
> diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
> index b383c2fe0cf3..8e90405bb1e6 100644
> --- a/include/uapi/linux/v4l2-subdev.h
> +++ b/include/uapi/linux/v4l2-subdev.h
> @@ -187,6 +187,22 @@ struct v4l2_subdev_capability {
> __u32 reserved[14];
> };
>
> +/**
> + * struct v4l2_subdev_vc - Pad-level virtual channel settings
> + * @which: format type (from enum v4l2_subdev_format_whence)
> + * @pad: pad number, as reported by the media API
> + * @vc: virtual channel
> + * @stream: stream number, defined in subdev routing
> + * @reserved: drivers and applications must zero this array
> + */
> +struct v4l2_subdev_vc {
> + __u32 which;
> + __u32 pad;
> + __u32 vc;
> + __u32 stream;
> + __u32 reserved[7];
> +};
> +
> /* The v4l2 sub-device video device node is registered in read-only mode. */
> #define V4L2_SUBDEV_CAP_RO_SUBDEV 0x00000001
>
> @@ -268,6 +284,8 @@ struct v4l2_subdev_client_capability {
> #define VIDIOC_SUBDEV_S_SELECTION _IOWR('V', 62, struct v4l2_subdev_selection)
> #define VIDIOC_SUBDEV_G_ROUTING _IOWR('V', 38, struct v4l2_subdev_routing)
> #define VIDIOC_SUBDEV_S_ROUTING _IOWR('V', 39, struct v4l2_subdev_routing)
> +#define VIDIOC_SUBDEV_G_VC _IOWR('V', 40, struct v4l2_subdev_vc)
> +#define VIDIOC_SUBDEV_S_VC _IOWR('V', 41, struct v4l2_subdev_vc)
> #define VIDIOC_SUBDEV_G_CLIENT_CAP _IOR('V', 101, struct v4l2_subdev_client_capability)
> #define VIDIOC_SUBDEV_S_CLIENT_CAP _IOWR('V', 102, struct v4l2_subdev_client_capability)
>


\
 
 \ /
  Last update: 2024-01-10 13:51    [W:0.052 / U:0.224 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site