aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/media-framework.txt19
-rw-r--r--drivers/media/media-entity.c57
-rw-r--r--include/media/media-entity.h5
3 files changed, 77 insertions, 4 deletions
diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt
index 3a0f879533ce..802875413873 100644
--- a/Documentation/media-framework.txt
+++ b/Documentation/media-framework.txt
@@ -335,6 +335,9 @@ the media_entity pipe field.
335Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must 335Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
336be identical for all nested calls to the function. 336be identical for all nested calls to the function.
337 337
338media_entity_pipeline_start() may return an error. In that case, it will
339clean up any the changes it did by itself.
340
338When stopping the stream, drivers must notify the entities with 341When stopping the stream, drivers must notify the entities with
339 342
340 media_entity_pipeline_stop(struct media_entity *entity); 343 media_entity_pipeline_stop(struct media_entity *entity);
@@ -351,3 +354,19 @@ If other operations need to be disallowed on streaming entities (such as
351changing entities configuration parameters) drivers can explicitly check the 354changing entities configuration parameters) drivers can explicitly check the
352media_entity stream_count field to find out if an entity is streaming. This 355media_entity stream_count field to find out if an entity is streaming. This
353operation must be done with the media_device graph_mutex held. 356operation must be done with the media_device graph_mutex held.
357
358
359Link validation
360---------------
361
362Link validation is performed by media_entity_pipeline_start() for any
363entity which has sink pads in the pipeline. The
364media_entity::link_validate() callback is used for that purpose. In
365link_validate() callback, entity driver should check that the properties of
366the source pad of the connected entity and its own sink pad match. It is up
367to the type of the entity (and in the end, the properties of the hardware)
368what matching actually means.
369
370Subsystems should facilitate link validation by providing subsystem specific
371helper functions to provide easy access for commonly needed information, and
372in the end provide a way to use driver-specific callbacks.
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 056138f63c7d..e1cd13283407 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -214,23 +214,76 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
214 * pipeline pointer must be identical for all nested calls to 214 * pipeline pointer must be identical for all nested calls to
215 * media_entity_pipeline_start(). 215 * media_entity_pipeline_start().
216 */ 216 */
217void media_entity_pipeline_start(struct media_entity *entity, 217__must_check int media_entity_pipeline_start(struct media_entity *entity,
218 struct media_pipeline *pipe) 218 struct media_pipeline *pipe)
219{ 219{
220 struct media_device *mdev = entity->parent; 220 struct media_device *mdev = entity->parent;
221 struct media_entity_graph graph; 221 struct media_entity_graph graph;
222 struct media_entity *entity_err = entity;
223 int ret;
222 224
223 mutex_lock(&mdev->graph_mutex); 225 mutex_lock(&mdev->graph_mutex);
224 226
225 media_entity_graph_walk_start(&graph, entity); 227 media_entity_graph_walk_start(&graph, entity);
226 228
227 while ((entity = media_entity_graph_walk_next(&graph))) { 229 while ((entity = media_entity_graph_walk_next(&graph))) {
230 unsigned int i;
231
228 entity->stream_count++; 232 entity->stream_count++;
229 WARN_ON(entity->pipe && entity->pipe != pipe); 233 WARN_ON(entity->pipe && entity->pipe != pipe);
230 entity->pipe = pipe; 234 entity->pipe = pipe;
235
236 /* Already streaming --- no need to check. */
237 if (entity->stream_count > 1)
238 continue;
239
240 if (!entity->ops || !entity->ops->link_validate)
241 continue;
242
243 for (i = 0; i < entity->num_links; i++) {
244 struct media_link *link = &entity->links[i];
245
246 /* Is this pad part of an enabled link? */
247 if (!(link->flags & MEDIA_LNK_FL_ENABLED))
248 continue;
249
250 /* Are we the sink or not? */
251 if (link->sink->entity != entity)
252 continue;
253
254 ret = entity->ops->link_validate(link);
255 if (ret < 0 && ret != -ENOIOCTLCMD)
256 goto error;
257 }
231 } 258 }
232 259
233 mutex_unlock(&mdev->graph_mutex); 260 mutex_unlock(&mdev->graph_mutex);
261
262 return 0;
263
264error:
265 /*
266 * Link validation on graph failed. We revert what we did and
267 * return the error.
268 */
269 media_entity_graph_walk_start(&graph, entity_err);
270
271 while ((entity_err = media_entity_graph_walk_next(&graph))) {
272 entity_err->stream_count--;
273 if (entity_err->stream_count == 0)
274 entity_err->pipe = NULL;
275
276 /*
277 * We haven't increased stream_count further than this
278 * so we quit here.
279 */
280 if (entity_err == entity)
281 break;
282 }
283
284 mutex_unlock(&mdev->graph_mutex);
285
286 return ret;
234} 287}
235EXPORT_SYMBOL_GPL(media_entity_pipeline_start); 288EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
236 289
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 29e7bba78ffe..0c16f518ee09 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -46,6 +46,7 @@ struct media_entity_operations {
46 int (*link_setup)(struct media_entity *entity, 46 int (*link_setup)(struct media_entity *entity,
47 const struct media_pad *local, 47 const struct media_pad *local,
48 const struct media_pad *remote, u32 flags); 48 const struct media_pad *remote, u32 flags);
49 int (*link_validate)(struct media_link *link);
49}; 50};
50 51
51struct media_entity { 52struct media_entity {
@@ -140,8 +141,8 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph,
140 struct media_entity *entity); 141 struct media_entity *entity);
141struct media_entity * 142struct media_entity *
142media_entity_graph_walk_next(struct media_entity_graph *graph); 143media_entity_graph_walk_next(struct media_entity_graph *graph);
143void media_entity_pipeline_start(struct media_entity *entity, 144__must_check int media_entity_pipeline_start(struct media_entity *entity,
144 struct media_pipeline *pipe); 145 struct media_pipeline *pipe);
145void media_entity_pipeline_stop(struct media_entity *entity); 146void media_entity_pipeline_stop(struct media_entity *entity);
146 147
147#define media_entity_call(entity, operation, args...) \ 148#define media_entity_call(entity, operation, args...) \