diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch')
-rw-r--r-- | extras/recipes-kernel/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch b/extras/recipes-kernel/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch new file mode 100644 index 00000000..969162f8 --- /dev/null +++ b/extras/recipes-kernel/linux/linux-omap/media/0016-media-Pipelines-and-media-streams.patch | |||
@@ -0,0 +1,259 @@ | |||
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 | ||
5 | |||
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. | ||
9 | |||
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(). | ||
14 | |||
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. | ||
19 | |||
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. | ||
23 | |||
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(-) | ||
33 | |||
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); | ||
116 | |||
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 | */ | ||
189 | |||
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; | ||
193 | |||
194 | + if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) && | ||
195 | + (source->stream_count || sink->stream_count)) | ||
196 | + return -EBUSY; | ||
197 | + | ||
198 | mdev = source->parent; | ||
199 | |||
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 { | ||
206 | |||
207 | #define MEDIA_LNK_FL_ENABLED (1 << 0) | ||
208 | #define MEDIA_LNK_FL_IMMUTABLE (1 << 1) | ||
209 | +#define MEDIA_LNK_FL_DYNAMIC (1 << 2) | ||
210 | |||
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> | ||
220 | |||
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 { | ||
228 | |||
229 | const struct media_entity_operations *ops; /* Entity operations */ | ||
230 | |||
231 | + int stream_count; /* Stream count for the entity. */ | ||
232 | int use_count; /* Use count for the entity. */ | ||
233 | |||
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); | ||
254 | |||
255 | #define media_entity_call(entity, operation, args...) \ | ||
256 | (((entity)->ops && (entity)->ops->operation) ? \ | ||
257 | -- | ||
258 | 1.6.6.1 | ||
259 | |||