clear-pkgs-linux-iot-lts2018/0050-v4l-for-multiplex-pad-...

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 *
--
2.21.0