linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com,
	Jacopo Mondi <jacopo+renesas@jmondi.org>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	niklas.soderlund+renesas@ragnatech.se,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Hans Verkuil <hverkuil-cisco@xs4all.nl>,
	Pratyush Yadav <p.yadav@ti.com>
Subject: Re: [PATCH v10 00/38] v4l: subdev internal routing and streams
Date: Wed, 1 Dec 2021 08:26:14 +0200	[thread overview]
Message-ID: <d66254da-9b68-85fa-35ec-3fa1c1769592@ideasonboard.com> (raw)
In-Reply-To: <20211130141536.891878-1-tomi.valkeinen@ideasonboard.com>

[-- Attachment #1: Type: text/plain, Size: 1321 bytes --]

On 30/11/2021 16:14, Tomi Valkeinen wrote:
> Hi,
> 
> This is v10 of the multiplexed streams series. v8 can be found from:

That's supposed to be v9, not v8.

> https://lore.kernel.org/all/20211005085750.138151-1-tomi.valkeinen@ideasonboard.com/
> 
> I have pushed my work branch to:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git multistream/work-v10
> 
> which contains the patches in this series, along with subdev drivers
> using multiplexed streams.
> 
> I have also pushed v4l-utils changes to:
> 
> https://github.com/tomba/v4l-utils.git streams-review-v1
> 
> Changes to v9:
> 
> - Add V4L2_SUBDEV_CAP_MPLEXED flag
> - Use standard kmalloc and kmemdup for routes
> - Allow NULL as pad/stream param for v4l2_state_find_opposite_end
> - Add for_each_active_route
> - Use _BITUL() in uapi header
> - Rearrange struct v4l2_subdev_routing members to align on 64 bit
> - Renames:
> 	sd->state -> sd->active_state
> 	v4l2_state_find_opposite_end -> v4l2_subdev_routing_find_opposite_end
> 	v4l2_state_get_opposite_stream_format -> v4l2_subdev_state_get_opposite_stream_format
> 	v4l2_routing_simple_verify -> v4l2_subdev_routing_validate_1_to_1
> 	v4l2_subdev_validate_and_lock_state -> v4l2_subdev_lock_and_return_state
> - Doc & comment updates

To help reviews, here's the diff to the v8.

  Tomi

[-- Attachment #2: multistream-diff.txt --]
[-- Type: text/plain, Size: 22882 bytes --]

diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
index 410e03a29f2a..1d986e814b4e 100644
--- a/Documentation/driver-api/media/v4l2-subdev.rst
+++ b/Documentation/driver-api/media/v4l2-subdev.rst
@@ -525,9 +525,9 @@ Traditionally V4L2 subdev drivers maintained internal state for the active
 configuration for the subdev. This is often implemented as an array of struct
 v4l2_mbus_framefmt, one entry for each pad.
 
-In addition to the active configuration, each subdev filehandle has contained
-an array of struct v4l2_subdev_pad_config, managed by V4L2 core, which
-contains the TRY configuration.
+In addition to the active configuration, each subdev filehandle has an array of
+struct v4l2_subdev_pad_config, managed by V4L2 core, which contains the TRY
+configuration.
 
 To simplify the subdev drivers the V4L2 subdev API now optionally supports a
 centrally managed active configuration. A subdev driver must use
@@ -535,13 +535,13 @@ v4l2_subdev_init_finalize() to initialize the active state between calls to
 media_entity_pads_init() and v4l2_*_register_subdev(), and must call
 v4l2_subdev_cleanup() to free the state.
 
-The active state must be locked before access, and can be done with
+The active state must be locked before access, and that can be done with
 v4l2_subdev_lock_state() or v4l2_subdev_lock_active_state().
 
 The V4L2 core will pass either the TRY or ACTIVE state to various subdev ops.
-Unfortunately all the subdev drivers do not comply with this yet, and may pass
+Unfortunately not all the subdev drivers comply with this yet, and may pass
 NULL for the ACTIVE case. This is only a problem for subdev drivers which use
-the cetrally managed active state and are used in media pipelines with older
+the centrally managed active state and are used in media pipelines with older
 subdev drivers. In these cases the called subdev ops must also handle the NULL
 case. This can be easily managed by the use of
 v4l2_subdev_validate_and_lock_state() helper.
diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
index ea3efa97bb08..fd042afeddd6 100644
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst
@@ -508,7 +508,7 @@ Streams, multiplexed media pads and internal routing
 ----------------------------------------------------
 
 Commonly V4L2 subdevices support only separate video streams, that is, each
-link in the media grap and each pad in a subdevice passes through a single
+link in the media graph and each pad in a subdevice pass through a single
 video stream. Thus each pad contains a format configuration for that single
 stream. In some cases a subdev can do stream processing and split a stream
 into two or compose two streams into one, but the inputs and outputs for the
@@ -520,22 +520,22 @@ stream and a metadata stream, and a bridge subdev could route the streams
 from multiple input pads into a single output pad.
 
 Subdevice drivers that support multiplexed streams are compatible with
-non-multiplexed subdev drivers, but, of course, requires such a routing
-configuration where the link between those two types of drivers contain only
-a single stream.
+non-multiplexed subdev drivers, but, of course, require a routing configuration
+where the link between those two types of drivers contains only a single
+stream.
 
 Understanding streams
 ^^^^^^^^^^^^^^^^^^^^^
 
 A stream is a stream of content (e.g. pixel data or metadata) flowing through
-the media pipeline from a source (e.g. a sensor) towards the final sink
-(e.g. a receiver in a SoC). Each media link carries all the streams from
-one end of the link to the other, whereas subdevices have routing tables
-which describe how the incoming streams from sink pads are routed to the
-source pads.
+the media pipeline from a source (e.g. a sensor) towards the final sink(e.g. a
+receiver and demultiplexer in a SoC). Each media link carries all the streams
+from one end of the link to the other, and subdevices have routing tables which
+describe how the incoming streams from sink pads are routed to the source
+pads.
 
 A stream ID (often just "stream") is a media link-local identifier for a
-stream. In other words, configuration for a particular stream ID must exist
+stream. In other words, a configuration for a particular stream ID must exist
 on both sides of a media link, but another stream ID can be used for the same
 stream at the other side of the subdevice.
 
@@ -556,7 +556,8 @@ There are three steps in configuring the streams:
 Controller API <media_controller>`
 
 2) Routing. The routing table for the subdevice must be set with
-:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl.
+:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that
+setting the routing table will reset all the stream configurations.
 
 3) Configure streams. Each route endpoint must be configured
 with :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>`.
@@ -662,8 +663,8 @@ not differ from normal non-multiplexed media controller setup.
 After configuring the routing table, the next step is configuring the streams.
 This step is similar to configuring the pads in a non-multiplexed streams
 setup, with the difference that we need to configure each (pad, stream) pair
-(i.e. route endpoint), instead of just a pad.
+(i.e. route endpoint) instead of just a pad.
 
-Presuming there are no format conversions in the pipeline, the userspace needs
-to configure all the route endpoints using four formats (two pixel formats
-and two metadata formats) with VIDIOC_SUBDEV_S_FMT.
+A common way to accomplish this is to start from the sensors and propagate the
+configurations along the stream towards the receiver, using VIDIOC_SUBDEV_S_FMT
+to configure each stream endpoint in each subdev.
diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
index 41f4873c49f7..a0d9c79e162f 100644
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
@@ -41,19 +41,23 @@ The routing configuration determines the flows of data inside an entity.
 
 Drivers report their current routing tables using the
 ``VIDIOC_SUBDEV_G_ROUTING`` ioctl and application may enable or disable routes
-with the VIDIOC_SUBDEV_S_ROUTING ioctl, by adding or removing routes and setting
-or clearing the ``V4L2_SUBDEV_ROUTE_FL_ACTIVE`` flag of the  ``flags`` field of
-a struct :c:type:`v4l2_subdev_route`.
+with the ``VIDIOC_SUBDEV_S_ROUTING`` ioctl, by adding or removing routes and
+setting or clearing flags of the  ``flags`` field of a
+struct :c:type:`v4l2_subdev_route`.
+
+All stream configurations are reset when ``VIDIOC_SUBDEV_S_ROUTING`` is called. This
+means that the userspace mut reconfigure all streams after calling the ioctl
+with e.g. ``VIDIOC_SUBDEV_S_FMT``.
 
 A special case for routing are routes marked with
 ``V4L2_SUBDEV_ROUTE_FL_SOURCE`` flag. These routes are used to describe
 source endpoints on sensors and the sink fields are unused.
 
-When inspecting routes through VIDIOC_SUBDEV_G_ROUTING and the application
+When inspecting routes through ``VIDIOC_SUBDEV_G_ROUTING`` and the application
 provided ``num_routes`` is not big enough to contain all the available routes
 the subdevice exposes, drivers return the ENOSPC error code and adjust the
 value of the ``num_routes`` field. Application should then reserve enough memory
-for all the route entries and call VIDIOC_SUBDEV_G_ROUTING again.
+for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again.
 
 .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
 
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 2a64ff003e4b..dca2bea180ec 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -175,7 +175,7 @@ static int check_state_pad_stream(struct v4l2_subdev *sd,
 	 * We need to take the state lock to access the format, but as we then
 	 * have to unlock, nothing prevents someone changing the state before
 	 * this call thread enters the driver's op and the driver has the
-	 * change to lock the state.
+	 * chance to lock the state.
 	 */
 	v4l2_subdev_lock_state(state);
 
@@ -462,7 +462,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 
 		memset(cap->reserved, 0, sizeof(cap->reserved));
 		cap->version = LINUX_VERSION_CODE;
-		cap->capabilities = ro_subdev ? V4L2_SUBDEV_CAP_RO_SUBDEV : 0;
+		cap->capabilities =
+			(ro_subdev ? V4L2_SUBDEV_CAP_RO_SUBDEV : 0) |
+			((sd->flags & V4L2_SUBDEV_FL_MULTIPLEXED) ? V4L2_SUBDEV_CAP_MPLEXED : 0);
 
 		return 0;
 	}
@@ -1197,7 +1199,11 @@ int v4l2_subdev_link_validate(struct media_link *link)
 	if (ret)
 		goto free_source;
 
-	/* It is ok to have more source streams than sink streams */
+	/*
+	 * It is ok to have more source streams than sink streams as extra
+	 * source streams can just be ignored (i.e. they go nowhere), but extra
+	 * sink streams is an error.
+	 */
 	if (num_source_streams < num_sink_streams) {
 		dev_err(dev,
 			"Not enough source streams: %d < %d\n",
@@ -1358,7 +1364,7 @@ void __v4l2_subdev_state_free(struct v4l2_subdev_state *state)
 
 	mutex_destroy(&state->lock);
 
-	kvfree(state->routing.routes);
+	kfree(state->routing.routes);
 	kvfree(state->stream_configs.configs);
 	kvfree(state->pads);
 	kfree(state);
@@ -1403,7 +1409,7 @@ int __v4l2_subdev_init_finalize(struct v4l2_subdev *sd, const char *name,
 	if (IS_ERR(state))
 		return PTR_ERR(state);
 
-	sd->state = state;
+	sd->active_state = state;
 
 	return 0;
 }
@@ -1411,16 +1417,16 @@ EXPORT_SYMBOL_GPL(__v4l2_subdev_init_finalize);
 
 void v4l2_subdev_cleanup(struct v4l2_subdev *sd)
 {
-	__v4l2_subdev_state_free(sd->state);
-	sd->state = NULL;
+	__v4l2_subdev_state_free(sd->active_state);
+	sd->active_state = NULL;
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_cleanup);
 
 struct v4l2_subdev_state *v4l2_subdev_lock_active_state(struct v4l2_subdev *sd)
 {
-	mutex_lock(&sd->state->lock);
+	mutex_lock(&sd->active_state->lock);
 
-	return sd->state;
+	return sd->active_state;
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_lock_active_state);
 
@@ -1445,18 +1451,17 @@ int v4l2_subdev_set_routing(struct v4l2_subdev *sd,
 
 	lockdep_assert_held(&state->lock);
 
-	kvfree(dst->routes);
+	kfree(dst->routes);
 	dst->routes = NULL;
 	dst->num_routes = 0;
 
 	if (src->num_routes > 0) {
-		dst->routes = kvmalloc_array(src->num_routes,
-					     sizeof(*src->routes), GFP_KERNEL);
+		dst->routes = kmemdup(src->routes,
+				      src->num_routes * sizeof(*src->routes),
+				      GFP_KERNEL);
 		if (!dst->routes)
 			return -ENOMEM;
 
-		memcpy(dst->routes, src->routes,
-		       src->num_routes * sizeof(*src->routes));
 		dst->num_routes = src->num_routes;
 	}
 
@@ -1507,8 +1512,9 @@ v4l2_state_get_stream_format(struct v4l2_subdev_state *state, unsigned int pad,
 }
 EXPORT_SYMBOL_GPL(v4l2_state_get_stream_format);
 
-int v4l2_state_find_opposite_end(struct v4l2_subdev_krouting *routing, u32 pad,
-				 u32 stream, u32 *other_pad, u32 *other_stream)
+int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing,
+					  u32 pad, u32 stream, u32 *other_pad,
+					  u32 *other_stream)
 {
 	unsigned int i;
 
@@ -1517,37 +1523,41 @@ int v4l2_state_find_opposite_end(struct v4l2_subdev_krouting *routing, u32 pad,
 
 		if (route->source_pad == pad &&
 		    route->source_stream == stream) {
-			*other_pad = route->sink_pad;
-			*other_stream = route->sink_stream;
+			if (other_pad)
+				*other_pad = route->sink_pad;
+			if (other_stream)
+				*other_stream = route->sink_stream;
 			return 0;
 		}
 
 		if (route->sink_pad == pad && route->sink_stream == stream) {
-			*other_pad = route->source_pad;
-			*other_stream = route->source_stream;
+			if (other_pad)
+				*other_pad = route->source_pad;
+			if (other_stream)
+				*other_stream = route->source_stream;
 			return 0;
 		}
 	}
 
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(v4l2_state_find_opposite_end);
+EXPORT_SYMBOL_GPL(v4l2_subdev_routing_find_opposite_end);
 
 struct v4l2_mbus_framefmt *
-v4l2_state_get_opposite_stream_format(struct v4l2_subdev_state *state, u32 pad,
-				      u32 stream)
+v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state,
+					     u32 pad, u32 stream)
 {
 	u32 other_pad, other_stream;
 	int ret;
 
-	ret = v4l2_state_find_opposite_end(&state->routing, pad, stream,
-					   &other_pad, &other_stream);
+	ret = v4l2_subdev_routing_find_opposite_end(&state->routing, pad, stream,
+						    &other_pad, &other_stream);
 	if (ret)
 		return NULL;
 
 	return v4l2_state_get_stream_format(state, other_pad, other_stream);
 }
-EXPORT_SYMBOL_GPL(v4l2_state_get_opposite_stream_format);
+EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_opposite_stream_format);
 
 int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
 			struct v4l2_subdev_format *format)
@@ -1570,7 +1580,7 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_get_fmt);
 
-int v4l2_routing_simple_verify(const struct v4l2_subdev_krouting *routing)
+int v4l2_subdev_routing_validate_1_to_1(const struct v4l2_subdev_krouting *routing)
 {
 	unsigned int i, j;
 
@@ -1592,4 +1602,24 @@ int v4l2_routing_simple_verify(const struct v4l2_subdev_krouting *routing)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(v4l2_routing_simple_verify);
+EXPORT_SYMBOL_GPL(v4l2_subdev_routing_validate_1_to_1);
+
+struct v4l2_subdev_route *
+__v4l2_subdev_next_active_route(const struct v4l2_subdev_krouting *routing,
+				struct v4l2_subdev_route *route)
+{
+	if (route)
+		++route;
+	else
+		route = &routing->routes[0];
+
+	for (; route < routing->routes + routing->num_routes; ++route) {
+		if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+			continue;
+
+		return route;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(__v4l2_subdev_next_active_route);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 5e50f2ded653..9754913b34f8 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -687,6 +687,9 @@ struct v4l2_subdev_ir_ops {
  * This structure only needs to be passed to the pad op if the 'which' field
  * of the main argument is set to %V4L2_SUBDEV_FORMAT_TRY. For
  * %V4L2_SUBDEV_FORMAT_ACTIVE it is safe to pass %NULL.
+ *
+ * Note: This struct is also used in active state, and the try_ prefix is
+ * historical and to be removed.
  */
 struct v4l2_subdev_pad_config {
 	struct v4l2_mbus_framefmt try_fmt;
@@ -751,6 +754,7 @@ struct v4l2_subdev_krouting {
  * %V4L2_SUBDEV_FORMAT_ACTIVE it is safe to pass %NULL.
  */
 struct v4l2_subdev_state {
+	/* lock for the struct v4l2_subdev_state fields */
 	struct mutex lock;
 	struct v4l2_subdev_pad_config *pads;
 	struct v4l2_subdev_krouting routing;
@@ -1008,8 +1012,8 @@ struct v4l2_subdev_platform_data {
  * @subdev_notifier: A sub-device notifier implicitly registered for the sub-
  *		     device using v4l2_async_register_subdev_sensor().
  * @pdata: common part of subdevice platform data
- * @state: active state for the subdev (NULL for subdevs tracking the state
- *	   internally)
+ * @active_state: active state for the subdev (NULL for subdevs tracking the
+ *                state internally)
  *
  * Each instance of a subdev driver should create this struct, either
  * stand-alone or embedded in a larger struct.
@@ -1053,7 +1057,7 @@ struct v4l2_subdev {
 	 * easily catch uses of state in the cases where the driver doesn't
 	 * support it.
 	 */
-	struct v4l2_subdev_state *state;
+	struct v4l2_subdev_state *active_state;
 };
 
 
@@ -1404,7 +1408,7 @@ void v4l2_subdev_cleanup(struct v4l2_subdev *sd);
 static inline struct v4l2_subdev_state *
 v4l2_subdev_get_active_state(struct v4l2_subdev *sd)
 {
-	return sd->state;
+	return sd->active_state;
 }
 
 /**
@@ -1438,8 +1442,7 @@ void v4l2_subdev_lock_state(struct v4l2_subdev_state *state);
 void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state);
 
 /**
- * v4l2_subdev_validate_and_lock_state() - Gets locked TRY or ACTIVE subdev
- *					   state
+ * v4l2_subdev_lock_and_return_state() - Gets locked TRY or ACTIVE subdev state
  * @sd: subdevice
  * @state: subdevice state as passed to the subdev op
  *
@@ -1448,22 +1451,21 @@ void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state);
  * state stored privately.
  *
  * However, newer state-aware subdev drivers, which store their active state in
- * a common place, subdev->state, expect to always get a proper state as a
- * parameter.
+ * a common place, subdev->active_state, expect to always get a proper state as
+ * a parameter.
  *
- * These state-aware drivers can use v4l2_subdev_validate_and_lock_state()
- * instead of v4l2_subdev_lock_state(). v4l2_subdev_validate_and_lock_state()
- * solves the issue by using subdev->state in case the passed state is
- * NULL.
+ * These state-aware drivers can use v4l2_subdev_lock_and_return_state() instead
+ * of v4l2_subdev_lock_state(). v4l2_subdev_lock_and_return_state() solves the
+ * issue by using subdev->state in case the passed state is NULL.
  *
  * This is a temporary helper function, and should be removed when we can ensure
  * that all drivers pass proper state when calling other subdevs.
  */
 static inline struct v4l2_subdev_state *
-v4l2_subdev_validate_and_lock_state(struct v4l2_subdev *sd,
-				    struct v4l2_subdev_state *state)
+v4l2_subdev_lock_and_return_state(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_state *state)
 {
-	state = state ? state : sd->state;
+	state = state ? state : sd->active_state;
 
 	v4l2_subdev_lock_state(state);
 
@@ -1518,7 +1520,7 @@ v4l2_state_get_stream_format(struct v4l2_subdev_state *state, unsigned int pad,
 			     u32 stream);
 
 /**
- * v4l2_state_find_opposite_end() - Find the opposite stream
+ * v4l2_subdev_routing_find_opposite_end() - Find the opposite stream
  * @routing: routing used to find the opposite side
  * @pad: pad id
  * @stream: stream id
@@ -1528,14 +1530,18 @@ v4l2_state_get_stream_format(struct v4l2_subdev_state *state, unsigned int pad,
  * This function uses the routing table to find the pad + stream which is
  * opposite the given pad + stream.
  *
+ * @other_pad and/or @other_stream can be NULL if the caller does not need the
+ * value.
+ *
  * Returns 0 on success, or -EINVAL if no matching route is found.
  */
-int v4l2_state_find_opposite_end(struct v4l2_subdev_krouting *routing, u32 pad,
-				 u32 stream, u32 *other_pad, u32 *other_stream);
+int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing,
+					  u32 pad, u32 stream, u32 *other_pad,
+					  u32 *other_stream);
 
 /**
- * v4l2_state_get_opposite_stream_format() - Get pointer to opposite stream
- *					     format
+ * v4l2_subdev_state_get_opposite_stream_format() - Get pointer to opposite
+ *                                                  stream format
  * @state: subdevice state
  * @pad: pad id
  * @stream: stream id
@@ -1546,8 +1552,9 @@ int v4l2_state_find_opposite_end(struct v4l2_subdev_krouting *routing, u32 pad,
  * If the state does not contain the given pad + stream, NULL is returned.
  */
 struct v4l2_mbus_framefmt *
-v4l2_state_get_opposite_stream_format(struct v4l2_subdev_state *state, u32 pad,
-				      u32 stream);
+v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state,
+					     u32 pad, u32 stream);
+
 /**
  * v4l2_subdev_get_fmt() - Fill format based on state
  * @sd: subdevice
@@ -1566,8 +1573,8 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
 			struct v4l2_subdev_format *format);
 
 /**
- * v4l2_routing_simple_verify() - Verify that all streams are non-overlapping
- *				  1-to-1 streams
+ * v4l2_subdev_routing_validate_1_to_1() - Verify that all streams are
+ *                                         non-overlapping 1-to-1 streams
  * @routing: routing to verify
  *
  * This verifies that the given routing contains only non-overlapping 1-to-1
@@ -1577,6 +1584,19 @@ int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
  *
  * Returns 0 on success, error value otherwise.
  */
-int v4l2_routing_simple_verify(const struct v4l2_subdev_krouting *routing);
+int v4l2_subdev_routing_validate_1_to_1(const struct v4l2_subdev_krouting *routing);
+
+struct v4l2_subdev_route *
+__v4l2_subdev_next_active_route(const struct v4l2_subdev_krouting *routing,
+				struct v4l2_subdev_route *route);
+
+/**
+ * for_each_active_route - iterate on all active routes of a routing table
+ * @routing: The routing table
+ * @route: The route iterator
+ */
+#define for_each_active_route(routing, route) \
+	for ((route) = NULL;                  \
+	     ((route) = __v4l2_subdev_next_active_route((routing), (route)));)
 
 #endif
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index f61ace2b5755..480891dba193 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -202,17 +202,20 @@ struct v4l2_subdev_capability {
 /* The v4l2 sub-device video device node is registered in read-only mode. */
 #define V4L2_SUBDEV_CAP_RO_SUBDEV		0x00000001
 
+/* The v4l2 sub-device supports multiplexed streams. */
+#define V4L2_SUBDEV_CAP_MPLEXED			0x00000002
+
 /*
  * Is the route active? An active route will start when streaming is enabled
  * on a video node.
  */
-#define V4L2_SUBDEV_ROUTE_FL_ACTIVE		(1 << 0)
+#define V4L2_SUBDEV_ROUTE_FL_ACTIVE		_BITUL(0)
 
 /*
  * Is the route immutable, i.e. can it be activated and inactivated?
  * Set by the driver.
  */
-#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE		(1 << 1)
+#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE		_BITUL(1)
 
 /*
  * Is the route a source endpoint? A source endpoint route refers to a stream
@@ -221,7 +224,7 @@ struct v4l2_subdev_capability {
  * fields are unused.
  * Set by the driver.
  */
-#define V4L2_SUBDEV_ROUTE_FL_SOURCE		(1 << 2)
+#define V4L2_SUBDEV_ROUTE_FL_SOURCE		_BITUL(2)
 
 /**
  * struct v4l2_subdev_route - A route inside a subdev
@@ -246,15 +249,15 @@ struct v4l2_subdev_route {
  * struct v4l2_subdev_routing - Subdev routing information
  *
  * @which: configuration type (from enum v4l2_subdev_format_whence)
- * @routes: pointer to the routes array
  * @num_routes: the total number of routes in the routes array
+ * @routes: pointer to the routes array
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_routing {
 	__u32 which;
-	__u64 routes;
 	__u32 num_routes;
-	__u32 reserved[5];
+	__u64 routes;
+	__u32 reserved[6];
 };
 
 /* Backwards compatibility define --- to be removed */

      parent reply	other threads:[~2021-12-01  6:26 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-30 14:14 [PATCH v10 00/38] v4l: subdev internal routing and streams Tomi Valkeinen
2021-11-30 14:14 ` [PATCH v10 01/38] media: subdev: rename subdev-state alloc & free Tomi Valkeinen
2021-12-13 21:28   ` Jacopo Mondi
2021-11-30 14:15 ` [PATCH v10 02/38] media: subdev: add active state to struct v4l2_subdev Tomi Valkeinen
2021-12-13 21:30   ` Jacopo Mondi
2021-12-15  8:06     ` Tomi Valkeinen
2021-12-15  9:38       ` Jacopo Mondi
2021-12-15 15:35         ` Tomi Valkeinen
2021-12-15 16:25           ` Jacopo Mondi
2021-12-16 14:14             ` Laurent Pinchart
2021-12-16 14:41               ` Laurent Pinchart
2021-12-17  8:00                 ` Tomi Valkeinen
2021-12-17 10:12   ` Hans Verkuil
2021-11-30 14:15 ` [PATCH v10 03/38] media: subdev: pass also the active state to subdevs from ioctls Tomi Valkeinen
2021-12-14  7:13   ` Jacopo Mondi
2021-12-15  8:13     ` Tomi Valkeinen
2021-12-16 13:47   ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 04/38] media: subdev: add subdev state locking Tomi Valkeinen
2021-12-14  7:42   ` Jacopo Mondi
2021-12-15  8:18     ` Tomi Valkeinen
2021-12-16 13:39   ` Laurent Pinchart
2021-12-17 11:23   ` Hans Verkuil
2021-11-30 14:15 ` [PATCH v10 05/38] media: subdev: Add v4l2_subdev_lock_and_return_state() Tomi Valkeinen
2021-12-16 14:34   ` Laurent Pinchart
2021-12-17 17:43     ` Sakari Ailus
2021-12-17 17:54       ` Laurent Pinchart
2021-12-20 11:48         ` Sakari Ailus
2021-12-17 11:48   ` Hans Verkuil
2021-12-17 17:55     ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 06/38] media: Documentation: add documentation about subdev state Tomi Valkeinen
2021-12-14  8:31   ` Jacopo Mondi
2021-12-16 14:50     ` Laurent Pinchart
2021-12-17  9:22     ` Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 07/38] media: entity: Use pad as a starting point for graph walk Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 08/38] media: entity: Use pads instead of entities in the media graph walk stack Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 09/38] media: entity: Walk the graph based on pads Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 10/38] media: mc: Start walk from a specific pad in use count calculation Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 11/38] media: entity: Add iterator helper for entity pads Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 12/38] media: entity: Move the pipeline from entity to pads Tomi Valkeinen
2022-01-07 19:52   ` Laurent Pinchart
2022-01-09  0:58     ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 13/38] media: entity: Use pad as the starting point for a pipeline Tomi Valkeinen
2022-01-11 23:39   ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 14/38] media: entity: Add has_route entity operation Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 15/38] media: entity: Add media_entity_has_route() function Tomi Valkeinen
2022-01-08 23:31   ` Laurent Pinchart
2022-01-10  7:18     ` Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 16/38] media: entity: Use routing information during graph traversal Tomi Valkeinen
2022-01-17 23:13   ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 17/38] media: entity: Skip link validation for pads to which there is no route Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 18/38] media: entity: Add an iterator helper for connected pads Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 19/38] media: entity: Add only connected pads to the pipeline Tomi Valkeinen
2022-01-07 19:57   ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 20/38] media: entity: Add debug information in graph walk route check Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 21/38] media: Add bus type to frame descriptors Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 22/38] media: Add CSI-2 bus configuration " Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 23/38] media: Add stream to frame descriptor Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 24/38] media: subdev: increase V4L2_FRAME_DESC_ENTRY_MAX to 8 Tomi Valkeinen
2021-12-14  8:35   ` Jacopo Mondi
2021-11-30 14:15 ` [PATCH v10 25/38] media: add V4L2_SUBDEV_FL_MULTIPLEXED Tomi Valkeinen
2021-12-14  8:41   ` Jacopo Mondi
2021-12-15  8:23     ` Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 26/38] media: add V4L2_SUBDEV_CAP_MPLEXED Tomi Valkeinen
2021-12-14  8:39   ` Jacopo Mondi
2021-12-21 18:07     ` Laurent Pinchart
2021-11-30 14:15 ` [PATCH v10 27/38] media: Documentation: Add GS_ROUTING documentation Tomi Valkeinen
2022-02-03 10:55   ` Kieran Bingham
2022-02-03 10:58     ` Kieran Bingham
2021-11-30 14:15 ` [PATCH v10 28/38] media: subdev: Add [GS]_ROUTING subdev ioctls and operations Tomi Valkeinen
2021-12-17  3:31   ` Laurent Pinchart
2021-12-21 17:37   ` Dave Stevenson
2021-11-30 14:15 ` [PATCH v10 29/38] media: subdev: add v4l2_subdev_has_route() Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 30/38] media: subdev: add v4l2_subdev_set_routing helper() Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 31/38] media: Documentation: add multiplexed streams documentation Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 32/38] media: subdev: add stream based configuration Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 33/38] media: subdev: use streams in v4l2_subdev_link_validate() Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 34/38] media: subdev: add "opposite" stream helper funcs Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 35/38] media: subdev: add v4l2_subdev_get_fmt() helper function Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 36/38] media: subdev: add v4l2_subdev_set_routing_with_fmt() helper Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 37/38] media: subdev: add v4l2_subdev_routing_validate_1_to_1 helper Tomi Valkeinen
2021-11-30 14:15 ` [PATCH v10 38/38] media: subdev: Add for_each_active_route() macro Tomi Valkeinen
2021-12-01  6:26 ` Tomi Valkeinen [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d66254da-9b68-85fa-35ec-3fa1c1769592@ideasonboard.com \
    --to=tomi.valkeinen@ideasonboard.com \
    --cc=hverkuil-cisco@xs4all.nl \
    --cc=jacopo+renesas@jmondi.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=niklas.soderlund+renesas@ragnatech.se \
    --cc=p.yadav@ti.com \
    --cc=sakari.ailus@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).