From: "Niklas Söderlund" <niklas.soderlund+renesas@ragnatech.se>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
Benoit Parrot <bparrot@ti.com>,
linux-media@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
Subject: [PATCH v2 18/30] v4l: subdev: Take routing information into account in link validation
Date: Fri, 2 Nov 2018 00:31:32 +0100 [thread overview]
Message-ID: <20181101233144.31507-19-niklas.soderlund+renesas@ragnatech.se> (raw)
In-Reply-To: <20181101233144.31507-1-niklas.soderlund+renesas@ragnatech.se>
From: Sakari Ailus <sakari.ailus@linux.intel.com>
The routing information is essential in link validation for multiplexed
links: the pads at the ends of a multiplexed link have no single format
defined for them. Instead, the format is accessible in the sink (or
source) pads of the sub-devices at both ends of that link.
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/media/v4l2-core/v4l2-subdev.c | 217 ++++++++++++++++++++++++--
1 file changed, 203 insertions(+), 14 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 1d3b37cf548fa533..05684c796b184272 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -640,12 +640,17 @@ static int
v4l2_subdev_link_validate_get_format(struct media_pad *pad,
struct v4l2_subdev_format *fmt)
{
+ dev_dbg(pad->entity->graph_obj.mdev->dev,
+ "obtaining format on \"%s\":%u\n", pad->entity->name,
+ pad->index);
+
if (is_media_entity_v4l2_subdev(pad->entity)) {
struct v4l2_subdev *sd =
media_entity_to_v4l2_subdev(pad->entity);
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
fmt->pad = pad->index;
+
return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
}
@@ -656,31 +661,215 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad,
return -EINVAL;
}
-int v4l2_subdev_link_validate(struct media_link *link)
+static int v4l2_subdev_link_validate_one(struct media_link *link,
+ struct v4l2_subdev_format *source_fmt,
+ struct v4l2_subdev_format *sink_fmt)
{
struct v4l2_subdev *sink;
- struct v4l2_subdev_format sink_fmt, source_fmt;
int rval;
- rval = v4l2_subdev_link_validate_get_format(
- link->source, &source_fmt);
- if (rval < 0)
- return 0;
-
- rval = v4l2_subdev_link_validate_get_format(
- link->sink, &sink_fmt);
- if (rval < 0)
- return 0;
-
sink = media_entity_to_v4l2_subdev(link->sink->entity);
rval = v4l2_subdev_call(sink, pad, link_validate, link,
- &source_fmt, &sink_fmt);
+ source_fmt, sink_fmt);
if (rval != -ENOIOCTLCMD)
return rval;
return v4l2_subdev_link_validate_default(
- sink, link, &source_fmt, &sink_fmt);
+ sink, link, source_fmt, sink_fmt);
+}
+
+/* How many routes to assume there can be per a sub-device? */
+#define LINK_VALIDATE_ROUTES 8
+
+#define R_SRC 0
+#define R_SINK 1
+#define NR_R 2
+
+int v4l2_subdev_link_validate(struct media_link *link)
+{
+ struct v4l2_subdev *sink;
+ struct route_info {
+ struct v4l2_subdev_route routes[LINK_VALIDATE_ROUTES];
+ struct v4l2_subdev_routing routing;
+ bool has_route;
+ struct media_pad *pad;
+ /* Format for a non-multiplexed pad. */
+ struct v4l2_subdev_format fmt;
+ } r[NR_R] = {
+ {
+ /* Source end of the link */
+ .routing = {
+ .routes = r[R_SRC].routes,
+ .num_routes = ARRAY_SIZE(r[R_SRC].routes),
+ },
+ .pad = link->source,
+ },
+ {
+ /* Sink end of the link */
+ .routing = {
+ .routes = r[R_SINK].routes,
+ .num_routes = ARRAY_SIZE(r[R_SINK].routes),
+ },
+ .pad = link->sink,
+ },
+ };
+ unsigned int i, j;
+ int rval;
+
+ sink = media_entity_to_v4l2_subdev(link->sink->entity);
+
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "validating link \"%s\":%u -> \"%s\":%u\n",
+ link->source->entity->name, link->source->index,
+ sink->entity.name, link->sink->index);
+
+ for (i = 0; i < NR_R; i++) {
+ struct route_info *ri = &r[i];
+
+ ri->has_route = true;
+
+ rval = v4l2_subdev_call(
+ media_entity_to_v4l2_subdev(ri->pad->entity),
+ pad, get_routing, &ri->routing);
+
+ switch (rval) {
+ case 0:
+ break;
+ case -ENOIOCTLCMD:
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "no routing information on \"%s\":%u\n",
+ ri->pad->entity->name, ri->pad->index);
+ ri->has_route = false;
+ break;
+ default:
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "error %d in get_routing() on \"%s\":%u\n",
+ rval, ri->pad->entity->name, ri->pad->index);
+ return rval;
+ }
+
+ rval = v4l2_subdev_link_validate_get_format(ri->pad,
+ &ri->fmt);
+
+ if (!rval) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "format information available on \"%s\":%u\n",
+ ri->pad->entity->name, ri->pad->index);
+ ri->has_route = false;
+ }
+
+ if (!ri->has_route) {
+ ri->routing.num_routes = 1;
+ } else {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "routes on \"%s\":%u:\n",
+ ri->pad->entity->name, ri->pad->index);
+ for (j = 0; j < ri->routing.num_routes; j++)
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "\t%u: %u/%u -> %u/%u\n", j,
+ ri->routing.routes[j].sink_pad,
+ ri->routing.routes[j].sink_stream,
+ ri->routing.routes[j].source_pad,
+ ri->routing.routes[j].source_stream);
+ }
+ }
+
+ for (i = 0, j = 0;
+ i < r[R_SRC].routing.num_routes &&
+ j < r[R_SINK].routing.num_routes; ) {
+ unsigned int *ro[] = { &i, &j };
+ unsigned int k;
+
+ /* Get the first active route for the sink pad. */
+ if (r[R_SINK].has_route &&
+ (r[R_SINK].routes[j].sink_pad != link->sink->index ||
+ !(r[R_SINK].routes[j].flags
+ & V4L2_SUBDEV_ROUTE_FL_ACTIVE))) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "skipping route %u/%u -> %u/%u[%u]\n",
+ r[R_SINK].routes[j].sink_pad,
+ r[R_SINK].routes[j].sink_stream,
+ r[R_SINK].routes[j].source_pad,
+ r[R_SINK].routes[j].source_stream,
+ (bool)(r[R_SINK].routes[j].flags
+ & V4L2_SUBDEV_ROUTE_FL_ACTIVE));
+ j++;
+ continue;
+ }
+
+ /*
+ * Get the corresponding route for the source pad.
+ * It's ok for the source pad to have routes active
+ * where the sink pad does not, but the routes that
+ * are active on the sink pad have to be active on
+ * the source pad as well.
+ */
+ if (r[R_SRC].has_route &&
+ (r[R_SRC].routes[i].source_pad != link->source->index ||
+ r[R_SRC].routes[i].source_stream
+ != r[R_SINK].routes[j].sink_stream)) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "skipping source route %u/%u -> %u/%u\n",
+ r[R_SRC].routes[i].sink_pad,
+ r[R_SRC].routes[i].sink_stream,
+ r[R_SRC].routes[i].source_pad,
+ r[R_SRC].routes[i].source_stream);
+ i++;
+ continue;
+ }
+
+ /* The source route must be active. */
+ if (r[R_SRC].has_route &&
+ !(r[R_SRC].routes[i].flags
+ & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "source route not active\n");
+ return -EINVAL;
+ }
+
+ for (k = 0; k < NR_R; k++) {
+ if (r[k].has_route) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "validating %s route \"%s\": %u/%u -> %u/%u\n",
+ k == R_SINK ? "sink" : "source",
+ r[k].pad->entity->name,
+ r[k].routes[*ro[k]].sink_pad,
+ r[k].routes[*ro[k]].sink_stream,
+ r[k].routes[*ro[k]].source_pad,
+ r[k].routes[*ro[k]].source_stream);
+ rval = v4l2_subdev_link_validate_get_format(
+ &r[k].pad->entity->pads[
+ k == R_SINK
+ ? r[k].routes[*ro[k]].source_pad
+ : r[k].routes[*ro[k]].sink_pad],
+ &r[k].fmt);
+ } else {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "routing not supported by \"%s\":%u",
+ r[k].pad->entity->name,
+ r[k].pad->index);
+ }
+ }
+
+ rval = v4l2_subdev_link_validate_one(
+ link, &r[R_SRC].fmt, &r[R_SINK].fmt);
+ if (rval) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "error %d in link validation\n", rval);
+ return rval;
+ }
+
+ i++, j++;
+ }
+
+ if (j < r[R_SINK].routing.num_routes) {
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
+ "not all sink routes verified; out of source routes\n");
+ return -EINVAL;
+ }
+
+ return 0;
}
EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate);
--
2.19.1
next prev parent reply other threads:[~2018-11-01 23:31 UTC|newest]
Thread overview: 90+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-01 23:31 [PATCH v2 00/30] v4l: add support for multiplexed streams Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 01/30] media: entity: Use pad as a starting point for graph walk Niklas Söderlund
2019-01-15 21:43 ` Laurent Pinchart
2018-11-01 23:31 ` [PATCH v2 02/30] media: entity: Use pads instead of entities in the media graph walk stack Niklas Söderlund
2019-01-15 22:03 ` Laurent Pinchart
2019-01-15 22:13 ` Sakari Ailus
2019-01-15 22:07 ` Laurent Pinchart
2018-11-01 23:31 ` [PATCH v2 03/30] media: entity: Walk the graph based on pads Niklas Söderlund
2019-01-15 22:21 ` Laurent Pinchart
[not found] ` <20190115223406.mxgzl36cp54gb7nv@kekkonen.localdomain>
2019-01-15 23:28 ` Laurent Pinchart
2019-01-22 14:50 ` Sakari Ailus
2019-02-14 15:15 ` Jacopo Mondi
2018-11-01 23:31 ` [PATCH v2 04/30] v4l: mc: Start walk from a specific pad in use count calculation Niklas Söderlund
2019-01-15 22:24 ` Laurent Pinchart
2019-01-15 22:36 ` Sakari Ailus
2018-11-01 23:31 ` [PATCH v2 05/30] media: entity: Move the pipeline from entity to pads Niklas Söderlund
2019-01-15 22:38 ` Laurent Pinchart
2019-01-15 22:48 ` Sakari Ailus
2019-02-14 15:53 ` Jacopo Mondi
2018-11-01 23:31 ` [PATCH v2 06/30] media: entity: Use pad as the starting point for a pipeline Niklas Söderlund
2019-01-15 22:54 ` Laurent Pinchart
2019-01-22 15:31 ` Sakari Ailus
2019-01-22 15:37 ` Laurent Pinchart
2019-01-22 16:16 ` Sakari Ailus
2018-11-01 23:31 ` [PATCH v2 07/30] media: entity: Add has_route entity operation Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 08/30] media: entity: Add media_has_route() function Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 09/30] media: entity: Swap pads if route is checked from source to sink Niklas Söderlund
2019-01-15 22:57 ` Laurent Pinchart
2019-01-22 15:15 ` Sakari Ailus
2019-01-22 15:20 ` Laurent Pinchart
2019-02-18 9:21 ` Jacopo Mondi
2019-02-22 12:18 ` Laurent Pinchart
2019-03-04 12:35 ` Jacopo Mondi
2019-03-05 20:04 ` Laurent Pinchart
2019-03-06 8:29 ` Jacopo Mondi
2018-11-01 23:31 ` [PATCH v2 10/30] media: entity: Use routing information during graph traversal Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 11/30] media: entity: Skip link validation for pads to which there is no route to Niklas Söderlund
2019-01-15 23:13 ` Laurent Pinchart
2018-11-01 23:31 ` [PATCH v2 12/30] media: entity: Add an iterator helper for connected pads Niklas Söderlund
2019-01-15 23:24 ` Laurent Pinchart
2019-01-22 15:36 ` Sakari Ailus
2019-01-22 15:38 ` Laurent Pinchart
2019-01-22 16:21 ` Sakari Ailus
2018-11-01 23:31 ` [PATCH v2 13/30] media: entity: Add only connected pads to the pipeline Niklas Söderlund
2019-01-15 23:33 ` Laurent Pinchart
2018-11-01 23:31 ` [PATCH v2 14/30] media: entity: Add debug information in graph walk route check Niklas Söderlund
2019-01-15 23:35 ` Laurent Pinchart
2019-01-22 15:38 ` Sakari Ailus
2018-11-01 23:31 ` [PATCH v2 15/30] media: entity: Look for indirect routes Niklas Söderlund
2019-01-15 23:41 ` Laurent Pinchart
2019-01-22 15:56 ` Sakari Ailus
2018-11-01 23:31 ` [PATCH v2 16/30] v4l: subdev: Add [GS]_ROUTING subdev ioctls and operations Niklas Söderlund
2019-01-15 23:51 ` Laurent Pinchart
2019-01-22 16:14 ` Sakari Ailus
2019-01-22 17:00 ` Laurent Pinchart
2019-02-21 14:59 ` Jacopo Mondi
2019-02-21 23:49 ` Sakari Ailus
2019-02-22 8:46 ` Jacopo Mondi
2019-02-21 14:39 ` Jacopo Mondi
2019-02-21 22:31 ` Sakari Ailus
2019-02-22 8:40 ` Jacopo Mondi
2019-02-22 11:04 ` Sakari Ailus
2019-02-22 11:17 ` Jacopo Mondi
2019-02-22 11:29 ` Sakari Ailus
2019-02-22 13:37 ` Ian Arkver
2019-02-22 13:50 ` Geert Uytterhoeven
2018-11-01 23:31 ` [PATCH v2 17/30] v4l: subdev: compat: Implement handling for VIDIOC_SUBDEV_[GS]_ROUTING Niklas Söderlund
2019-01-08 10:04 ` Geert Uytterhoeven
2019-01-15 23:53 ` Laurent Pinchart
2019-01-22 15:57 ` Sakari Ailus
2019-02-18 11:21 ` Jacopo Mondi
2019-02-21 23:50 ` Sakari Ailus
2018-11-01 23:31 ` Niklas Söderlund [this message]
2018-11-01 23:31 ` [PATCH v2 19/30] v4l: subdev: Improve link format validation debug messages Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 20/30] v4l: mc: Add an S_ROUTING helper function for power state changes Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 21/30] v4l: Add bus type to frame descriptors Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 22/30] v4l: Add CSI-2 bus configuration " Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 23/30] v4l: Add stream to frame descriptor Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 24/30] adv748x: csi2: add translation from pixelcode to CSI-2 datatype Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 25/30] adv748x: csi2: only allow formats on sink pads Niklas Söderlund
2019-02-21 14:18 ` Jacopo Mondi
2018-11-01 23:31 ` [PATCH v2 26/30] adv748x: csi2: describe the multiplexed stream Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 27/30] adv748x: csi2: add internal routing configuration Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 28/30] adv748x: afe: add routing support Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 29/30] rcar-csi2: use frame description information to configure CSI-2 bus Niklas Söderlund
2018-11-01 23:31 ` [PATCH v2 30/30] rcar-csi2: expose the subdevice internal routing Niklas Söderlund
2018-11-14 13:10 ` Nikita Yushchenko
2018-11-14 19:45 ` Niklas Söderlund
2018-12-03 22:16 ` [PATCH v2 00/30] v4l: add support for multiplexed streams Sakari Ailus
2018-12-05 22:09 ` Niklas Söderlund
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=20181101233144.31507-19-niklas.soderlund+renesas@ragnatech.se \
--to=niklas.soderlund+renesas@ragnatech.se \
--cc=bparrot@ti.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--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).