182 lines
5.6 KiB
Diff
182 lines
5.6 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Meng Wei <wei.meng@intel.com>
|
|
Date: Fri, 26 Oct 2018 09:52:23 +0800
|
|
Subject: [PATCH] v4l: for multiplex pad add routing informaion in link
|
|
validation
|
|
|
|
for links have 2 multiplexed pad, validating all active
|
|
streams.
|
|
|
|
otherwise, all follow 1:1 pad link route with stream id 0
|
|
|
|
Signed-off-by: Chang Ying <ying.chang@intel.com>
|
|
Signed-off-by: Meng Wei <wei.meng@intel.com>
|
|
---
|
|
drivers/media/v4l2-core/v4l2-subdev.c | 135 +++++++++++++++++++++++++-
|
|
1 file changed, 130 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
|
|
index 5d0ee2f..e95cda5 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-subdev.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
|
|
@@ -668,19 +668,21 @@ 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 media_pad *source_pad, unsigned int source_stream,
|
|
+ struct media_pad *sink_pad, unsigned int sink_stream)
|
|
{
|
|
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);
|
|
+ source_fmt.stream = source_stream;
|
|
+ rval = v4l2_subdev_link_validate_get_format(source_pad, &source_fmt);
|
|
if (rval < 0)
|
|
return 0;
|
|
|
|
- rval = v4l2_subdev_link_validate_get_format(
|
|
- link->sink, &sink_fmt);
|
|
+ sink_fmt.stream = sink_stream;
|
|
+ rval = v4l2_subdev_link_validate_get_format(sink_pad, &sink_fmt);
|
|
if (rval < 0)
|
|
return 0;
|
|
|
|
@@ -694,6 +696,129 @@ int v4l2_subdev_link_validate(struct media_link *link)
|
|
return v4l2_subdev_link_validate_default(
|
|
sink, link, &source_fmt, &sink_fmt);
|
|
}
|
|
+
|
|
+/* How many routes to assume there can be per a sub-device? */
|
|
+#define LINK_VALIDATE_ROUTES 8
|
|
+
|
|
+int v4l2_subdev_link_validate(struct media_link *link)
|
|
+{
|
|
+ struct v4l2_subdev *sink;
|
|
+ struct v4l2_subdev_route sink_routes[LINK_VALIDATE_ROUTES];
|
|
+ struct v4l2_subdev_routing sink_routing = {
|
|
+ .routes = sink_routes,
|
|
+ .num_routes = ARRAY_SIZE(sink_routes),
|
|
+ };
|
|
+ struct v4l2_subdev_route src_routes[LINK_VALIDATE_ROUTES];
|
|
+ struct v4l2_subdev_routing src_routing = {
|
|
+ .routes = src_routes,
|
|
+ .num_routes = ARRAY_SIZE(src_routes),
|
|
+ };
|
|
+ unsigned int i, j;
|
|
+ int rval;
|
|
+
|
|
+ sink = media_entity_to_v4l2_subdev(link->sink->entity);
|
|
+
|
|
+ if (!(link->sink->flags & MEDIA_PAD_FL_MULTIPLEX &&
|
|
+ link->source->flags & MEDIA_PAD_FL_MULTIPLEX))
|
|
+ return v4l2_subdev_link_validate_one(link, link->source, 0,
|
|
+ link->sink, 0);
|
|
+ /*
|
|
+ * multiplex link cannot proceed without route information.
|
|
+ */
|
|
+ rval = v4l2_subdev_call(sink, pad, get_routing, &sink_routing);
|
|
+
|
|
+ if (rval) {
|
|
+ dev_err(sink->entity.graph_obj.mdev->dev,
|
|
+ "error %d in get_routing() on %s, sink pad %u\n", rval,
|
|
+ sink->entity.name, link->sink->index);
|
|
+
|
|
+ return rval;
|
|
+ }
|
|
+
|
|
+ rval = v4l2_subdev_call(media_entity_to_v4l2_subdev(
|
|
+ link->source->entity),
|
|
+ pad, get_routing, &src_routing);
|
|
+ if (rval) {
|
|
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
|
|
+ "error %d in get_routing() on %s, source pad %u\n",
|
|
+ rval, sink->entity.name, link->source->index);
|
|
+
|
|
+ return rval;
|
|
+ }
|
|
+
|
|
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
|
|
+ "validating multiplexed link \"%s\":%u -> \"%s\":%u; %u/%u routes\n",
|
|
+ link->source->entity->name, link->source->index,
|
|
+ sink->entity.name, link->sink->index,
|
|
+ src_routing.num_routes, sink_routing.num_routes);
|
|
+
|
|
+ for (i = 0; i < sink_routing.num_routes; i++) {
|
|
+ /* Get the first active route for the sink pad. */
|
|
+ if (sink_routes[i].sink_pad != link->sink->index ||
|
|
+ !(sink_routes[i].flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
|
|
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
|
|
+ "skipping sink route %u/%u -> %u/%u[%u]\n",
|
|
+ sink_routes[i].sink_pad,
|
|
+ sink_routes[i].sink_stream,
|
|
+ sink_routes[i].source_pad,
|
|
+ sink_routes[i].source_stream,
|
|
+ (bool)(sink_routes[i].flags
|
|
+ & V4L2_SUBDEV_ROUTE_FL_ACTIVE));
|
|
+ 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 source pad have to be active on
|
|
+ * the sink pad as well.
|
|
+ */
|
|
+
|
|
+ for (j = 0; j < src_routing.num_routes; j++) {
|
|
+ if (src_routes[j].source_pad == link->source->index &&
|
|
+ src_routes[j].source_stream
|
|
+ == sink_routes[i].sink_stream)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (j == src_routing.num_routes) {
|
|
+ dev_err(sink->entity.graph_obj.mdev->dev,
|
|
+ "no corresponding source found.\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ /* The source route must be active. */
|
|
+ if (!(src_routes[j].flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
|
|
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
|
|
+ "source route not active\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
|
|
+ "validating link \"%s\": %u/%u => \"%s\" %u/%u\n",
|
|
+ link->source->entity->name, src_routes[j].source_pad,
|
|
+ src_routes[j].source_stream, sink->entity.name,
|
|
+ sink_routes[i].sink_pad, sink_routes[i].sink_stream);
|
|
+
|
|
+ rval = v4l2_subdev_link_validate_one(
|
|
+ link, link->source, src_routes[j].source_stream,
|
|
+ link->sink, sink_routes[j].sink_stream);
|
|
+ if (rval) {
|
|
+ dev_dbg(sink->entity.graph_obj.mdev->dev,
|
|
+ "error %d in link validation\n", rval);
|
|
+ return rval;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (i < 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);
|
|
|
|
struct v4l2_subdev_pad_config *
|
|
--
|
|
https://clearlinux.org
|
|
|