@@ -912,6 +912,95 @@ v4l2_subdev_link_validate_get_format(struct media_pad *pad,
return -EINVAL;
}
+int v4l2_subdev_get_routing(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_krouting *routing)
+{
+ int ret;
+
+ routing->which = state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+ routing->routes = NULL;
+ routing->num_routes = 0;
+
+ ret = v4l2_subdev_call(sd, pad, get_routing, state, routing);
+ if (ret == 0)
+ return 0;
+ if (ret != -ENOSPC)
+ return ret;
+
+ routing->routes = kvmalloc_array(routing->num_routes,
+ sizeof(*routing->routes), GFP_KERNEL);
+ if (!routing->routes)
+ return -ENOMEM;
+
+ ret = v4l2_subdev_call(sd, pad, get_routing, state, routing);
+ if (ret) {
+ kvfree(routing->routes);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_get_routing);
+
+void v4l2_subdev_free_routing(struct v4l2_subdev_krouting *routing)
+{
+ kvfree(routing->routes);
+ routing->routes = NULL;
+ routing->num_routes = 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_free_routing);
+
+void v4l2_subdev_cpy_routing(struct v4l2_subdev_krouting *dst,
+ const struct v4l2_subdev_krouting *src)
+{
+ memcpy(dst->routes, src->routes,
+ src->num_routes * sizeof(*src->routes));
+ dst->num_routes = src->num_routes;
+ dst->which = src->which;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_cpy_routing);
+
+int v4l2_subdev_dup_routing(struct v4l2_subdev_krouting *dst,
+ const struct v4l2_subdev_krouting *src)
+{
+ v4l2_subdev_free_routing(dst);
+
+ if (src->num_routes == 0) {
+ dst->which = src->which;
+ return 0;
+ }
+
+ dst->routes = kvmalloc_array(src->num_routes, sizeof(*src->routes),
+ GFP_KERNEL);
+ if (!dst->routes)
+ return -ENOMEM;
+
+ v4l2_subdev_cpy_routing(dst, src);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_dup_routing);
+
+bool v4l2_subdev_has_route(struct v4l2_subdev_krouting *routing,
+ unsigned int pad0, unsigned int pad1)
+{
+ unsigned int i;
+
+ for (i = 0; i < routing->num_routes; ++i) {
+ struct v4l2_subdev_route *route = &routing->routes[i];
+
+ if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+ continue;
+
+ if (route->sink_pad == pad0 && route->source_pad == pad1)
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_has_route);
+
int v4l2_subdev_link_validate(struct media_link *link)
{
struct v4l2_subdev *sink;
@@ -1252,4 +1252,19 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers;
void v4l2_subdev_notify_event(struct v4l2_subdev *sd,
const struct v4l2_event *ev);
+int v4l2_subdev_get_routing(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ struct v4l2_subdev_krouting *routing);
+
+void v4l2_subdev_free_routing(struct v4l2_subdev_krouting *routing);
+
+int v4l2_subdev_dup_routing(struct v4l2_subdev_krouting *dst,
+ const struct v4l2_subdev_krouting *src);
+
+void v4l2_subdev_cpy_routing(struct v4l2_subdev_krouting *dst,
+ const struct v4l2_subdev_krouting *src);
+
+bool v4l2_subdev_has_route(struct v4l2_subdev_krouting *routing,
+ unsigned int pad0, unsigned int pad1);
+
#endif
Add helper functions for routing. These helpers make it easier for the drivers to use struct v4l2_subdev_krouting. TODO: add docs TODO: fix according to comments Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- drivers/media/v4l2-core/v4l2-subdev.c | 89 +++++++++++++++++++++++++++ include/media/v4l2-subdev.h | 15 +++++ 2 files changed, 104 insertions(+)