aboutsummaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch265
1 files changed, 265 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch b/extras/recipes-kernel/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch
new file mode 100644
index 00000000..c7ae882a
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/media/0019-v4l-Make-v4l2_subdev-inherit-from-media_entity.patch
@@ -0,0 +1,265 @@
+From ab4bf9e43078f79ba2b287e6dd6d6871901d0341 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 9 Dec 2009 12:40:08 +0100
+Subject: [PATCH 19/43] v4l: Make v4l2_subdev inherit from media_entity
+
+V4L2 subdevices are media entities. As such they need to inherit from
+(include) the media_entity structure.
+
+When registering/unregistering the subdevice, the media entity is
+automatically registered/unregistered. The entity is acquired on device
+open and released on device close.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+---
+ Documentation/video4linux/v4l2-framework.txt | 23 ++++++++++++++
+ drivers/media/video/v4l2-device.c | 39 ++++++++++++++++++++----
+ drivers/media/video/v4l2-subdev.c | 41 ++++++++++++++++++++++++-
+ include/media/v4l2-subdev.h | 10 ++++++
+ 4 files changed, 104 insertions(+), 9 deletions(-)
+
+diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
+index f231bc2..d0fb880 100644
+--- a/Documentation/video4linux/v4l2-framework.txt
++++ b/Documentation/video4linux/v4l2-framework.txt
+@@ -268,6 +268,26 @@ A sub-device driver initializes the v4l2_subdev struct using:
+ Afterwards you need to initialize subdev->name with a unique name and set the
+ module owner. This is done for you if you use the i2c helper functions.
+
++If integration with the media framework is needed, you must initialize the
++media_entity struct embedded in the v4l2_subdev struct (entity field) by
++calling media_entity_init():
++
++ struct media_pad *pads = &my_sd->pads;
++ int err;
++
++ err = media_entity_init(&sd->entity, npads, pads, 0);
++
++The pads array must have been previously initialized. There is no need to
++manually set the struct media_entity type and name fields, but the revision
++field must be initialized if needed.
++
++A reference to the entity will be automatically acquired/released when the
++subdev device node (if any) is opened/closed.
++
++Don't forget to cleanup the media entity before the sub-device is destroyed:
++
++ media_entity_cleanup(&sd->entity);
++
+ A device (bridge) driver needs to register the v4l2_subdev with the
+ v4l2_device:
+
+@@ -277,6 +297,9 @@ This can fail if the subdev module disappeared before it could be registered.
+ After this function was called successfully the subdev->dev field points to
+ the v4l2_device.
+
++If the v4l2_device parent device has a non-NULL mdev field, the sub-device
++entity will be automatically registered with the media device.
++
+ You can unregister a sub-device using:
+
+ v4l2_device_unregister_subdev(sd);
+diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
+index 5c16a12..69cb429 100644
+--- a/drivers/media/video/v4l2-device.c
++++ b/drivers/media/video/v4l2-device.c
+@@ -116,8 +116,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
+ EXPORT_SYMBOL_GPL(v4l2_device_unregister);
+
+ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+- struct v4l2_subdev *sd)
++ struct v4l2_subdev *sd)
+ {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity *entity = &sd->entity;
++#endif
+ struct video_device *vdev;
+ int err;
+
+@@ -135,7 +138,16 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+ err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
+ if (err)
+ return err;
+-
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ /* Register the entity. */
++ if (v4l2_dev->mdev) {
++ err = media_device_register_entity(v4l2_dev->mdev, entity);
++ if (err < 0) {
++ module_put(sd->owner);
++ return err;
++ }
++ }
++#endif
+ sd->v4l2_dev = v4l2_dev;
+ spin_lock(&v4l2_dev->lock);
+ list_add_tail(&sd->list, &v4l2_dev->subdevs);
+@@ -150,26 +162,39 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+ if (sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) {
+ err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+ sd->owner);
+- if (err < 0)
++ if (err < 0) {
+ v4l2_device_unregister_subdev(sd);
++ return err;
++ }
+ }
+-
+- return err;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ entity->v4l.major = VIDEO_MAJOR;
++ entity->v4l.minor = vdev->minor;
++#endif
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
+
+ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
+ {
++ struct v4l2_device *v4l2_dev;
++
+ /* return if it isn't registered */
+ if (sd == NULL || sd->v4l2_dev == NULL)
+ return;
+
+- spin_lock(&sd->v4l2_dev->lock);
++ v4l2_dev = sd->v4l2_dev;
++
++ spin_lock(&v4l2_dev->lock);
+ list_del(&sd->list);
+- spin_unlock(&sd->v4l2_dev->lock);
++ spin_unlock(&v4l2_dev->lock);
+ sd->v4l2_dev = NULL;
+
+ module_put(sd->owner);
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (v4l2_dev->mdev)
++ media_device_unregister_entity(&sd->entity);
++#endif
+ video_unregister_device(&sd->devnode);
+ }
+ EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
+diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
+index fbccefd..a49856a 100644
+--- a/drivers/media/video/v4l2-subdev.c
++++ b/drivers/media/video/v4l2-subdev.c
+@@ -35,7 +35,10 @@ static int subdev_open(struct file *file)
+ {
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+- struct v4l2_fh *vfh;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity *entity;
++#endif
++ struct v4l2_fh *vfh = NULL;
+ int ret;
+
+ if (!sd->initialized)
+@@ -61,11 +64,20 @@ static int subdev_open(struct file *file)
+ v4l2_fh_add(vfh);
+ file->private_data = vfh;
+ }
+-
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (sd->v4l2_dev->mdev) {
++ entity = media_entity_get(&sd->entity);
++ if (!entity) {
++ ret = -EBUSY;
++ goto err;
++ }
++ }
++#endif
+ return 0;
+
+ err:
+ if (vfh != NULL) {
++ v4l2_fh_del(vfh);
+ v4l2_fh_exit(vfh);
+ kfree(vfh);
+ }
+@@ -75,8 +87,16 @@ err:
+
+ static int subdev_close(struct file *file)
+ {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct video_device *vdev = video_devdata(file);
++ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
++#endif
+ struct v4l2_fh *vfh = file->private_data;
+
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ if (sd->v4l2_dev->mdev)
++ media_entity_put(&sd->entity);
++#endif
+ if (vfh != NULL) {
+ v4l2_fh_del(vfh);
+ v4l2_fh_exit(vfh);
+@@ -176,5 +196,22 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
+ sd->dev_priv = NULL;
+ sd->host_priv = NULL;
+ sd->initialized = 1;
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ sd->entity.name = sd->name;
++ sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
++#endif
+ }
+ EXPORT_SYMBOL(v4l2_subdev_init);
++
++#if defined(CONFIG_MEDIA_CONTROLLER)
++int v4l2_subdev_set_power(struct media_entity *entity, int power)
++{
++ struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
++
++ dev_dbg(entity->parent->dev,
++ "%s power%s\n", entity->name, power ? "on" : "off");
++
++ return v4l2_subdev_call(sd, core, s_power, power);
++}
++EXPORT_SYMBOL_GPL(v4l2_subdev_set_power);
++#endif
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 68cbe48..7d55b0c 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -21,6 +21,7 @@
+ #ifndef _V4L2_SUBDEV_H
+ #define _V4L2_SUBDEV_H
+
++#include <media/media-entity.h>
+ #include <media/v4l2-common.h>
+ #include <media/v4l2-dev.h>
+ #include <media/v4l2-mediabus.h>
+@@ -437,6 +438,9 @@ struct v4l2_subdev_ops {
+ stand-alone or embedded in a larger struct.
+ */
+ struct v4l2_subdev {
++#if defined(CONFIG_MEDIA_CONTROLLER)
++ struct media_entity entity;
++#endif
+ struct list_head list;
+ struct module *owner;
+ u32 flags;
+@@ -458,6 +462,8 @@ struct v4l2_subdev {
+ unsigned int nevents;
+ };
+
++#define media_entity_to_v4l2_subdev(ent) \
++ container_of(ent, struct v4l2_subdev, entity)
+ #define vdev_to_v4l2_subdev(vdev) \
+ container_of(vdev, struct v4l2_subdev, devnode)
+
+@@ -486,6 +492,10 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
+ void v4l2_subdev_init(struct v4l2_subdev *sd,
+ const struct v4l2_subdev_ops *ops);
+
++#if defined(CONFIG_MEDIA_CONTROLLER)
++int v4l2_subdev_set_power(struct media_entity *entity, int power);
++#endif
++
+ /* Call an ops of a v4l2_subdev, doing the right checks against
+ NULL pointers.
+
+--
+1.6.6.1
+