diff options
-rw-r--r-- | drivers/media/media-entity.c | 40 | ||||
-rw-r--r-- | include/media/media-device.h | 15 | ||||
-rw-r--r-- | include/media/media-entity.h | 141 |
3 files changed, 188 insertions, 8 deletions
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 13c8ca11f169..5e3f32f63187 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -71,6 +71,46 @@ static inline const char *intf_type(struct media_interface *intf) }; /** + * __media_entity_enum_init - Initialise an entity enumeration + * + * @ent_enum: Entity enumeration to be initialised + * @idx_max: Maximum number of entities in the enumeration + * + * Returns zero on success or a negative error code. + */ +__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, + int idx_max) +{ + if (idx_max > MEDIA_ENTITY_ENUM_MAX_ID) { + ent_enum->bmap = kcalloc(DIV_ROUND_UP(idx_max, BITS_PER_LONG), + sizeof(long), GFP_KERNEL); + if (!ent_enum->bmap) + return -ENOMEM; + } else { + ent_enum->bmap = ent_enum->prealloc_bmap; + } + + bitmap_zero(ent_enum->bmap, idx_max); + ent_enum->idx_max = idx_max; + + return 0; +} +EXPORT_SYMBOL_GPL(__media_entity_enum_init); + +/** + * media_entity_enum_cleanup - Release resources of an entity enumeration + * + * @e: Entity enumeration to be released + */ +void media_entity_enum_cleanup(struct media_entity_enum *ent_enum) +{ + if (ent_enum->bmap != ent_enum->prealloc_bmap) + kfree(ent_enum->bmap); + ent_enum->bmap = NULL; +} +EXPORT_SYMBOL_GPL(media_entity_enum_cleanup); + +/** * dev_dbg_obj - Prints in debug mode a change on some object * * @event_name: Name of the event to report. Could be __func__ diff --git a/include/media/media-device.h b/include/media/media-device.h index 2ab4e6803842..da4e12ca259c 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -342,6 +342,21 @@ struct media_device { #define to_media_device(node) container_of(node, struct media_device, devnode) /** + * media_entity_enum_init - Initialise an entity enumeration + * + * @e: Entity enumeration to be initialised + * @mdev: The related media device + * + * Returns zero on success or a negative error code. + */ +static inline __must_check int media_entity_enum_init( + struct media_entity_enum *ent_enum, struct media_device *mdev) +{ + return __media_entity_enum_init(ent_enum, + mdev->entity_internal_idx_max + 1); +} + +/** * media_device_init() - Initializes a media device element * * @mdev: pointer to struct &media_device diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 30e8f9fd3efa..c593dbd3e030 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -23,7 +23,7 @@ #ifndef _MEDIA_ENTITY_H #define _MEDIA_ENTITY_H -#include <linux/bitops.h> +#include <linux/bitmap.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/media.h> @@ -71,6 +71,32 @@ struct media_gobj { struct list_head list; }; +#define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 +#define MEDIA_ENTITY_ENUM_MAX_ID 64 + +/* + * The number of pads can't be bigger than the number of entities, + * as the worse-case scenario is to have one entity linked up to + * MEDIA_ENTITY_ENUM_MAX_ID - 1 entities. + */ +#define MEDIA_ENTITY_MAX_PADS (MEDIA_ENTITY_ENUM_MAX_ID - 1) + +/** + * struct media_entity_enum - An enumeration of media entities. + * + * @prealloc_bmap: Pre-allocated space reserved for media entities if the + * total number of entities does not exceed + * MEDIA_ENTITY_ENUM_MAX_ID. + * @bmap: Bit map in which each bit represents one entity at struct + * media_entity->internal_idx. + * @idx_max: Number of bits in bmap + */ +struct media_entity_enum { + DECLARE_BITMAP(prealloc_bmap, MEDIA_ENTITY_ENUM_MAX_ID); + unsigned long *bmap; + int idx_max; +}; + struct media_pipeline { }; @@ -329,15 +355,114 @@ static inline bool is_media_entity_v4l2_subdev(struct media_entity *entity) } } -#define MEDIA_ENTITY_ENUM_MAX_DEPTH 16 -#define MEDIA_ENTITY_ENUM_MAX_ID 64 +__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum, + int idx_max); +void media_entity_enum_cleanup(struct media_entity_enum *e); -/* - * The number of pads can't be bigger than the number of entities, - * as the worse-case scenario is to have one entity linked up to - * MEDIA_ENTITY_ENUM_MAX_ID - 1 entities. +/** + * media_entity_enum_zero - Clear the entire enum + * + * @e: Entity enumeration to be cleared */ -#define MEDIA_ENTITY_MAX_PADS (MEDIA_ENTITY_ENUM_MAX_ID - 1) +static inline void media_entity_enum_zero(struct media_entity_enum *ent_enum) +{ + bitmap_zero(ent_enum->bmap, ent_enum->idx_max); +} + +/** + * media_entity_enum_set - Mark a single entity in the enum + * + * @e: Entity enumeration + * @entity: Entity to be marked + */ +static inline void media_entity_enum_set(struct media_entity_enum *ent_enum, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) + return; + + __set_bit(entity->internal_idx, ent_enum->bmap); +} + +/** + * media_entity_enum_clear - Unmark a single entity in the enum + * + * @e: Entity enumeration + * @entity: Entity to be unmarked + */ +static inline void media_entity_enum_clear(struct media_entity_enum *ent_enum, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) + return; + + __clear_bit(entity->internal_idx, ent_enum->bmap); +} + +/** + * media_entity_enum_test - Test whether the entity is marked + * + * @e: Entity enumeration + * @entity: Entity to be tested + * + * Returns true if the entity was marked. + */ +static inline bool media_entity_enum_test(struct media_entity_enum *ent_enum, + struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) + return true; + + return test_bit(entity->internal_idx, ent_enum->bmap); +} + +/** + * media_entity_enum_test - Test whether the entity is marked, and mark it + * + * @e: Entity enumeration + * @entity: Entity to be tested + * + * Returns true if the entity was marked, and mark it before doing so. + */ +static inline bool media_entity_enum_test_and_set( + struct media_entity_enum *ent_enum, struct media_entity *entity) +{ + if (WARN_ON(entity->internal_idx >= ent_enum->idx_max)) + return true; + + return __test_and_set_bit(entity->internal_idx, ent_enum->bmap); +} + +/** + * media_entity_enum_test - Test whether the entire enum is empty + * + * @e: Entity enumeration + * @entity: Entity to be tested + * + * Returns true if the entity was marked. + */ +static inline bool media_entity_enum_empty(struct media_entity_enum *ent_enum) +{ + return bitmap_empty(ent_enum->bmap, ent_enum->idx_max); +} + +/** + * media_entity_enum_intersects - Test whether two enums intersect + * + * @e: First entity enumeration + * @f: Second entity enumeration + * + * Returns true if entity enumerations e and f intersect, otherwise false. + */ +static inline bool media_entity_enum_intersects( + struct media_entity_enum *ent_enum1, + struct media_entity_enum *ent_enum2) +{ + WARN_ON(ent_enum1->idx_max != ent_enum2->idx_max); + + return bitmap_intersects(ent_enum1->bmap, ent_enum2->bmap, + min(ent_enum1->idx_max, ent_enum2->idx_max)); +} struct media_entity_graph { struct { |