[media] media: Add link_validate() op to check links to the sink pad
authorSakari Ailus <sakari.ailus@iki.fi>
Wed, 11 Jan 2012 09:25:15 +0000 (06:25 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 14 May 2012 11:44:11 +0000 (08:44 -0300)
The purpose of the link_validate() op is to allow an entity driver to ensure
that the properties of the pads at the both ends of the link are suitable
for starting the pipeline. link_validate is called on sink pads on active
links which belong to the active part of the graph.

Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Documentation/media-framework.txt
drivers/media/media-entity.c
include/media/media-entity.h

index 3a0f879..8028754 100644 (file)
@@ -335,6 +335,9 @@ the media_entity pipe field.
 Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
 be identical for all nested calls to the function.
 
+media_entity_pipeline_start() may return an error. In that case, it will
+clean up any the changes it did by itself.
+
 When stopping the stream, drivers must notify the entities with
 
        media_entity_pipeline_stop(struct media_entity *entity);
@@ -351,3 +354,19 @@ If other operations need to be disallowed on streaming entities (such as
 changing entities configuration parameters) drivers can explicitly check the
 media_entity stream_count field to find out if an entity is streaming. This
 operation must be done with the media_device graph_mutex held.
+
+
+Link validation
+---------------
+
+Link validation is performed by media_entity_pipeline_start() for any
+entity which has sink pads in the pipeline. The
+media_entity::link_validate() callback is used for that purpose. In
+link_validate() callback, entity driver should check that the properties of
+the source pad of the connected entity and its own sink pad match. It is up
+to the type of the entity (and in the end, the properties of the hardware)
+what matching actually means.
+
+Subsystems should facilitate link validation by providing subsystem specific
+helper functions to provide easy access for commonly needed information, and
+in the end provide a way to use driver-specific callbacks.
index 056138f..e1cd132 100644 (file)
@@ -214,23 +214,76 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
  * pipeline pointer must be identical for all nested calls to
  * media_entity_pipeline_start().
  */
-void media_entity_pipeline_start(struct media_entity *entity,
-                                struct media_pipeline *pipe)
+__must_check int media_entity_pipeline_start(struct media_entity *entity,
+                                            struct media_pipeline *pipe)
 {
        struct media_device *mdev = entity->parent;
        struct media_entity_graph graph;
+       struct media_entity *entity_err = entity;
+       int ret;
 
        mutex_lock(&mdev->graph_mutex);
 
        media_entity_graph_walk_start(&graph, entity);
 
        while ((entity = media_entity_graph_walk_next(&graph))) {
+               unsigned int i;
+
                entity->stream_count++;
                WARN_ON(entity->pipe && entity->pipe != pipe);
                entity->pipe = pipe;
+
+               /* Already streaming --- no need to check. */
+               if (entity->stream_count > 1)
+                       continue;
+
+               if (!entity->ops || !entity->ops->link_validate)
+                       continue;
+
+               for (i = 0; i < entity->num_links; i++) {
+                       struct media_link *link = &entity->links[i];
+
+                       /* Is this pad part of an enabled link? */
+                       if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+                               continue;
+
+                       /* Are we the sink or not? */
+                       if (link->sink->entity != entity)
+                               continue;
+
+                       ret = entity->ops->link_validate(link);
+                       if (ret < 0 && ret != -ENOIOCTLCMD)
+                               goto error;
+               }
        }
 
        mutex_unlock(&mdev->graph_mutex);
+
+       return 0;
+
+error:
+       /*
+        * Link validation on graph failed. We revert what we did and
+        * return the error.
+        */
+       media_entity_graph_walk_start(&graph, entity_err);
+
+       while ((entity_err = media_entity_graph_walk_next(&graph))) {
+               entity_err->stream_count--;
+               if (entity_err->stream_count == 0)
+                       entity_err->pipe = NULL;
+
+               /*
+                * We haven't increased stream_count further than this
+                * so we quit here.
+                */
+               if (entity_err == entity)
+                       break;
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
 
index 29e7bba..0c16f51 100644 (file)
@@ -46,6 +46,7 @@ struct media_entity_operations {
        int (*link_setup)(struct media_entity *entity,
                          const struct media_pad *local,
                          const struct media_pad *remote, u32 flags);
+       int (*link_validate)(struct media_link *link);
 };
 
 struct media_entity {
@@ -140,8 +141,8 @@ 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);
-void media_entity_pipeline_start(struct media_entity *entity,
-               struct media_pipeline *pipe);
+__must_check int media_entity_pipeline_start(struct media_entity *entity,
+                                            struct media_pipeline *pipe);
 void media_entity_pipeline_stop(struct media_entity *entity);
 
 #define media_entity_call(entity, operation, args...)                  \