diff options
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.patch | 265 |
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 + |