Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[pandora-kernel.git] / drivers / media / media-entity.c
index 6795c92..23640ed 100644 (file)
@@ -196,6 +196,75 @@ media_entity_graph_walk_next(struct media_entity_graph *graph)
 }
 EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
 
+/* -----------------------------------------------------------------------------
+ * Pipeline management
+ */
+
+/**
+ * media_entity_pipeline_start - Mark a pipeline as streaming
+ * @entity: Starting entity
+ * @pipe: Media pipeline to be assigned to all entities in the pipeline.
+ *
+ * Mark all entities connected to a given entity through enabled links, either
+ * directly or indirectly, as streaming. The given pipeline object is assigned to
+ * every entity in the pipeline and stored in the media_entity pipe field.
+ *
+ * Calls to this function can be nested, in which case the same number of
+ * media_entity_pipeline_stop() calls will be required to stop streaming. The
+ * 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)
+{
+       struct media_device *mdev = entity->parent;
+       struct media_entity_graph graph;
+
+       mutex_lock(&mdev->graph_mutex);
+
+       media_entity_graph_walk_start(&graph, entity);
+
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+               entity->stream_count++;
+               WARN_ON(entity->pipe && entity->pipe != pipe);
+               entity->pipe = pipe;
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+}
+EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
+
+/**
+ * media_entity_pipeline_stop - Mark a pipeline as not streaming
+ * @entity: Starting entity
+ *
+ * Mark all entities connected to a given entity through enabled links, either
+ * directly or indirectly, as not streaming. The media_entity pipe field is
+ * reset to NULL.
+ *
+ * If multiple calls to media_entity_pipeline_start() have been made, the same
+ * number of calls to this function are required to mark the pipeline as not
+ * streaming.
+ */
+void media_entity_pipeline_stop(struct media_entity *entity)
+{
+       struct media_device *mdev = entity->parent;
+       struct media_entity_graph graph;
+
+       mutex_lock(&mdev->graph_mutex);
+
+       media_entity_graph_walk_start(&graph, entity);
+
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+               entity->stream_count--;
+               if (entity->stream_count == 0)
+                       entity->pipe = NULL;
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+}
+EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
+
 /* -----------------------------------------------------------------------------
  * Module use count
  */
@@ -364,6 +433,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
        source = link->source->entity;
        sink = link->sink->entity;
 
+       if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
+           (source->stream_count || sink->stream_count))
+               return -EBUSY;
+
        mdev = source->parent;
 
        if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) {