[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-omap / media / 0016-media-Pipelines-and-media-streams.patch
1 From 4e07e9ada1b3baaec6d4948eccf3c0499e3228df Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Wed, 25 Aug 2010 15:00:41 +0300
4 Subject: [PATCH 16/43] media: Pipelines and media streams
6 Drivers often need to associate pipeline objects to entities, and to
7 take stream state into account when configuring entities and links. The
8 pipeline API helps drivers manage that information.
10 When starting streaming, drivers call media_entity_pipeline_start(). The
11 function marks all entities connected to the given entity through
12 enabled links, either directly or indirectly, as streaming. Similarly,
13 when stopping the stream, drivers call media_entity_pipeline_stop().
15 The media_entity_pipeline_start() function takes a pointer to a media
16 pipeline and stores it in every entity in the graph. Drivers should
17 embed the media_pipeline structure in higher-level pipeline structures
18 and can then access the pipeline through the media_entity structure.
20 Link configuration will fail with -EBUSY by default if either end of the
21 link is a streaming entity, unless the link is marked with the
22 MEDIA_LNK_FL_DYNAMIC flag.
24 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
25 ---
26 Documentation/DocBook/v4l/media-ioc-enum-links.xml | 5 ++
27 Documentation/DocBook/v4l/media-ioc-setup-link.xml | 3 +
28 Documentation/media-framework.txt | 38 ++++++++++
29 drivers/media/media-entity.c | 73 ++++++++++++++++++++
30 include/linux/media.h | 1 +
31 include/media/media-entity.h | 10 +++
32 6 files changed, 130 insertions(+), 0 deletions(-)
34 diff --git a/Documentation/DocBook/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
35 index daf0360..b204bfb 100644
36 --- a/Documentation/DocBook/v4l/media-ioc-enum-links.xml
37 +++ b/Documentation/DocBook/v4l/media-ioc-enum-links.xml
38 @@ -179,6 +179,11 @@
39 <entry>The link enabled state can't be modified at runtime. An
40 immutable link is always enabled.</entry>
41 </row>
42 + <row>
43 + <entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry>
44 + <entry>The link enabled state can be modified during streaming. This
45 + flag is set by drivers and is read-only for applications.</entry>
46 + </row>
47 </tbody>
48 </tgroup>
49 </table>
50 diff --git a/Documentation/DocBook/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
51 index 09ab3d2..2331e76 100644
52 --- a/Documentation/DocBook/v4l/media-ioc-setup-link.xml
53 +++ b/Documentation/DocBook/v4l/media-ioc-setup-link.xml
54 @@ -60,6 +60,9 @@
55 <para>Link configuration has no side effect on other links. If an enabled
56 link at the sink pad prevents the link from being enabled, the driver
57 returns with an &EBUSY;.</para>
58 + <para>Only links marked with the <constant>DYNAMIC</constant> link flag can
59 + be enabled/disabled while streaming media data. Attempting to enable or
60 + disable a streaming non-dynamic link will return an &EBUSY;.</para>
61 <para>If the specified link can't be found the driver returns with an
62 &EINVAL;.</para>
63 </refsect1>
64 diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
65 index 634845e..435d0c4 100644
66 --- a/Documentation/media-framework.txt
67 +++ b/Documentation/media-framework.txt
68 @@ -313,3 +313,41 @@ Link configuration must not have any side effect on other links. If an enabled
69 link at a sink pad prevents another link at the same pad from being disabled,
70 the link_setup operation must return -EBUSY and can't implicitly disable the
71 first enabled link.
72 +
73 +
74 +Pipelines and media streams
75 +---------------------------
76 +
77 +When starting streaming, drivers must notify all entities in the pipeline to
78 +prevent link states from being modified during streaming by calling
79 +
80 + media_entity_pipeline_start(struct media_entity *entity,
81 + struct media_pipeline *pipe);
82 +
83 +The function will mark all entities connected to the given entity through
84 +enabled links, either directly or indirectly, as streaming.
85 +
86 +The media_pipeline instance pointed to by the pipe argument will be stored in
87 +every entity in the pipeline. Drivers should embed the media_pipeline structure
88 +in higher-level pipeline structures and can then access the pipeline through
89 +the media_entity pipe field.
90 +
91 +Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
92 +be identical for all nested calls to the function.
93 +
94 +When stopping the stream, drivers must notify the entities with
95 +
96 + media_entity_pipeline_stop(struct media_entity *entity);
97 +
98 +If multiple calls to media_entity_pipeline_start() have been made the same
99 +number of media_entity_pipeline_stop() calls are required to stop streaming. The
100 +media_entity pipe field is reset to NULL on the last nested stop call.
101 +
102 +Link configuration will fail with -EBUSY by default if either end of the link is
103 +a streaming entity. Links that can be modified while streaming must be marked
104 +with the MEDIA_LNK_FL_DYNAMIC flag.
105 +
106 +If other operations need to be disallowed on streaming entities (such as
107 +changing entities configuration parameters) drivers can explictly check the
108 +media_entity stream_count field to find out if an entity is streaming. This
109 +operation must be done with the media_device graph_mutex held.
110 diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
111 index d703ce8..e63e089 100644
112 --- a/drivers/media/media-entity.c
113 +++ b/drivers/media/media-entity.c
114 @@ -197,6 +197,75 @@ media_entity_graph_walk_next(struct media_entity_graph *graph)
115 EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
117 /* -----------------------------------------------------------------------------
118 + * Pipeline management
119 + */
120 +
121 +/**
122 + * media_entity_pipeline_start - Mark a pipeline as streaming
123 + * @entity: Starting entity
124 + * @pipe: Media pipeline to be assigned to all entities in the pipeline.
125 + *
126 + * Mark all entities connected to a given entity through enabled links, either
127 + * directly or indirectly, as streaming. The given pipeline object is assigned to
128 + * every entity in the pipeline and stored in the media_entity pipe field.
129 + *
130 + * Calls to this function can be nested, in which case the same number of
131 + * media_entity_pipeline_stop() calls will be required to stop streaming. The
132 + * pipeline pointer must be identical for all nested calls to
133 + * media_entity_pipeline_start().
134 + */
135 +void media_entity_pipeline_start(struct media_entity *entity,
136 + struct media_pipeline *pipe)
137 +{
138 + struct media_device *mdev = entity->parent;
139 + struct media_entity_graph graph;
140 +
141 + mutex_lock(&mdev->graph_mutex);
142 +
143 + media_entity_graph_walk_start(&graph, entity);
144 +
145 + while ((entity = media_entity_graph_walk_next(&graph))) {
146 + entity->stream_count++;
147 + WARN_ON(entity->pipe && entity->pipe != pipe);
148 + entity->pipe = pipe;
149 + }
150 +
151 + mutex_unlock(&mdev->graph_mutex);
152 +}
153 +EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
154 +
155 +/**
156 + * media_entity_pipeline_stop - Mark a pipeline as not streaming
157 + * @entity: Starting entity
158 + *
159 + * Mark all entities connected to a given entity through enabled links, either
160 + * directly or indirectly, as not streaming. The media_entity pipe field is
161 + * reset to NULL.
162 + *
163 + * If multiple calls to media_entity_pipeline_start() have been made, the same
164 + * number of calls to this function are required to mark the pipeline as not
165 + * streaming.
166 + */
167 +void media_entity_pipeline_stop(struct media_entity *entity)
168 +{
169 + struct media_device *mdev = entity->parent;
170 + struct media_entity_graph graph;
171 +
172 + mutex_lock(&mdev->graph_mutex);
173 +
174 + media_entity_graph_walk_start(&graph, entity);
175 +
176 + while ((entity = media_entity_graph_walk_next(&graph))) {
177 + entity->stream_count--;
178 + if (entity->stream_count == 0)
179 + entity->pipe = NULL;
180 + }
181 +
182 + mutex_unlock(&mdev->graph_mutex);
183 +}
184 +EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
185 +
186 +/* -----------------------------------------------------------------------------
187 * Module use count
188 */
190 @@ -364,6 +433,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
191 source = link->source->entity;
192 sink = link->sink->entity;
194 + if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
195 + (source->stream_count || sink->stream_count))
196 + return -EBUSY;
197 +
198 mdev = source->parent;
200 if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) {
201 diff --git a/include/linux/media.h b/include/linux/media.h
202 index 2f67ed2..29039e8 100644
203 --- a/include/linux/media.h
204 +++ b/include/linux/media.h
205 @@ -106,6 +106,7 @@ struct media_pad_desc {
207 #define MEDIA_LNK_FL_ENABLED (1 << 0)
208 #define MEDIA_LNK_FL_IMMUTABLE (1 << 1)
209 +#define MEDIA_LNK_FL_DYNAMIC (1 << 2)
211 struct media_link_desc {
212 struct media_pad_desc source;
213 diff --git a/include/media/media-entity.h b/include/media/media-entity.h
214 index 60fc7bd..450ba12 100644
215 --- a/include/media/media-entity.h
216 +++ b/include/media/media-entity.h
217 @@ -26,6 +26,9 @@
218 #include <linux/list.h>
219 #include <linux/media.h>
221 +struct media_pipeline {
222 +};
223 +
224 struct media_link {
225 struct media_pad *source; /* Source pad */
226 struct media_pad *sink; /* Sink pad */
227 @@ -67,8 +70,11 @@ struct media_entity {
229 const struct media_entity_operations *ops; /* Entity operations */
231 + int stream_count; /* Stream count for the entity. */
232 int use_count; /* Use count for the entity. */
234 + struct media_pipeline *pipe; /* Pipeline this entity belongs to. */
235 +
236 union {
237 /* Node specifications */
238 struct {
239 @@ -114,6 +120,7 @@ struct media_entity_graph {
240 int media_entity_init(struct media_entity *entity, u16 num_pads,
241 struct media_pad *pads, u16 extra_links);
242 void media_entity_cleanup(struct media_entity *entity);
243 +
244 int media_entity_create_link(struct media_entity *source, u16 source_pad,
245 struct media_entity *sink, u16 sink_pad, u32 flags);
246 int __media_entity_setup_link(struct media_link *link, u32 flags);
247 @@ -129,6 +136,9 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph,
248 struct media_entity *entity);
249 struct media_entity *
250 media_entity_graph_walk_next(struct media_entity_graph *graph);
251 +void media_entity_pipeline_start(struct media_entity *entity,
252 + struct media_pipeline *pipe);
253 +void media_entity_pipeline_stop(struct media_entity *entity);
255 #define media_entity_call(entity, operation, args...) \
256 (((entity)->ops && (entity)->ops->operation) ? \
257 --
258 1.6.6.1