[media] media: Add link_validate() op to check links to the sink pad
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>
This commit is contained in:
parent
440f0fadd4
commit
af88be3887
|
@ -335,6 +335,9 @@ the media_entity pipe field.
|
||||||
Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
|
Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
|
||||||
be identical for all nested calls to the function.
|
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
|
When stopping the stream, drivers must notify the entities with
|
||||||
|
|
||||||
media_entity_pipeline_stop(struct media_entity *entity);
|
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
|
changing entities configuration parameters) drivers can explicitly check the
|
||||||
media_entity stream_count field to find out if an entity is streaming. This
|
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.
|
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.
|
||||||
|
|
|
@ -214,23 +214,76 @@ EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
|
||||||
* pipeline pointer must be identical for all nested calls to
|
* pipeline pointer must be identical for all nested calls to
|
||||||
* media_entity_pipeline_start().
|
* media_entity_pipeline_start().
|
||||||
*/
|
*/
|
||||||
void media_entity_pipeline_start(struct media_entity *entity,
|
__must_check int media_entity_pipeline_start(struct media_entity *entity,
|
||||||
struct media_pipeline *pipe)
|
struct media_pipeline *pipe)
|
||||||
{
|
{
|
||||||
struct media_device *mdev = entity->parent;
|
struct media_device *mdev = entity->parent;
|
||||||
struct media_entity_graph graph;
|
struct media_entity_graph graph;
|
||||||
|
struct media_entity *entity_err = entity;
|
||||||
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&mdev->graph_mutex);
|
mutex_lock(&mdev->graph_mutex);
|
||||||
|
|
||||||
media_entity_graph_walk_start(&graph, entity);
|
media_entity_graph_walk_start(&graph, entity);
|
||||||
|
|
||||||
while ((entity = media_entity_graph_walk_next(&graph))) {
|
while ((entity = media_entity_graph_walk_next(&graph))) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
entity->stream_count++;
|
entity->stream_count++;
|
||||||
WARN_ON(entity->pipe && entity->pipe != pipe);
|
WARN_ON(entity->pipe && entity->pipe != 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);
|
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);
|
EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ struct media_entity_operations {
|
||||||
int (*link_setup)(struct media_entity *entity,
|
int (*link_setup)(struct media_entity *entity,
|
||||||
const struct media_pad *local,
|
const struct media_pad *local,
|
||||||
const struct media_pad *remote, u32 flags);
|
const struct media_pad *remote, u32 flags);
|
||||||
|
int (*link_validate)(struct media_link *link);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct media_entity {
|
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 *entity);
|
||||||
struct media_entity *
|
struct media_entity *
|
||||||
media_entity_graph_walk_next(struct media_entity_graph *graph);
|
media_entity_graph_walk_next(struct media_entity_graph *graph);
|
||||||
void media_entity_pipeline_start(struct media_entity *entity,
|
__must_check int media_entity_pipeline_start(struct media_entity *entity,
|
||||||
struct media_pipeline *pipe);
|
struct media_pipeline *pipe);
|
||||||
void media_entity_pipeline_stop(struct media_entity *entity);
|
void media_entity_pipeline_stop(struct media_entity *entity);
|
||||||
|
|
||||||
#define media_entity_call(entity, operation, args...) \
|
#define media_entity_call(entity, operation, args...) \
|
||||||
|
|
Reference in New Issue