[media] media: Links setup

Create the following ioctl and implement it at the media device level to
setup links.

- MEDIA_IOC_SETUP_LINK: Modify the properties of a given link

The only property that can currently be modified is the ENABLED link
flag to enable/disable a link. Links marked with the IMMUTABLE link flag
can not be enabled or disabled.

Enabling or disabling a link has effects on entities' use count. Those
changes are automatically propagated through the graph.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/include/linux/media.h b/include/linux/media.h
index 17c93a4..7c69913 100644
--- a/include/linux/media.h
+++ b/include/linux/media.h
@@ -126,5 +126,6 @@
 #define MEDIA_IOC_DEVICE_INFO		_IOWR('M', 1, struct media_device_info)
 #define MEDIA_IOC_ENUM_ENTITIES		_IOWR('M', 2, struct media_entity_desc)
 #define MEDIA_IOC_ENUM_LINKS		_IOWR('M', 3, struct media_links_enum)
+#define MEDIA_IOC_SETUP_LINK		_IOWR('M', 4, struct media_link_desc)
 
 #endif /* __LINUX_MEDIA_H */
diff --git a/include/media/media-device.h b/include/media/media-device.h
index 5d2bff4..6a27d91 100644
--- a/include/media/media-device.h
+++ b/include/media/media-device.h
@@ -73,6 +73,9 @@
 	spinlock_t lock;
 	/* Serializes graph operations. */
 	struct mutex graph_mutex;
+
+	int (*link_notify)(struct media_pad *source,
+			   struct media_pad *sink, u32 flags);
 };
 
 /* media_devnode to media_device */
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 51bdafc..d889dcc 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -39,6 +39,12 @@
 	unsigned long flags;		/* Pad flags (MEDIA_PAD_FL_*) */
 };
 
+struct media_entity_operations {
+	int (*link_setup)(struct media_entity *entity,
+			  const struct media_pad *local,
+			  const struct media_pad *remote, u32 flags);
+};
+
 struct media_entity {
 	struct list_head list;
 	struct media_device *parent;	/* Media device this entity belongs to*/
@@ -59,6 +65,8 @@
 	struct media_pad *pads;		/* Pads array (num_pads elements) */
 	struct media_link *links;	/* Links array (max_links elements)*/
 
+	const struct media_entity_operations *ops;	/* Entity operations */
+
 	/* 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.
@@ -112,6 +120,11 @@
 void media_entity_cleanup(struct media_entity *entity);
 int media_entity_create_link(struct media_entity *source, u16 source_pad,
 		struct media_entity *sink, u16 sink_pad, u32 flags);
+int __media_entity_setup_link(struct media_link *link, u32 flags);
+int media_entity_setup_link(struct media_link *link, u32 flags);
+struct media_link *media_entity_find_link(struct media_pad *source,
+		struct media_pad *sink);
+struct media_pad *media_entity_remote_source(struct media_pad *pad);
 
 struct media_entity *media_entity_get(struct media_entity *entity);
 void media_entity_put(struct media_entity *entity);
@@ -121,4 +134,8 @@
 struct media_entity *
 media_entity_graph_walk_next(struct media_entity_graph *graph);
 
+#define media_entity_call(entity, operation, args...)			\
+	(((entity)->ops && (entity)->ops->operation) ?			\
+	 (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
+
 #endif