summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-12-30 12:45:48 +0100
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2016-01-11 15:19:26 +0100
commitb01cc9ce7c13e0463575332dfa3171727f706afb (patch)
tree12ceed1549c68cdcb0fbfad45b537b44584a18d5 /drivers
parent[media] dvb-usb-v2: postpone removal of media_device (diff)
downloadlinux-b01cc9ce7c13e0463575332dfa3171727f706afb.tar.xz
linux-b01cc9ce7c13e0463575332dfa3171727f706afb.zip
[media] media-entitiy: add a function to create multiple links
Sometimes, it is desired to create 1:n and n:1 or even n:n links between different entities with the same function. This is actually needed to support DVB devices that have multiple frontends. While we could do a function like that internally at the DVB core, such function is generic enough to be at media-entity, and it could be useful on some other places. So, add such function. Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/media-entity.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index eb38bc35320a..e89d85a7d31b 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -625,6 +625,71 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
}
EXPORT_SYMBOL_GPL(media_create_pad_link);
+int media_create_pad_links(const struct media_device *mdev,
+ const u32 source_function,
+ struct media_entity *source,
+ const u16 source_pad,
+ const u32 sink_function,
+ struct media_entity *sink,
+ const u16 sink_pad,
+ u32 flags,
+ const bool allow_both_undefined)
+{
+ struct media_entity *entity;
+ unsigned function;
+ int ret;
+
+ /* Trivial case: 1:1 relation */
+ if (source && sink)
+ return media_create_pad_link(source, source_pad,
+ sink, sink_pad, flags);
+
+ /* Worse case scenario: n:n relation */
+ if (!source && !sink) {
+ if (!allow_both_undefined)
+ return 0;
+ media_device_for_each_entity(source, mdev) {
+ if (source->function != source_function)
+ continue;
+ media_device_for_each_entity(sink, mdev) {
+ if (sink->function != sink_function)
+ continue;
+ ret = media_create_pad_link(source, source_pad,
+ sink, sink_pad,
+ flags);
+ if (ret)
+ return ret;
+ flags &= ~(MEDIA_LNK_FL_ENABLED |
+ MEDIA_LNK_FL_IMMUTABLE);
+ }
+ }
+ return 0;
+ }
+
+ /* Handle 1:n and n:1 cases */
+ if (source)
+ function = sink_function;
+ else
+ function = source_function;
+
+ media_device_for_each_entity(entity, mdev) {
+ if (entity->function != function)
+ continue;
+
+ if (source)
+ ret = media_create_pad_link(source, source_pad,
+ entity, sink_pad, flags);
+ else
+ ret = media_create_pad_link(entity, source_pad,
+ sink, sink_pad, flags);
+ if (ret)
+ return ret;
+ flags &= ~(MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(media_create_pad_links);
+
void __media_entity_remove_links(struct media_entity *entity)
{
struct media_link *link, *tmp;