aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2009-12-09 06:40:10 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 03:53:19 -0400
commit2c0ab67be1b4197a4effac89bb0604832e38be8d (patch)
tree033b1d2c6ae25e05f1f46f3c2e7bdb504c359ad3
parent95db3a60e0652a52df145aacade1a88c5acef659 (diff)
[media] v4l: Make video_device inherit from media_entity
V4L2 devices are media entities. As such they need to inherit from (include) the media_entity structure. When registering/unregistering the device, 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@iki.fi> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--Documentation/video4linux/v4l2-framework.txt38
-rw-r--r--drivers/media/video/v4l2-dev.c49
-rw-r--r--include/media/v4l2-dev.h7
3 files changed, 87 insertions, 7 deletions
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 7de55cfae04e..062708169def 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -71,6 +71,10 @@ sub-device instances, the video_device struct stores V4L2 device node data
71and in the future a v4l2_fh struct will keep track of filehandle instances 71and in the future a v4l2_fh struct will keep track of filehandle instances
72(this is not yet implemented). 72(this is not yet implemented).
73 73
74The V4L2 framework also optionally integrates with the media framework. If a
75driver sets the struct v4l2_device mdev field, sub-devices and video nodes
76will automatically appear in the media framework as entities.
77
74 78
75struct v4l2_device 79struct v4l2_device
76------------------ 80------------------
@@ -84,11 +88,14 @@ You must register the device instance:
84 v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); 88 v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
85 89
86Registration will initialize the v4l2_device struct. If the dev->driver_data 90Registration will initialize the v4l2_device struct. If the dev->driver_data
87field is NULL, it will be linked to v4l2_dev. Drivers that use the media 91field is NULL, it will be linked to v4l2_dev.
88device framework in addition to the V4L2 framework need to set 92
93Drivers that want integration with the media device framework need to set
89dev->driver_data manually to point to the driver-specific device structure 94dev->driver_data manually to point to the driver-specific device structure
90that embed the struct v4l2_device instance. This is achieved by a 95that embed the struct v4l2_device instance. This is achieved by a
91dev_set_drvdata() call before registering the V4L2 device instance. 96dev_set_drvdata() call before registering the V4L2 device instance. They must
97also set the struct v4l2_device mdev field to point to a properly initialized
98and registered media_device instance.
92 99
93If v4l2_dev->name is empty then it will be set to a value derived from dev 100If v4l2_dev->name is empty then it will be set to a value derived from dev
94(driver name followed by the bus_id, to be precise). If you set it up before 101(driver name followed by the bus_id, to be precise). If you set it up before
@@ -530,6 +537,21 @@ If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
530The v4l2_file_operations struct is a subset of file_operations. The main 537The v4l2_file_operations struct is a subset of file_operations. The main
531difference is that the inode argument is omitted since it is never used. 538difference is that the inode argument is omitted since it is never used.
532 539
540If integration with the media framework is needed, you must initialize the
541media_entity struct embedded in the video_device struct (entity field) by
542calling media_entity_init():
543
544 struct media_pad *pad = &my_vdev->pad;
545 int err;
546
547 err = media_entity_init(&vdev->entity, 1, pad, 0);
548
549The pads array must have been previously initialized. There is no need to
550manually set the struct media_entity type and name fields.
551
552A reference to the entity will be automatically acquired/released when the
553video device is opened/closed.
554
533v4l2_file_operations and locking 555v4l2_file_operations and locking
534-------------------------------- 556--------------------------------
535 557
@@ -559,6 +581,9 @@ for you.
559 return err; 581 return err;
560 } 582 }
561 583
584If the v4l2_device parent device has a non-NULL mdev field, the video device
585entity will be automatically registered with the media device.
586
562Which device is registered depends on the type argument. The following 587Which device is registered depends on the type argument. The following
563types exist: 588types exist:
564 589
@@ -634,6 +659,13 @@ release, of course) will return an error as well.
634When the last user of the video device node exits, then the vdev->release() 659When the last user of the video device node exits, then the vdev->release()
635callback is called and you can do the final cleanup there. 660callback is called and you can do the final cleanup there.
636 661
662Don't forget to cleanup the media entity associated with the video device if
663it has been initialized:
664
665 media_entity_cleanup(&vdev->entity);
666
667This can be done from the release callback.
668
637 669
638video_device helper functions 670video_device helper functions
639----------------------------- 671-----------------------------
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index abe04ef38066..e405b8094b94 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -303,6 +303,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
303static int v4l2_open(struct inode *inode, struct file *filp) 303static int v4l2_open(struct inode *inode, struct file *filp)
304{ 304{
305 struct video_device *vdev; 305 struct video_device *vdev;
306#if defined(CONFIG_MEDIA_CONTROLLER)
307 struct media_entity *entity = NULL;
308#endif
306 int ret = 0; 309 int ret = 0;
307 310
308 /* Check if the video device is available */ 311 /* Check if the video device is available */
@@ -316,6 +319,16 @@ static int v4l2_open(struct inode *inode, struct file *filp)
316 /* and increase the device refcount */ 319 /* and increase the device refcount */
317 video_get(vdev); 320 video_get(vdev);
318 mutex_unlock(&videodev_lock); 321 mutex_unlock(&videodev_lock);
322#if defined(CONFIG_MEDIA_CONTROLLER)
323 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
324 entity = media_entity_get(&vdev->entity);
325 if (!entity) {
326 ret = -EBUSY;
327 video_put(vdev);
328 return ret;
329 }
330 }
331#endif
319 if (vdev->fops->open) { 332 if (vdev->fops->open) {
320 if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { 333 if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
321 ret = -ERESTARTSYS; 334 ret = -ERESTARTSYS;
@@ -331,8 +344,13 @@ static int v4l2_open(struct inode *inode, struct file *filp)
331 344
332err: 345err:
333 /* decrease the refcount in case of an error */ 346 /* decrease the refcount in case of an error */
334 if (ret) 347 if (ret) {
348#if defined(CONFIG_MEDIA_CONTROLLER)
349 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
350 media_entity_put(entity);
351#endif
335 video_put(vdev); 352 video_put(vdev);
353 }
336 return ret; 354 return ret;
337} 355}
338 356
@@ -349,7 +367,10 @@ static int v4l2_release(struct inode *inode, struct file *filp)
349 if (vdev->lock) 367 if (vdev->lock)
350 mutex_unlock(vdev->lock); 368 mutex_unlock(vdev->lock);
351 } 369 }
352 370#if defined(CONFIG_MEDIA_CONTROLLER)
371 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
372 media_entity_put(&vdev->entity);
373#endif
353 /* decrease the refcount unconditionally since the release() 374 /* decrease the refcount unconditionally since the release()
354 return value is ignored. */ 375 return value is ignored. */
355 video_put(vdev); 376 video_put(vdev);
@@ -585,12 +606,27 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
585 if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) 606 if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
586 printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, 607 printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
587 name_base, nr, video_device_node_name(vdev)); 608 name_base, nr, video_device_node_name(vdev));
588 609#if defined(CONFIG_MEDIA_CONTROLLER)
589 /* Part 5: Activate this minor. The char device can now be used. */ 610 /* Part 5: Register the entity. */
611 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
612 vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
613 vdev->entity.name = vdev->name;
614 vdev->entity.v4l.major = VIDEO_MAJOR;
615 vdev->entity.v4l.minor = vdev->minor;
616 ret = media_device_register_entity(vdev->v4l2_dev->mdev,
617 &vdev->entity);
618 if (ret < 0)
619 printk(KERN_WARNING
620 "%s: media_device_register_entity failed\n",
621 __func__);
622 }
623#endif
624 /* Part 6: Activate this minor. The char device can now be used. */
590 set_bit(V4L2_FL_REGISTERED, &vdev->flags); 625 set_bit(V4L2_FL_REGISTERED, &vdev->flags);
591 mutex_lock(&videodev_lock); 626 mutex_lock(&videodev_lock);
592 video_device[vdev->minor] = vdev; 627 video_device[vdev->minor] = vdev;
593 mutex_unlock(&videodev_lock); 628 mutex_unlock(&videodev_lock);
629
594 return 0; 630 return 0;
595 631
596cleanup: 632cleanup:
@@ -618,6 +654,11 @@ void video_unregister_device(struct video_device *vdev)
618 if (!vdev || !video_is_registered(vdev)) 654 if (!vdev || !video_is_registered(vdev))
619 return; 655 return;
620 656
657#if defined(CONFIG_MEDIA_CONTROLLER)
658 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
659 media_device_unregister_entity(&vdev->entity);
660#endif
661
621 mutex_lock(&videodev_lock); 662 mutex_lock(&videodev_lock);
622 /* This must be in a critical section to prevent a race with v4l2_open. 663 /* This must be in a critical section to prevent a race with v4l2_open.
623 * Once this bit has been cleared video_get may never be called again. 664 * Once this bit has been cleared video_get may never be called again.
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 4fe6831b1851..51b2c515f687 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -16,6 +16,8 @@
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/videodev2.h> 17#include <linux/videodev2.h>
18 18
19#include <media/media-entity.h>
20
19#define VIDEO_MAJOR 81 21#define VIDEO_MAJOR 81
20 22
21#define VFL_TYPE_GRABBER 0 23#define VFL_TYPE_GRABBER 0
@@ -55,6 +57,9 @@ struct v4l2_file_operations {
55 57
56struct video_device 58struct video_device
57{ 59{
60#if defined(CONFIG_MEDIA_CONTROLLER)
61 struct media_entity entity;
62#endif
58 /* device ops */ 63 /* device ops */
59 const struct v4l2_file_operations *fops; 64 const struct v4l2_file_operations *fops;
60 65
@@ -100,6 +105,8 @@ struct video_device
100 struct mutex *lock; 105 struct mutex *lock;
101}; 106};
102 107
108#define media_entity_to_video_device(entity) \
109 container_of(entity, struct video_device, entity)
103/* dev to video-device */ 110/* dev to video-device */
104#define to_video_device(cd) container_of(cd, struct video_device, dev) 111#define to_video_device(cd) container_of(cd, struct video_device, dev)
105 112