diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch b/extras/recipes-kernel/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch new file mode 100644 index 00000000..15fc6123 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap/media/0011-media-Entity-graph-traversal.patch @@ -0,0 +1,228 @@ +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 + |