From 2096a5dcf9704f5a86ecba37169eb813aaf0431c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:38:49 -0300 Subject: [media] v4l: subdev: Add device node support Create a device node named subdevX for every registered subdev. As the device node is registered before the subdev core::s_config function is called, return -EGAIN on open until initialization completes. Signed-off-by: Laurent Pinchart Signed-off-by: Vimarsh Zutshi Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-dev.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'include/media/v4l2-dev.h') diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 15802a067a1..4fe6831b185 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -21,7 +21,8 @@ #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 -#define VFL_TYPE_MAX 3 +#define VFL_TYPE_SUBDEV 3 +#define VFL_TYPE_MAX 4 struct v4l2_ioctl_callbacks; struct video_device; @@ -102,15 +103,26 @@ struct video_device /* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) +int __must_check __video_register_device(struct video_device *vdev, int type, + int nr, int warn_if_nr_in_use, struct module *owner); + /* Register video devices. Note that if video_register_device fails, the release() callback of the video_device structure is *not* called, so the caller is responsible for freeing any data. Usually that means that you call video_device_release() on failure. */ -int __must_check video_register_device(struct video_device *vdev, int type, int nr); +static inline int __must_check video_register_device(struct video_device *vdev, + int type, int nr) +{ + return __video_register_device(vdev, type, nr, 1, vdev->fops->owner); +} /* Same as video_register_device, but no warning is issued if the desired device node number was already in use. */ -int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr); +static inline int __must_check video_register_device_no_warn( + struct video_device *vdev, int type, int nr) +{ + return __video_register_device(vdev, type, nr, 0, vdev->fops->owner); +} /* Unregister video devices. Will do nothing if vdev == NULL or video_is_registered() returns false. */ -- cgit v1.2.3-70-g09d2 From 2c0ab67be1b4197a4effac89bb0604832e38be8d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:10 -0300 Subject: [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 Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 38 +++++++++++++++++++-- drivers/media/video/v4l2-dev.c | 49 +++++++++++++++++++++++++--- include/media/v4l2-dev.h | 7 ++++ 3 files changed, 87 insertions(+), 7 deletions(-) (limited to 'include/media/v4l2-dev.h') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 7de55cfae04..062708169de 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 and in the future a v4l2_fh struct will keep track of filehandle instances (this is not yet implemented). +The V4L2 framework also optionally integrates with the media framework. If a +driver sets the struct v4l2_device mdev field, sub-devices and video nodes +will automatically appear in the media framework as entities. + struct v4l2_device ------------------ @@ -84,11 +88,14 @@ You must register the device instance: v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); Registration will initialize the v4l2_device struct. If the dev->driver_data -field is NULL, it will be linked to v4l2_dev. Drivers that use the media -device framework in addition to the V4L2 framework need to set +field is NULL, it will be linked to v4l2_dev. + +Drivers that want integration with the media device framework need to set dev->driver_data manually to point to the driver-specific device structure that embed the struct v4l2_device instance. This is achieved by a -dev_set_drvdata() call before registering the V4L2 device instance. +dev_set_drvdata() call before registering the V4L2 device instance. They must +also set the struct v4l2_device mdev field to point to a properly initialized +and registered media_device instance. If v4l2_dev->name is empty then it will be set to a value derived from dev (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 The v4l2_file_operations struct is a subset of file_operations. The main difference is that the inode argument is omitted since it is never used. +If integration with the media framework is needed, you must initialize the +media_entity struct embedded in the video_device struct (entity field) by +calling media_entity_init(): + + struct media_pad *pad = &my_vdev->pad; + int err; + + err = media_entity_init(&vdev->entity, 1, pad, 0); + +The pads array must have been previously initialized. There is no need to +manually set the struct media_entity type and name fields. + +A reference to the entity will be automatically acquired/released when the +video device is opened/closed. + v4l2_file_operations and locking -------------------------------- @@ -559,6 +581,9 @@ for you. return err; } +If the v4l2_device parent device has a non-NULL mdev field, the video device +entity will be automatically registered with the media device. + Which device is registered depends on the type argument. The following types exist: @@ -634,6 +659,13 @@ release, of course) will return an error as well. When the last user of the video device node exits, then the vdev->release() callback is called and you can do the final cleanup there. +Don't forget to cleanup the media entity associated with the video device if +it has been initialized: + + media_entity_cleanup(&vdev->entity); + +This can be done from the release callback. + video_device helper functions ----------------------------- diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index abe04ef3806..e405b8094b9 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) static int v4l2_open(struct inode *inode, struct file *filp) { struct video_device *vdev; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity *entity = NULL; +#endif int ret = 0; /* Check if the video device is available */ @@ -316,6 +319,16 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) { + entity = media_entity_get(&vdev->entity); + if (!entity) { + ret = -EBUSY; + video_put(vdev); + return ret; + } + } +#endif if (vdev->fops->open) { if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { ret = -ERESTARTSYS; @@ -331,8 +344,13 @@ static int v4l2_open(struct inode *inode, struct file *filp) err: /* decrease the refcount in case of an error */ - if (ret) + if (ret) { +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) + media_entity_put(entity); +#endif video_put(vdev); + } return ret; } @@ -349,7 +367,10 @@ static int v4l2_release(struct inode *inode, struct file *filp) if (vdev->lock) mutex_unlock(vdev->lock); } - +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) + media_entity_put(&vdev->entity); +#endif /* decrease the refcount unconditionally since the release() return value is ignored. */ video_put(vdev); @@ -585,12 +606,27 @@ int __video_register_device(struct video_device *vdev, int type, int nr, if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, name_base, nr, video_device_node_name(vdev)); - - /* Part 5: Activate this minor. The char device can now be used. */ +#if defined(CONFIG_MEDIA_CONTROLLER) + /* Part 5: Register the entity. */ + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) { + vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; + vdev->entity.name = vdev->name; + vdev->entity.v4l.major = VIDEO_MAJOR; + vdev->entity.v4l.minor = vdev->minor; + ret = media_device_register_entity(vdev->v4l2_dev->mdev, + &vdev->entity); + if (ret < 0) + printk(KERN_WARNING + "%s: media_device_register_entity failed\n", + __func__); + } +#endif + /* Part 6: Activate this minor. The char device can now be used. */ set_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_lock(&videodev_lock); video_device[vdev->minor] = vdev; mutex_unlock(&videodev_lock); + return 0; cleanup: @@ -618,6 +654,11 @@ void video_unregister_device(struct video_device *vdev) if (!vdev || !video_is_registered(vdev)) return; +#if defined(CONFIG_MEDIA_CONTROLLER) + if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) + media_device_unregister_entity(&vdev->entity); +#endif + mutex_lock(&videodev_lock); /* This must be in a critical section to prevent a race with v4l2_open. * 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 4fe6831b185..51b2c515f68 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -16,6 +16,8 @@ #include #include +#include + #define VIDEO_MAJOR 81 #define VFL_TYPE_GRABBER 0 @@ -55,6 +57,9 @@ struct v4l2_file_operations { struct video_device { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity entity; +#endif /* device ops */ const struct v4l2_file_operations *fops; @@ -100,6 +105,8 @@ struct video_device struct mutex *lock; }; +#define media_entity_to_video_device(entity) \ + container_of(entity, struct video_device, entity) /* dev to video-device */ #define to_video_device(cd) container_of(cd, struct video_device, dev) -- cgit v1.2.3-70-g09d2 From 022654930891c7ddfdb1ea34d6c4af9d1096bf91 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 Dec 2010 10:05:02 -0300 Subject: [media] v4l2_prio: move from v4l2-common to v4l2-dev We are going to move priority handling into the v4l2 core. As a consequence the v4l2_prio helper functions need to be moved into the core videodev module as well to prevent circular dependencies. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-common.c | 63 -------------------------------------- drivers/media/video/v4l2-dev.c | 64 +++++++++++++++++++++++++++++++++++++++ include/media/v4l2-common.h | 15 --------- include/media/v4l2-dev.h | 15 +++++++++ 4 files changed, 79 insertions(+), 78 deletions(-) (limited to 'include/media/v4l2-dev.h') diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 940b5db3463..06b9f9f8201 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -80,69 +80,6 @@ MODULE_LICENSE("GPL"); * Video Standard Operations (contributed by Michael Schimek) */ - -/* ----------------------------------------------------------------- */ -/* priority handling */ - -#define V4L2_PRIO_VALID(val) (val == V4L2_PRIORITY_BACKGROUND || \ - val == V4L2_PRIORITY_INTERACTIVE || \ - val == V4L2_PRIORITY_RECORD) - -void v4l2_prio_init(struct v4l2_prio_state *global) -{ - memset(global, 0, sizeof(*global)); -} -EXPORT_SYMBOL(v4l2_prio_init); - -int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, - enum v4l2_priority new) -{ - if (!V4L2_PRIO_VALID(new)) - return -EINVAL; - if (*local == new) - return 0; - - atomic_inc(&global->prios[new]); - if (V4L2_PRIO_VALID(*local)) - atomic_dec(&global->prios[*local]); - *local = new; - return 0; -} -EXPORT_SYMBOL(v4l2_prio_change); - -void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) -{ - v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT); -} -EXPORT_SYMBOL(v4l2_prio_open); - -void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local) -{ - if (V4L2_PRIO_VALID(local)) - atomic_dec(&global->prios[local]); -} -EXPORT_SYMBOL(v4l2_prio_close); - -enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) -{ - if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0) - return V4L2_PRIORITY_RECORD; - if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0) - return V4L2_PRIORITY_INTERACTIVE; - if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0) - return V4L2_PRIORITY_BACKGROUND; - return V4L2_PRIORITY_UNSET; -} -EXPORT_SYMBOL(v4l2_prio_max); - -int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local) -{ - return (local < v4l2_prio_max(global)) ? -EBUSY : 0; -} -EXPORT_SYMBOL(v4l2_prio_check); - -/* ----------------------------------------------------------------- */ - /* Helper functions for control handling */ /* Check for correctness of the ctrl's value based on the data from diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index e405b8094b9..65d546f35ef 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -182,6 +182,70 @@ struct video_device *video_devdata(struct file *file) } EXPORT_SYMBOL(video_devdata); + +/* Priority handling */ + +static inline bool prio_is_valid(enum v4l2_priority prio) +{ + return prio == V4L2_PRIORITY_BACKGROUND || + prio == V4L2_PRIORITY_INTERACTIVE || + prio == V4L2_PRIORITY_RECORD; +} + +void v4l2_prio_init(struct v4l2_prio_state *global) +{ + memset(global, 0, sizeof(*global)); +} +EXPORT_SYMBOL(v4l2_prio_init); + +int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, + enum v4l2_priority new) +{ + if (!prio_is_valid(new)) + return -EINVAL; + if (*local == new) + return 0; + + atomic_inc(&global->prios[new]); + if (prio_is_valid(*local)) + atomic_dec(&global->prios[*local]); + *local = new; + return 0; +} +EXPORT_SYMBOL(v4l2_prio_change); + +void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) +{ + v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT); +} +EXPORT_SYMBOL(v4l2_prio_open); + +void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local) +{ + if (prio_is_valid(local)) + atomic_dec(&global->prios[local]); +} +EXPORT_SYMBOL(v4l2_prio_close); + +enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) +{ + if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0) + return V4L2_PRIORITY_RECORD; + if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0) + return V4L2_PRIORITY_INTERACTIVE; + if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0) + return V4L2_PRIORITY_BACKGROUND; + return V4L2_PRIORITY_UNSET; +} +EXPORT_SYMBOL(v4l2_prio_max); + +int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local) +{ + return (local < v4l2_prio_max(global)) ? -EBUSY : 0; +} +EXPORT_SYMBOL(v4l2_prio_check); + + static ssize_t v4l2_read(struct file *filp, char __user *buf, size_t sz, loff_t *off) { diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index a659319e858..a298ec49ddc 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -80,21 +80,6 @@ /* ------------------------------------------------------------------------- */ -/* Priority helper functions */ - -struct v4l2_prio_state { - atomic_t prios[4]; -}; -void v4l2_prio_init(struct v4l2_prio_state *global); -int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, - enum v4l2_priority new); -void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); -void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local); -enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); -int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local); - -/* ------------------------------------------------------------------------- */ - /* Control helper functions */ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 51b2c515f68..9193703f4f0 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -37,6 +37,21 @@ struct v4l2_ctrl_handler; #define V4L2_FL_REGISTERED (0) #define V4L2_FL_USES_V4L2_FH (1) +/* Priority helper functions */ + +struct v4l2_prio_state { + atomic_t prios[4]; +}; + +void v4l2_prio_init(struct v4l2_prio_state *global); +int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, + enum v4l2_priority new); +void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); +void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local); +enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); +int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local); + + struct v4l2_file_operations { struct module *owner; ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); -- cgit v1.2.3-70-g09d2 From 0f62fd6a2fa12d6a63cbb18f9e30b05345f636f6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Feb 2011 10:42:24 -0300 Subject: [media] v4l2: add v4l2_prio_state to v4l2_device and video_device Integrate the v4l2_prio_state into the core, ready for use. One struct v4l2_prio_state is added to v4l2_device and a pointer to a prio state is added to video_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-dev.c | 6 ++++++ drivers/media/video/v4l2-device.c | 1 + include/media/v4l2-dev.h | 3 +++ include/media/v4l2-device.h | 3 +++ 4 files changed, 13 insertions(+) (limited to 'include/media/v4l2-dev.h') diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 65d546f35ef..6b1ef85d8cc 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -573,6 +573,12 @@ int __video_register_device(struct video_device *vdev, int type, int nr, vdev->parent = vdev->v4l2_dev->dev; if (vdev->ctrl_handler == NULL) vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; + /* If the prio state pointer is NULL, and if the driver doesn't + handle priorities itself, then use the v4l2_device prio + state. */ + if (vdev->prio == NULL && vdev->ioctl_ops && + vdev->ioctl_ops->vidioc_s_priority == NULL) + vdev->prio = &vdev->v4l2_dev->prio; } /* Part 2: find a free minor, device node number and device index. */ diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index a1afda352d0..fd7a445ce34 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -36,6 +36,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) INIT_LIST_HEAD(&v4l2_dev->subdevs); spin_lock_init(&v4l2_dev->lock); mutex_init(&v4l2_dev->ioctl_lock); + v4l2_prio_init(&v4l2_dev->prio); v4l2_dev->dev = dev; if (dev == NULL) { /* If dev == NULL, then name must be filled in by the caller */ diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 9193703f4f0..3700127ba29 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -89,6 +89,9 @@ struct video_device /* Control handler associated with this device node. May be NULL. */ struct v4l2_ctrl_handler *ctrl_handler; + /* Priority state. If NULL, then v4l2_dev->prio will be used. */ + struct v4l2_prio_state *prio; + /* device info */ char name[32]; int vfl_type; diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 0c2bd307503..3b723283da2 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -23,6 +23,7 @@ #include #include +#include /* Each instance of a V4L2 device should create the v4l2_device struct, either stand-alone or embedded in a larger struct. @@ -55,6 +56,8 @@ struct v4l2_device { unsigned int notification, void *arg); /* The control handler. May be NULL. */ struct v4l2_ctrl_handler *ctrl_handler; + /* Device's priority state */ + struct v4l2_prio_state prio; /* BKL replacement mutex. Temporary solution only. */ struct mutex ioctl_lock; }; -- cgit v1.2.3-70-g09d2 From b1a873a37b6551a214ad37d1eee7654a9d65fd6e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 22 Mar 2011 10:14:07 -0300 Subject: [media] v4l2: use new flag to enable core priority handling Rather than guess which driver supports core priority handling, require drivers that do to explicitly set the V4L2_FL_USE_FH_PRIO flag in video_device. Updated the core prio handling accordingly and set the flag in the three drivers that do. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 7 ++++++- drivers/media/video/cx18/cx18-streams.c | 1 + drivers/media/video/ivtv/ivtv-streams.c | 1 + drivers/media/video/v4l2-dev.c | 8 +++----- drivers/media/video/v4l2-fh.c | 7 ++++--- drivers/media/video/v4l2-ioctl.c | 13 ++++++++----- drivers/media/video/vivi.c | 1 + include/media/v4l2-dev.h | 3 +++ 8 files changed, 27 insertions(+), 14 deletions(-) (limited to 'include/media/v4l2-dev.h') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 7d09114af00..3b15608ee07 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -577,6 +577,10 @@ You should also set these fields: (cx8802). Since the v4l2_device cannot be associated with a particular PCI device it is setup without a parent device. But when the struct video_device is setup you do know which parent PCI device to use. +- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework + handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct + v4l2_fh. Eventually this flag will disappear once all drivers use the core + priority handling. But for now it has to be set explicitly. If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2 in your v4l2_file_operations struct. @@ -775,7 +779,8 @@ struct v4l2_fh struct v4l2_fh provides a way to easily keep file handle specific data that is used by the V4L2 framework. New drivers must use struct v4l2_fh -since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY). +since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY) +if the video_device flag V4L2_FL_USE_FH_PRIO is also set. The users of v4l2_fh (in the V4L2 framework, not the driver) know whether a driver uses v4l2_fh as its file->private_data pointer by diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 2d248560770..c6e2ca3b114 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -207,6 +207,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) s->video_dev->fops = &cx18_v4l2_enc_fops; s->video_dev->release = video_device_release; s->video_dev->tvnorms = V4L2_STD_ALL; + set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags); cx18_set_funcs(s->video_dev); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 512607e0cda..94268333655 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -214,6 +214,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) s->vdev->fops = ivtv_stream_info[type].fops; s->vdev->release = video_device_release; s->vdev->tvnorms = V4L2_STD_ALL; + set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); ivtv_set_funcs(s->vdev); return 0; } diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 1898099ec65..498e6742579 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -578,11 +578,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr, vdev->parent = vdev->v4l2_dev->dev; if (vdev->ctrl_handler == NULL) vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; - /* If the prio state pointer is NULL, and if the driver doesn't - handle priorities itself, then use the v4l2_device prio - state. */ - if (vdev->prio == NULL && vdev->ioctl_ops && - vdev->ioctl_ops->vidioc_s_priority == NULL) + /* If the prio state pointer is NULL, then use the v4l2_device + prio state. */ + if (vdev->prio == NULL) vdev->prio = &vdev->v4l2_dev->prio; } diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c index 543b3fe6784..717f71e6370 100644 --- a/drivers/media/video/v4l2-fh.c +++ b/drivers/media/video/v4l2-fh.c @@ -35,7 +35,6 @@ int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) INIT_LIST_HEAD(&fh->list); set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); fh->prio = V4L2_PRIORITY_UNSET; - BUG_ON(vdev->prio == NULL); /* * fh->events only needs to be initialized if the driver @@ -54,7 +53,8 @@ void v4l2_fh_add(struct v4l2_fh *fh) { unsigned long flags; - v4l2_prio_open(fh->vdev->prio, &fh->prio); + if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags)) + v4l2_prio_open(fh->vdev->prio, &fh->prio); spin_lock_irqsave(&fh->vdev->fh_lock, flags); list_add(&fh->list, &fh->vdev->fh_list); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); @@ -82,7 +82,8 @@ void v4l2_fh_del(struct v4l2_fh *fh) spin_lock_irqsave(&fh->vdev->fh_lock, flags); list_del_init(&fh->list); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - v4l2_prio_close(fh->vdev->prio, fh->prio); + if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags)) + v4l2_prio_close(fh->vdev->prio, fh->prio); } EXPORT_SYMBOL_GPL(v4l2_fh_del); diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 3e6b6fa5771..a01ed39e6c1 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -541,6 +541,7 @@ static long __video_do_ioctl(struct file *file, void *fh = file->private_data; struct v4l2_fh *vfh = NULL; struct v4l2_format f_copy; + int use_fh_prio = 0; long ret = -EINVAL; if (ops == NULL) { @@ -555,10 +556,12 @@ static long __video_do_ioctl(struct file *file, printk(KERN_CONT "\n"); } - if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { vfh = file->private_data; + use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); + } - if (vfh && !ops->vidioc_s_priority) { + if (use_fh_prio) { switch (cmd) { case VIDIOC_S_CTRL: case VIDIOC_S_STD: @@ -620,7 +623,7 @@ static long __video_do_ioctl(struct file *file, if (ops->vidioc_g_priority) { ret = ops->vidioc_g_priority(file, fh, p); - } else if (vfh) { + } else if (use_fh_prio) { *p = v4l2_prio_max(&vfd->v4l2_dev->prio); ret = 0; } @@ -632,7 +635,7 @@ static long __video_do_ioctl(struct file *file, { enum v4l2_priority *p = arg; - if (!ops->vidioc_s_priority && vfh == NULL) + if (!ops->vidioc_s_priority && !use_fh_prio) break; dbgarg(cmd, "setting priority to %d\n", *p); if (ops->vidioc_s_priority) @@ -2187,7 +2190,7 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_default) break; - if (vfh && !ops->vidioc_s_priority) + if (use_fh_prio) valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0; ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg); break; diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 42500bf03a9..2238a613d66 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1254,6 +1254,7 @@ static int __init vivi_create_instance(int inst) *vfd = vivi_template; vfd->debug = debug; vfd->v4l2_dev = &dev->v4l2_dev; + set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); /* * Provide a mutex to v4l2 core. It will be used to protect diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 3700127ba29..8266d5ade2f 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -35,7 +35,10 @@ struct v4l2_ctrl_handler; Drivers can clear this flag if they want to block all future device access. It is cleared by video_unregister_device. */ #define V4L2_FL_REGISTERED (0) +/* file->private_data points to struct v4l2_fh */ #define V4L2_FL_USES_V4L2_FH (1) +/* Use the prio field of v4l2_fh for core priority checking */ +#define V4L2_FL_USE_FH_PRIO (2) /* Priority helper functions */ -- cgit v1.2.3-70-g09d2