mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-07-16 14:27:48 +00:00
07e8c30da9
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
229 lines
7.4 KiB
Diff
229 lines
7.4 KiB
Diff
From 5b45472e8a692e6acea3cb6d601b44c17ea8d59e Mon Sep 17 00:00:00 2001
|
|
From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
|
|
Date: Sun, 7 Mar 2010 21:14:14 +0200
|
|
Subject: [PATCH 11/43] media: Entity graph traversal
|
|
|
|
Add media entity graph traversal. The traversal follows enabled links by
|
|
depth first. Traversing graph backwards is prevented by comparing the next
|
|
possible entity in the graph with the previous one. Multiply connected
|
|
graphs are thus not supported.
|
|
|
|
Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
|
|
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
|
Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
|
|
---
|
|
Documentation/media-framework.txt | 42 +++++++++++++
|
|
drivers/media/media-entity.c | 115 +++++++++++++++++++++++++++++++++++++
|
|
include/media/media-entity.h | 15 +++++
|
|
3 files changed, 172 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
|
|
index b252cf9..88fe379 100644
|
|
--- a/Documentation/media-framework.txt
|
|
+++ b/Documentation/media-framework.txt
|
|
@@ -216,3 +216,45 @@ Links have flags that describe the link capabilities and state.
|
|
modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then
|
|
MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always
|
|
enabled.
|
|
+
|
|
+
|
|
+Graph traversal
|
|
+---------------
|
|
+
|
|
+The media framework provides APIs to iterate over entities in a graph.
|
|
+
|
|
+To iterate over all entities belonging to a media device, drivers can use the
|
|
+media_device_for_each_entity macro, defined in include/media/media-device.h.
|
|
+
|
|
+ struct media_entity *entity;
|
|
+
|
|
+ media_device_for_each_entity(entity, mdev) {
|
|
+ /* entity will point to each entity in turn */
|
|
+ ...
|
|
+ }
|
|
+
|
|
+Drivers might also need to iterate over all entities in a graph that can be
|
|
+reached only through enabled links starting at a given entity. The media
|
|
+framework provides a depth-first graph traversal API for that purpose.
|
|
+
|
|
+Note that graphs with cycles (whether directed or undirected) are *NOT*
|
|
+supported by the graph traversal API. To prevent infinite loops, the graph
|
|
+traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH,
|
|
+currently defined as 16.
|
|
+
|
|
+Drivers initiate a graph traversal by calling
|
|
+
|
|
+ media_entity_graph_walk_start(struct media_entity_graph *graph,
|
|
+ struct media_entity *entity);
|
|
+
|
|
+The graph structure, provided by the caller, is initialized to start graph
|
|
+traversal at the given entity.
|
|
+
|
|
+Drivers can then retrieve the next entity by calling
|
|
+
|
|
+ media_entity_graph_walk_next(struct media_entity_graph *graph);
|
|
+
|
|
+When the graph traversal is complete the function will return NULL.
|
|
+
|
|
+Graph traversal can be interrupted at any moment. No cleanup function call is
|
|
+required and the graph structure can be freed normally.
|
|
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
|
|
index e4ba2bc..a805f20 100644
|
|
--- a/drivers/media/media-entity.c
|
|
+++ b/drivers/media/media-entity.c
|
|
@@ -84,6 +84,121 @@ media_entity_cleanup(struct media_entity *entity)
|
|
}
|
|
EXPORT_SYMBOL_GPL(media_entity_cleanup);
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
+ * Graph traversal
|
|
+ */
|
|
+
|
|
+static struct media_entity *
|
|
+media_entity_other(struct media_entity *entity, struct media_link *link)
|
|
+{
|
|
+ if (link->source->entity == entity)
|
|
+ return link->sink->entity;
|
|
+ else
|
|
+ return link->source->entity;
|
|
+}
|
|
+
|
|
+/* push an entity to traversal stack */
|
|
+static void stack_push(struct media_entity_graph *graph,
|
|
+ struct media_entity *entity)
|
|
+{
|
|
+ if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
|
|
+ WARN_ON(1);
|
|
+ return;
|
|
+ }
|
|
+ graph->top++;
|
|
+ graph->stack[graph->top].link = 0;
|
|
+ graph->stack[graph->top].entity = entity;
|
|
+}
|
|
+
|
|
+static struct media_entity *stack_pop(struct media_entity_graph *graph)
|
|
+{
|
|
+ struct media_entity *entity;
|
|
+
|
|
+ entity = graph->stack[graph->top].entity;
|
|
+ graph->top--;
|
|
+
|
|
+ return entity;
|
|
+}
|
|
+
|
|
+#define stack_peek(en) ((en)->stack[(en)->top - 1].entity)
|
|
+#define link_top(en) ((en)->stack[(en)->top].link)
|
|
+#define stack_top(en) ((en)->stack[(en)->top].entity)
|
|
+
|
|
+/**
|
|
+ * media_entity_graph_walk_start - Start walking the media graph at a given entity
|
|
+ * @graph: Media graph structure that will be used to walk the graph
|
|
+ * @entity: Starting entity
|
|
+ *
|
|
+ * This function initializes the graph traversal structure to walk the entities
|
|
+ * graph starting at the given entity. The traversal structure must not be
|
|
+ * modified by the caller during graph traversal. When done the structure can
|
|
+ * safely be freed.
|
|
+ */
|
|
+void media_entity_graph_walk_start(struct media_entity_graph *graph,
|
|
+ struct media_entity *entity)
|
|
+{
|
|
+ graph->top = 0;
|
|
+ graph->stack[graph->top].entity = NULL;
|
|
+ stack_push(graph, entity);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
|
|
+
|
|
+/**
|
|
+ * media_entity_graph_walk_next - Get the next entity in the graph
|
|
+ * @graph: Media graph structure
|
|
+ *
|
|
+ * Perform a depth-first traversal of the given media entities graph.
|
|
+ *
|
|
+ * The graph structure must have been previously initialized with a call to
|
|
+ * media_entity_graph_walk_start().
|
|
+ *
|
|
+ * Return the next entity in the graph or NULL if the whole graph have been
|
|
+ * traversed.
|
|
+ */
|
|
+struct media_entity *
|
|
+media_entity_graph_walk_next(struct media_entity_graph *graph)
|
|
+{
|
|
+ if (stack_top(graph) == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ /*
|
|
+ * Depth first search. Push entity to stack and continue from
|
|
+ * top of the stack until no more entities on the level can be
|
|
+ * found.
|
|
+ */
|
|
+ while (link_top(graph) < stack_top(graph)->num_links) {
|
|
+ struct media_entity *entity = stack_top(graph);
|
|
+ struct media_link *link = &entity->links[link_top(graph)];
|
|
+ struct media_entity *next;
|
|
+
|
|
+ /* The link is not enabled so we do not follow. */
|
|
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
|
|
+ link_top(graph)++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Get the entity in the other end of the link . */
|
|
+ next = media_entity_other(entity, link);
|
|
+
|
|
+ /* Was it the entity we came here from? */
|
|
+ if (next == stack_peek(graph)) {
|
|
+ link_top(graph)++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Push the new entity to stack and start over. */
|
|
+ link_top(graph)++;
|
|
+ stack_push(graph, next);
|
|
+ }
|
|
+
|
|
+ return stack_pop(graph);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
|
|
+
|
|
+/* -----------------------------------------------------------------------------
|
|
+ * Links management
|
|
+ */
|
|
+
|
|
static struct media_link *media_entity_add_link(struct media_entity *entity)
|
|
{
|
|
if (entity->num_links >= entity->max_links) {
|
|
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
|
|
index 7cf9135..b82f824 100644
|
|
--- a/include/media/media-entity.h
|
|
+++ b/include/media/media-entity.h
|
|
@@ -113,10 +113,25 @@ static inline u32 media_entity_subtype(struct media_entity *entity)
|
|
return entity->type & MEDIA_ENT_SUBTYPE_MASK;
|
|
}
|
|
|
|
+#define MEDIA_ENTITY_ENUM_MAX_DEPTH 16
|
|
+
|
|
+struct media_entity_graph {
|
|
+ struct {
|
|
+ struct media_entity *entity;
|
|
+ int link;
|
|
+ } stack[MEDIA_ENTITY_ENUM_MAX_DEPTH];
|
|
+ int top;
|
|
+};
|
|
+
|
|
int media_entity_init(struct media_entity *entity, u16 num_pads,
|
|
struct media_pad *pads, u16 extra_links);
|
|
void media_entity_cleanup(struct media_entity *entity);
|
|
int media_entity_create_link(struct media_entity *source, u16 source_pad,
|
|
struct media_entity *sink, u16 sink_pad, u32 flags);
|
|
|
|
+void media_entity_graph_walk_start(struct media_entity_graph *graph,
|
|
+ struct media_entity *entity);
|
|
+struct media_entity *
|
|
+media_entity_graph_walk_next(struct media_entity_graph *graph);
|
|
+
|
|
#endif
|
|
--
|
|
1.6.6.1
|
|
|