diff options
Diffstat (limited to 'include/media/media-entity.h')
| -rw-r--r-- | include/media/media-entity.h | 521 |
1 files changed, 446 insertions, 75 deletions
diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 754182d29668..b91ff6f8c3bb 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Media entity * @@ -5,15 +6,6 @@ * * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com> * Sakari Ailus <sakari.ailus@iki.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef _MEDIA_ENTITY_H @@ -21,10 +13,12 @@ #include <linux/bitmap.h> #include <linux/bug.h> +#include <linux/container_of.h> #include <linux/fwnode.h> -#include <linux/kernel.h> #include <linux/list.h> #include <linux/media.h> +#include <linux/minmax.h> +#include <linux/types.h> /* Enums used internally at the media controller to represent graphs */ @@ -88,6 +82,8 @@ struct media_entity_enum { * @stack: Graph traversal stack; the stack contains information * on the path the media entities to be walked and the * links through which they were reached. + * @stack.entity: pointer to &struct media_entity at the graph. + * @stack.link: pointer to &struct list_head. * @ent_enum: Visited entities * @top: The top of the stack */ @@ -104,12 +100,54 @@ struct media_graph { /** * struct media_pipeline - Media pipeline related information * - * @streaming_count: Streaming start count - streaming stop count - * @graph: Media graph walk during pipeline start / stop + * @allocated: Media pipeline allocated and freed by the framework + * @mdev: The media device the pipeline is part of + * @pads: List of media_pipeline_pad + * @start_count: Media pipeline start - stop count */ struct media_pipeline { - int streaming_count; - struct media_graph graph; + bool allocated; + struct media_device *mdev; + struct list_head pads; + int start_count; +}; + +/** + * struct media_pipeline_pad - A pad part of a media pipeline + * + * @list: Entry in the media_pad pads list + * @pipe: The media_pipeline that the pad is part of + * @pad: The media pad + * + * This structure associate a pad with a media pipeline. Instances of + * media_pipeline_pad are created by media_pipeline_start() when it builds the + * pipeline, and stored in the &media_pad.pads list. media_pipeline_stop() + * removes the entries from the list and deletes them. + */ +struct media_pipeline_pad { + struct list_head list; + struct media_pipeline *pipe; + struct media_pad *pad; +}; + +/** + * struct media_pipeline_pad_iter - Iterator for media_pipeline_for_each_pad + * + * @cursor: The current element + */ +struct media_pipeline_pad_iter { + struct list_head *cursor; +}; + +/** + * struct media_pipeline_entity_iter - Iterator for media_pipeline_for_each_entity + * + * @ent_enum: The entity enumeration tracker + * @cursor: The current element + */ +struct media_pipeline_entity_iter { + struct media_entity_enum ent_enum; + struct list_head *cursor; }; /** @@ -154,20 +192,60 @@ struct media_link { }; /** + * enum media_pad_signal_type - type of the signal inside a media pad + * + * @PAD_SIGNAL_DEFAULT: + * Default signal. Use this when all inputs or all outputs are + * uniquely identified by the pad number. + * @PAD_SIGNAL_ANALOG: + * The pad contains an analog signal. It can be Radio Frequency, + * Intermediate Frequency, a baseband signal or sub-carriers. + * Tuner inputs, IF-PLL demodulators, composite and s-video signals + * should use it. + * @PAD_SIGNAL_DV: + * Contains a digital video signal, with can be a bitstream of samples + * taken from an analog TV video source. On such case, it usually + * contains the VBI data on it. + * @PAD_SIGNAL_AUDIO: + * Contains an Intermediate Frequency analog signal from an audio + * sub-carrier or an audio bitstream. IF signals are provided by tuners + * and consumed by audio AM/FM decoders. Bitstream audio is provided by + * an audio decoder. + */ +enum media_pad_signal_type { + PAD_SIGNAL_DEFAULT = 0, + PAD_SIGNAL_ANALOG, + PAD_SIGNAL_DV, + PAD_SIGNAL_AUDIO, +}; + +/** * struct media_pad - A media pad graph object. * * @graph_obj: Embedded structure containing the media object common data * @entity: Entity this pad belongs to * @index: Pad index in the entity pads array, numbered from 0 to n + * @num_links: Number of links connected to this pad + * @sig_type: Type of the signal inside a media pad * @flags: Pad flags, as defined in * :ref:`include/uapi/linux/media.h <media_header>` * (seek for ``MEDIA_PAD_FL_*``) + * @pipe: Pipeline this pad belongs to. Use media_entity_pipeline() to + * access this field. */ struct media_pad { struct media_gobj graph_obj; /* must be first field in struct */ struct media_entity *entity; u16 index; + u16 num_links; + enum media_pad_signal_type sig_type; unsigned long flags; + + /* + * The fields below are private, and should only be accessed via + * appropriate functions. + */ + struct media_pipeline *pipe; }; /** @@ -181,6 +259,16 @@ struct media_pad { * @link_validate: Return whether a link is valid from the entity point of * view. The media_pipeline_start() function * validates all links by calling this operation. Optional. + * @has_pad_interdep: Return whether two pads of the entity are + * interdependent. If two pads are interdependent they are + * part of the same pipeline and enabling one of the pads + * means that the other pad will become "locked" and + * doesn't allow configuration changes. pad0 and pad1 are + * guaranteed to not both be sinks or sources. Never call + * the .has_pad_interdep() operation directly, always use + * media_entity_has_pad_interdep(). + * Optional: If the operation isn't implemented all pads + * will be considered as interdependent. * * .. note:: * @@ -188,11 +276,14 @@ struct media_pad { * mutex held. */ struct media_entity_operations { - int (*get_fwnode_pad)(struct fwnode_endpoint *endpoint); + int (*get_fwnode_pad)(struct media_entity *entity, + struct fwnode_endpoint *endpoint); int (*link_setup)(struct media_entity *entity, const struct media_pad *local, const struct media_pad *remote, u32 flags); int (*link_validate)(struct media_link *link); + bool (*has_pad_interdep)(struct media_entity *entity, unsigned int pad0, + unsigned int pad1); }; /** @@ -242,22 +333,18 @@ enum media_entity_type { * @pads: Pads array with the size defined by @num_pads. * @links: List of data links. * @ops: Entity operations. - * @stream_count: Stream count for the entity. * @use_count: Use count for the entity. - * @pipe: Pipeline this entity belongs to. * @info: Union with devnode information. Kept just for backward * compatibility. - * @major: Devnode major number (zero if not applicable). Kept just - * for backward compatibility. - * @minor: Devnode minor number (zero if not applicable). Kept just - * for backward compatibility. + * @info.dev: Contains device major and minor info. + * @info.dev.major: device node major, if the device is a devnode. + * @info.dev.minor: device node minor, if the device is a devnode. * * .. note:: * - * @stream_count and @use_count reference counts must never be - * negative, but are signed integers on purpose: a simple ``WARN_ON(<0)`` - * check can be used to detect reference count bugs that would make them - * negative. + * The @use_count reference count must never be negative, but is a signed + * integer on purpose: a simple ``WARN_ON(<0)`` check can be used to detect + * reference count bugs that would make it negative. */ struct media_entity { struct media_gobj graph_obj; /* must be first field in struct */ @@ -276,11 +363,8 @@ struct media_entity { const struct media_entity_operations *ops; - int stream_count; int use_count; - struct media_pipeline *pipe; - union { struct { u32 major; @@ -290,6 +374,18 @@ struct media_entity { }; /** + * media_entity_for_each_pad - Iterate on all pads in an entity + * @entity: The entity the pads belong to + * @iter: The iterator pad + * + * Iterate on all pads in a media entity. + */ +#define media_entity_for_each_pad(entity, iter) \ + for (iter = (entity)->pads; \ + iter < &(entity)->pads[(entity)->num_pads]; \ + ++iter) + +/** * struct media_interface - A media interface graph object. * * @graph_obj: embedded graph object @@ -400,15 +496,15 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) } /** - * __media_entity_enum_init - Initialise an entity enumeration + * media_entity_enum_init - Initialise an entity enumeration * * @ent_enum: Entity enumeration to be initialised - * @idx_max: Maximum number of entities in the enumeration + * @mdev: The related media device * - * Return: Returns zero on success or a negative error code. + * Return: zero on success or a negative error code. */ -__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, - int idx_max); +__must_check int media_entity_enum_init(struct media_entity_enum *ent_enum, + struct media_device *mdev); /** * media_entity_enum_cleanup - Release resources of an entity enumeration @@ -531,7 +627,7 @@ static inline bool media_entity_enum_intersects( * @gobj: Pointer to the struct &media_gobj graph object */ #define gobj_to_entity(gobj) \ - container_of(gobj, struct media_entity, graph_obj) + container_of_const(gobj, struct media_entity, graph_obj) /** * gobj_to_pad - returns the struct &media_pad pointer from the @@ -540,7 +636,7 @@ static inline bool media_entity_enum_intersects( * @gobj: Pointer to the struct &media_gobj graph object */ #define gobj_to_pad(gobj) \ - container_of(gobj, struct media_pad, graph_obj) + container_of_const(gobj, struct media_pad, graph_obj) /** * gobj_to_link - returns the struct &media_link pointer from the @@ -549,7 +645,7 @@ static inline bool media_entity_enum_intersects( * @gobj: Pointer to the struct &media_gobj graph object */ #define gobj_to_link(gobj) \ - container_of(gobj, struct media_link, graph_obj) + container_of_const(gobj, struct media_link, graph_obj) /** * gobj_to_intf - returns the struct &media_interface pointer from the @@ -558,7 +654,7 @@ static inline bool media_entity_enum_intersects( * @gobj: Pointer to the struct &media_gobj graph object */ #define gobj_to_intf(gobj) \ - container_of(gobj, struct media_interface, graph_obj) + container_of_const(gobj, struct media_interface, graph_obj) /** * intf_to_devnode - returns the struct media_intf_devnode pointer from the @@ -567,7 +663,7 @@ static inline bool media_entity_enum_intersects( * @intf: Pointer to struct &media_intf_devnode */ #define intf_to_devnode(intf) \ - container_of(intf, struct media_intf_devnode, intf) + container_of_const(intf, struct media_intf_devnode, intf) /** * media_gobj_create - Initialize a graph object @@ -628,8 +724,34 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, * * This function must be called during the cleanup phase after unregistering * the entity (currently, it does nothing). + * + * Calling media_entity_cleanup() on a media_entity whose memory has been + * zeroed but that has not been initialized with media_entity_pad_init() is + * valid and is a no-op. */ -static inline void media_entity_cleanup(struct media_entity *entity) {}; +#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) +static inline void media_entity_cleanup(struct media_entity *entity) {} +#else +#define media_entity_cleanup(entity) do { } while (false) +#endif + +/** + * media_get_pad_index() - retrieves a pad index from an entity + * + * @entity: entity where the pads belong + * @pad_type: the type of the pad, one of MEDIA_PAD_FL_* pad types + * @sig_type: type of signal of the pad to be search + * + * This helper function finds the first pad index inside an entity that + * satisfies both @is_sink and @sig_type conditions. + * + * Return: + * + * On success, return the pad number. If the pad was not found or the media + * entity is a NULL pointer, return -EINVAL. + */ +int media_get_pad_index(struct media_entity *entity, u32 pad_type, + enum media_pad_signal_type sig_type); /** * media_create_pad_link() - creates a link between two entities. @@ -753,7 +875,7 @@ int __media_entity_setup_link(struct media_link *link, u32 flags); * @flags: the requested new link flags * * The only configurable property is the %MEDIA_LNK_FL_ENABLED link flag - * flag to enable/disable a link. Links marked with the + * to enable/disable a link. Links marked with the * %MEDIA_LNK_FL_IMMUTABLE link flag can not be enabled or disabled. * * When a link is enabled or disabled, the media framework calls the @@ -796,7 +918,7 @@ struct media_link *media_entity_find_link(struct media_pad *source, struct media_pad *sink); /** - * media_entity_remote_pad - Find the pad at the remote end of a link + * media_pad_remote_pad_first - Find the first pad at the remote end of a link * @pad: Pad at the local end of the link * * Search for a remote pad connected to the given pad by iterating over all @@ -805,20 +927,135 @@ struct media_link *media_entity_find_link(struct media_pad *source, * Return: returns a pointer to the pad at the remote end of the first found * enabled link, or %NULL if no enabled link has been found. */ -struct media_pad *media_entity_remote_pad(struct media_pad *pad); +struct media_pad *media_pad_remote_pad_first(const struct media_pad *pad); /** - * media_entity_get - Get a reference to the parent module + * media_pad_remote_pad_unique - Find a remote pad connected to a pad + * @pad: The pad + * + * Search for and return a remote pad connected to @pad through an enabled + * link. If multiple (or no) remote pads are found, an error is returned. + * + * The uniqueness constraint makes this helper function suitable for entities + * that support a single active source at a time on a given pad. * + * Return: A pointer to the remote pad, or one of the following error pointers + * if an error occurs: + * + * * -ENOTUNIQ - Multiple links are enabled + * * -ENOLINK - No connected pad found + */ +struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad); + +/** + * media_entity_remote_pad_unique - Find a remote pad connected to an entity * @entity: The entity + * @type: The type of pad to find (MEDIA_PAD_FL_SINK or MEDIA_PAD_FL_SOURCE) + * + * Search for and return a remote pad of @type connected to @entity through an + * enabled link. If multiple (or no) remote pads match these criteria, an error + * is returned. * - * Get a reference to the parent media device module. + * The uniqueness constraint makes this helper function suitable for entities + * that support a single active source or sink at a time. * - * The function will return immediately if @entity is %NULL. + * Return: A pointer to the remote pad, or one of the following error pointers + * if an error occurs: * - * Return: returns a pointer to the entity on success or %NULL on failure. + * * -ENOTUNIQ - Multiple links are enabled + * * -ENOLINK - No connected pad found */ -struct media_entity *media_entity_get(struct media_entity *entity); +struct media_pad * +media_entity_remote_pad_unique(const struct media_entity *entity, + unsigned int type); + +/** + * media_entity_remote_source_pad_unique - Find a remote source pad connected to + * an entity + * @entity: The entity + * + * Search for and return a remote source pad connected to @entity through an + * enabled link. If multiple (or no) remote pads match these criteria, an error + * is returned. + * + * The uniqueness constraint makes this helper function suitable for entities + * that support a single active source at a time. + * + * Return: A pointer to the remote pad, or one of the following error pointers + * if an error occurs: + * + * * -ENOTUNIQ - Multiple links are enabled + * * -ENOLINK - No connected pad found + */ +static inline struct media_pad * +media_entity_remote_source_pad_unique(const struct media_entity *entity) +{ + return media_entity_remote_pad_unique(entity, MEDIA_PAD_FL_SOURCE); +} + +/** + * media_pad_is_streaming - Test if a pad is part of a streaming pipeline + * @pad: The pad + * + * Return: True if the pad is part of a pipeline started with the + * media_pipeline_start() function, false otherwise. + */ +static inline bool media_pad_is_streaming(const struct media_pad *pad) +{ + return pad->pipe; +} + +/** + * media_entity_is_streaming - Test if an entity is part of a streaming pipeline + * @entity: The entity + * + * Return: True if the entity is part of a pipeline started with the + * media_pipeline_start() function, false otherwise. + */ +static inline bool media_entity_is_streaming(const struct media_entity *entity) +{ + struct media_pad *pad; + + media_entity_for_each_pad(entity, pad) { + if (media_pad_is_streaming(pad)) + return true; + } + + return false; +} + +/** + * media_entity_pipeline - Get the media pipeline an entity is part of + * @entity: The entity + * + * DEPRECATED: use media_pad_pipeline() instead. + * + * This function returns the media pipeline that an entity has been associated + * with when constructing the pipeline with media_pipeline_start(). The pointer + * remains valid until media_pipeline_stop() is called. + * + * In general, entities can be part of multiple pipelines, when carrying + * multiple streams (either on different pads, or on the same pad using + * multiplexed streams). This function is to be used only for entities that + * do not support multiple pipelines. + * + * Return: The media_pipeline the entity is part of, or NULL if the entity is + * not part of any pipeline. + */ +struct media_pipeline *media_entity_pipeline(struct media_entity *entity); + +/** + * media_pad_pipeline - Get the media pipeline a pad is part of + * @pad: The pad + * + * This function returns the media pipeline that a pad has been associated + * with when constructing the pipeline with media_pipeline_start(). The pointer + * remains valid until media_pipeline_stop() is called. + * + * Return: The media_pipeline the pad is part of, or NULL if the pad is + * not part of any pipeline. + */ +struct media_pipeline *media_pad_pipeline(struct media_pad *pad); /** * media_entity_get_fwnode_pad - Get pad number from fwnode @@ -833,14 +1070,14 @@ struct media_entity *media_entity_get(struct media_entity *entity); * a fwnode. This is useful for devices which use more complex * mappings of media pads. * - * If the entity dose not implement the get_fwnode_pad() operation + * If the entity does not implement the get_fwnode_pad() operation * then this function searches the entity for the first pad that * matches the @direction_flags. * * Return: returns the pad number on success or a negative error code. */ int media_entity_get_fwnode_pad(struct media_entity *entity, - struct fwnode_handle *fwnode, + const struct fwnode_handle *fwnode, unsigned long direction_flags); /** @@ -848,6 +1085,13 @@ int media_entity_get_fwnode_pad(struct media_entity *entity, * * @graph: Media graph structure that will be used to walk the graph * @mdev: Pointer to the &media_device that contains the object + * + * This function is deprecated, use media_pipeline_for_each_pad() instead. + * + * The caller is required to hold the media_device graph_mutex during the graph + * walk until the graph state is released. + * + * Returns zero on success or a negative error code otherwise. */ __must_check int media_graph_walk_init( struct media_graph *graph, struct media_device *mdev); @@ -856,19 +1100,10 @@ __must_check int media_graph_walk_init( * media_graph_walk_cleanup - Release resources used by graph walk. * * @graph: Media graph structure that will be used to walk the graph - */ -void media_graph_walk_cleanup(struct media_graph *graph); - -/** - * media_entity_put - Release the reference to the parent module - * - * @entity: The entity * - * Release the reference count acquired by media_entity_get(). - * - * The function will return immediately if @entity is %NULL. + * This function is deprecated, use media_pipeline_for_each_pad() instead. */ -void media_entity_put(struct media_entity *entity); +void media_graph_walk_cleanup(struct media_graph *graph); /** * media_graph_walk_start - Start walking the media graph at a @@ -877,6 +1112,8 @@ void media_entity_put(struct media_entity *entity); * @graph: Media graph structure that will be used to walk the graph * @entity: Starting entity * + * This function is deprecated, use media_pipeline_for_each_pad() instead. + * * Before using this function, media_graph_walk_init() must be * used to allocate resources used for walking the graph. This * function initializes the graph traversal structure to walk the @@ -892,6 +1129,8 @@ void media_graph_walk_start(struct media_graph *graph, * media_graph_walk_next - Get the next entity in the graph * @graph: Media graph structure * + * This function is deprecated, use media_pipeline_for_each_pad() instead. + * * Perform a depth-first traversal of the given media entities graph. * * The graph structure must have been previously initialized with a call to @@ -904,53 +1143,136 @@ struct media_entity *media_graph_walk_next(struct media_graph *graph); /** * media_pipeline_start - Mark a pipeline as streaming - * @entity: Starting entity - * @pipe: Media pipeline to be assigned to all entities in the pipeline. + * @origin: Starting pad + * @pipe: Media pipeline to be assigned to all pads in the pipeline. * - * Mark all entities connected to a given entity through enabled links, either + * Mark all pads connected to pad @origin 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. + * to every pad in the pipeline and stored in the media_pad pipe field. * * Calls to this function can be nested, in which case the same number of * media_pipeline_stop() calls will be required to stop streaming. The * pipeline pointer must be identical for all nested calls to * media_pipeline_start(). */ -__must_check int media_pipeline_start(struct media_entity *entity, +__must_check int media_pipeline_start(struct media_pad *origin, struct media_pipeline *pipe); /** * __media_pipeline_start - Mark a pipeline as streaming * - * @entity: Starting entity - * @pipe: Media pipeline to be assigned to all entities in the pipeline. + * @origin: Starting pad + * @pipe: Media pipeline to be assigned to all pads in the pipeline. * * ..note:: This is the non-locking version of media_pipeline_start() */ -__must_check int __media_pipeline_start(struct media_entity *entity, +__must_check int __media_pipeline_start(struct media_pad *origin, struct media_pipeline *pipe); /** * media_pipeline_stop - Mark a pipeline as not streaming - * @entity: Starting entity + * @pad: Starting pad * - * Mark all entities connected to a given entity through enabled links, either - * directly or indirectly, as not streaming. The media_entity pipe field is + * Mark all pads connected to a given pad through enabled links, either + * directly or indirectly, as not streaming. The media_pad pipe field is * reset to %NULL. * * If multiple calls to media_pipeline_start() have been made, the same * number of calls to this function are required to mark the pipeline as not * streaming. */ -void media_pipeline_stop(struct media_entity *entity); +void media_pipeline_stop(struct media_pad *pad); /** * __media_pipeline_stop - Mark a pipeline as not streaming * - * @entity: Starting entity + * @pad: Starting pad * * .. note:: This is the non-locking version of media_pipeline_stop() */ -void __media_pipeline_stop(struct media_entity *entity); +void __media_pipeline_stop(struct media_pad *pad); + +struct media_pad * +__media_pipeline_pad_iter_next(struct media_pipeline *pipe, + struct media_pipeline_pad_iter *iter, + struct media_pad *pad); + +/** + * media_pipeline_for_each_pad - Iterate on all pads in a media pipeline + * @pipe: The pipeline + * @iter: The iterator (struct media_pipeline_pad_iter) + * @pad: The iterator pad + * + * Iterate on all pads in a media pipeline. This is only valid after the + * pipeline has been built with media_pipeline_start() and before it gets + * destroyed with media_pipeline_stop(). + */ +#define media_pipeline_for_each_pad(pipe, iter, pad) \ + for (pad = __media_pipeline_pad_iter_next((pipe), iter, NULL); \ + pad != NULL; \ + pad = __media_pipeline_pad_iter_next((pipe), iter, pad)) + +/** + * media_pipeline_entity_iter_init - Initialize a pipeline entity iterator + * @pipe: The pipeline + * @iter: The iterator + * + * This function must be called to initialize the iterator before using it in a + * media_pipeline_for_each_entity() loop. The iterator must be destroyed by a + * call to media_pipeline_entity_iter_cleanup after the loop (including in code + * paths that break from the loop). + * + * The same iterator can be used in multiple consecutive loops without being + * destroyed and reinitialized. + * + * Return: 0 on success or a negative error code otherwise. + */ +int media_pipeline_entity_iter_init(struct media_pipeline *pipe, + struct media_pipeline_entity_iter *iter); + +/** + * media_pipeline_entity_iter_cleanup - Destroy a pipeline entity iterator + * @iter: The iterator + * + * This function must be called to destroy iterators initialized with + * media_pipeline_entity_iter_init(). + */ +void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter); + +struct media_entity * +__media_pipeline_entity_iter_next(struct media_pipeline *pipe, + struct media_pipeline_entity_iter *iter, + struct media_entity *entity); + +/** + * media_pipeline_for_each_entity - Iterate on all entities in a media pipeline + * @pipe: The pipeline + * @iter: The iterator (struct media_pipeline_entity_iter) + * @entity: The iterator entity + * + * Iterate on all entities in a media pipeline. This is only valid after the + * pipeline has been built with media_pipeline_start() and before it gets + * destroyed with media_pipeline_stop(). The iterator must be initialized with + * media_pipeline_entity_iter_init() before iteration, and destroyed with + * media_pipeline_entity_iter_cleanup() after (including in code paths that + * break from the loop). + */ +#define media_pipeline_for_each_entity(pipe, iter, entity) \ + for (entity = __media_pipeline_entity_iter_next((pipe), iter, NULL); \ + entity != NULL; \ + entity = __media_pipeline_entity_iter_next((pipe), iter, entity)) + +/** + * media_pipeline_alloc_start - Mark a pipeline as streaming + * @pad: Starting pad + * + * media_pipeline_alloc_start() is similar to media_pipeline_start() but instead + * of working on a given pipeline the function will use an existing pipeline if + * the pad is already part of a pipeline, or allocate a new pipeline. + * + * Calls to media_pipeline_alloc_start() must be matched with + * media_pipeline_stop(). + */ +__must_check int media_pipeline_alloc_start(struct media_pad *pad); /** * media_devnode_create() - creates and initializes a device node interface @@ -985,7 +1307,6 @@ __must_check media_devnode_create(struct media_device *mdev, * removed. */ void media_devnode_remove(struct media_intf_devnode *devnode); -struct media_link * /** * media_create_intf_link() - creates a link between an entity and an interface @@ -1016,6 +1337,7 @@ struct media_link * * the interface and media_device_register_entity() should be called for the * interface that will be part of the link. */ +struct media_link * __must_check media_create_intf_link(struct media_entity *entity, struct media_interface *intf, u32 flags); @@ -1076,4 +1398,53 @@ void media_remove_intf_links(struct media_interface *intf); (((entity)->ops && (entity)->ops->operation) ? \ (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD) +/** + * media_create_ancillary_link() - create an ancillary link between two + * instances of &media_entity + * + * @primary: pointer to the primary &media_entity + * @ancillary: pointer to the ancillary &media_entity + * + * Create an ancillary link between two entities, indicating that they + * represent two connected pieces of hardware that form a single logical unit. + * A typical example is a camera lens controller being linked to the sensor that + * it is supporting. + * + * The function sets both MEDIA_LNK_FL_ENABLED and MEDIA_LNK_FL_IMMUTABLE for + * the new link. + */ +struct media_link * +media_create_ancillary_link(struct media_entity *primary, + struct media_entity *ancillary); + +/** + * __media_entity_next_link() - Iterate through a &media_entity's links + * + * @entity: pointer to the &media_entity + * @link: pointer to a &media_link to hold the iterated values + * @link_type: one of the MEDIA_LNK_FL_LINK_TYPE flags + * + * Return the next link against an entity matching a specific link type. This + * allows iteration through an entity's links whilst guaranteeing all of the + * returned links are of the given type. + */ +struct media_link *__media_entity_next_link(struct media_entity *entity, + struct media_link *link, + unsigned long link_type); + +/** + * for_each_media_entity_data_link() - Iterate through an entity's data links + * + * @entity: pointer to the &media_entity + * @link: pointer to a &media_link to hold the iterated values + * + * Iterate over a &media_entity's data links + */ +#define for_each_media_entity_data_link(entity, link) \ + for (link = __media_entity_next_link(entity, NULL, \ + MEDIA_LNK_FL_DATA_LINK); \ + link; \ + link = __media_entity_next_link(entity, link, \ + MEDIA_LNK_FL_DATA_LINK)) + #endif |
