aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-dev.c')
-rw-r--r--drivers/media/video/v4l2-dev.c152
1 files changed, 133 insertions, 19 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 341764a3a990..498e6742579e 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -143,6 +143,7 @@ static inline void video_put(struct video_device *vdev)
143static void v4l2_device_release(struct device *cd) 143static void v4l2_device_release(struct device *cd)
144{ 144{
145 struct video_device *vdev = to_video_device(cd); 145 struct video_device *vdev = to_video_device(cd);
146 struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
146 147
147 mutex_lock(&videodev_lock); 148 mutex_lock(&videodev_lock);
148 if (video_device[vdev->minor] != vdev) { 149 if (video_device[vdev->minor] != vdev) {
@@ -169,6 +170,10 @@ static void v4l2_device_release(struct device *cd)
169 /* Release video_device and perform other 170 /* Release video_device and perform other
170 cleanups as needed. */ 171 cleanups as needed. */
171 vdev->release(vdev); 172 vdev->release(vdev);
173
174 /* Decrease v4l2_device refcount */
175 if (v4l2_dev)
176 v4l2_device_put(v4l2_dev);
172} 177}
173 178
174static struct class video_class = { 179static struct class video_class = {
@@ -182,6 +187,70 @@ struct video_device *video_devdata(struct file *file)
182} 187}
183EXPORT_SYMBOL(video_devdata); 188EXPORT_SYMBOL(video_devdata);
184 189
190
191/* Priority handling */
192
193static inline bool prio_is_valid(enum v4l2_priority prio)
194{
195 return prio == V4L2_PRIORITY_BACKGROUND ||
196 prio == V4L2_PRIORITY_INTERACTIVE ||
197 prio == V4L2_PRIORITY_RECORD;
198}
199
200void v4l2_prio_init(struct v4l2_prio_state *global)
201{
202 memset(global, 0, sizeof(*global));
203}
204EXPORT_SYMBOL(v4l2_prio_init);
205
206int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
207 enum v4l2_priority new)
208{
209 if (!prio_is_valid(new))
210 return -EINVAL;
211 if (*local == new)
212 return 0;
213
214 atomic_inc(&global->prios[new]);
215 if (prio_is_valid(*local))
216 atomic_dec(&global->prios[*local]);
217 *local = new;
218 return 0;
219}
220EXPORT_SYMBOL(v4l2_prio_change);
221
222void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local)
223{
224 v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT);
225}
226EXPORT_SYMBOL(v4l2_prio_open);
227
228void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local)
229{
230 if (prio_is_valid(local))
231 atomic_dec(&global->prios[local]);
232}
233EXPORT_SYMBOL(v4l2_prio_close);
234
235enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)
236{
237 if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0)
238 return V4L2_PRIORITY_RECORD;
239 if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0)
240 return V4L2_PRIORITY_INTERACTIVE;
241 if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0)
242 return V4L2_PRIORITY_BACKGROUND;
243 return V4L2_PRIORITY_UNSET;
244}
245EXPORT_SYMBOL(v4l2_prio_max);
246
247int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local)
248{
249 return (local < v4l2_prio_max(global)) ? -EBUSY : 0;
250}
251EXPORT_SYMBOL(v4l2_prio_check);
252
253
185static ssize_t v4l2_read(struct file *filp, char __user *buf, 254static ssize_t v4l2_read(struct file *filp, char __user *buf,
186 size_t sz, loff_t *off) 255 size_t sz, loff_t *off)
187{ 256{
@@ -303,6 +372,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
303static int v4l2_open(struct inode *inode, struct file *filp) 372static int v4l2_open(struct inode *inode, struct file *filp)
304{ 373{
305 struct video_device *vdev; 374 struct video_device *vdev;
375#if defined(CONFIG_MEDIA_CONTROLLER)
376 struct media_entity *entity = NULL;
377#endif
306 int ret = 0; 378 int ret = 0;
307 379
308 /* Check if the video device is available */ 380 /* Check if the video device is available */
@@ -316,6 +388,16 @@ static int v4l2_open(struct inode *inode, struct file *filp)
316 /* and increase the device refcount */ 388 /* and increase the device refcount */
317 video_get(vdev); 389 video_get(vdev);
318 mutex_unlock(&videodev_lock); 390 mutex_unlock(&videodev_lock);
391#if defined(CONFIG_MEDIA_CONTROLLER)
392 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
393 entity = media_entity_get(&vdev->entity);
394 if (!entity) {
395 ret = -EBUSY;
396 video_put(vdev);
397 return ret;
398 }
399 }
400#endif
319 if (vdev->fops->open) { 401 if (vdev->fops->open) {
320 if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { 402 if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
321 ret = -ERESTARTSYS; 403 ret = -ERESTARTSYS;
@@ -331,8 +413,13 @@ static int v4l2_open(struct inode *inode, struct file *filp)
331 413
332err: 414err:
333 /* decrease the refcount in case of an error */ 415 /* decrease the refcount in case of an error */
334 if (ret) 416 if (ret) {
417#if defined(CONFIG_MEDIA_CONTROLLER)
418 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
419 media_entity_put(entity);
420#endif
335 video_put(vdev); 421 video_put(vdev);
422 }
336 return ret; 423 return ret;
337} 424}
338 425
@@ -349,7 +436,10 @@ static int v4l2_release(struct inode *inode, struct file *filp)
349 if (vdev->lock) 436 if (vdev->lock)
350 mutex_unlock(vdev->lock); 437 mutex_unlock(vdev->lock);
351 } 438 }
352 439#if defined(CONFIG_MEDIA_CONTROLLER)
440 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
441 media_entity_put(&vdev->entity);
442#endif
353 /* decrease the refcount unconditionally since the release() 443 /* decrease the refcount unconditionally since the release()
354 return value is ignored. */ 444 return value is ignored. */
355 video_put(vdev); 445 video_put(vdev);
@@ -408,13 +498,14 @@ static int get_index(struct video_device *vdev)
408} 498}
409 499
410/** 500/**
411 * video_register_device - register video4linux devices 501 * __video_register_device - register video4linux devices
412 * @vdev: video device structure we want to register 502 * @vdev: video device structure we want to register
413 * @type: type of device to register 503 * @type: type of device to register
414 * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... 504 * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ...
415 * -1 == first free) 505 * -1 == first free)
416 * @warn_if_nr_in_use: warn if the desired device node number 506 * @warn_if_nr_in_use: warn if the desired device node number
417 * was already in use and another number was chosen instead. 507 * was already in use and another number was chosen instead.
508 * @owner: module that owns the video device node
418 * 509 *
419 * The registration code assigns minor numbers and device node numbers 510 * The registration code assigns minor numbers and device node numbers
420 * based on the requested type and registers the new device node with 511 * based on the requested type and registers the new device node with
@@ -435,9 +526,11 @@ static int get_index(struct video_device *vdev)
435 * %VFL_TYPE_VBI - Vertical blank data (undecoded) 526 * %VFL_TYPE_VBI - Vertical blank data (undecoded)
436 * 527 *
437 * %VFL_TYPE_RADIO - A radio card 528 * %VFL_TYPE_RADIO - A radio card
529 *
530 * %VFL_TYPE_SUBDEV - A subdevice
438 */ 531 */
439static int __video_register_device(struct video_device *vdev, int type, int nr, 532int __video_register_device(struct video_device *vdev, int type, int nr,
440 int warn_if_nr_in_use) 533 int warn_if_nr_in_use, struct module *owner)
441{ 534{
442 int i = 0; 535 int i = 0;
443 int ret; 536 int ret;
@@ -469,6 +562,9 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
469 case VFL_TYPE_RADIO: 562 case VFL_TYPE_RADIO:
470 name_base = "radio"; 563 name_base = "radio";
471 break; 564 break;
565 case VFL_TYPE_SUBDEV:
566 name_base = "v4l-subdev";
567 break;
472 default: 568 default:
473 printk(KERN_ERR "%s called with unknown type: %d\n", 569 printk(KERN_ERR "%s called with unknown type: %d\n",
474 __func__, type); 570 __func__, type);
@@ -482,6 +578,10 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
482 vdev->parent = vdev->v4l2_dev->dev; 578 vdev->parent = vdev->v4l2_dev->dev;
483 if (vdev->ctrl_handler == NULL) 579 if (vdev->ctrl_handler == NULL)
484 vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; 580 vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler;
581 /* If the prio state pointer is NULL, then use the v4l2_device
582 prio state. */
583 if (vdev->prio == NULL)
584 vdev->prio = &vdev->v4l2_dev->prio;
485 } 585 }
486 586
487 /* Part 2: find a free minor, device node number and device index. */ 587 /* Part 2: find a free minor, device node number and device index. */
@@ -552,7 +652,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
552 goto cleanup; 652 goto cleanup;
553 } 653 }
554 vdev->cdev->ops = &v4l2_fops; 654 vdev->cdev->ops = &v4l2_fops;
555 vdev->cdev->owner = vdev->fops->owner; 655 vdev->cdev->owner = owner;
556 ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); 656 ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
557 if (ret < 0) { 657 if (ret < 0) {
558 printk(KERN_ERR "%s: cdev_add failed\n", __func__); 658 printk(KERN_ERR "%s: cdev_add failed\n", __func__);
@@ -580,11 +680,31 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
580 printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, 680 printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
581 name_base, nr, video_device_node_name(vdev)); 681 name_base, nr, video_device_node_name(vdev));
582 682
583 /* Part 5: Activate this minor. The char device can now be used. */ 683 /* Increase v4l2_device refcount */
684 if (vdev->v4l2_dev)
685 v4l2_device_get(vdev->v4l2_dev);
686
687#if defined(CONFIG_MEDIA_CONTROLLER)
688 /* Part 5: Register the entity. */
689 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
690 vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
691 vdev->entity.name = vdev->name;
692 vdev->entity.v4l.major = VIDEO_MAJOR;
693 vdev->entity.v4l.minor = vdev->minor;
694 ret = media_device_register_entity(vdev->v4l2_dev->mdev,
695 &vdev->entity);
696 if (ret < 0)
697 printk(KERN_WARNING
698 "%s: media_device_register_entity failed\n",
699 __func__);
700 }
701#endif
702 /* Part 6: Activate this minor. The char device can now be used. */
584 set_bit(V4L2_FL_REGISTERED, &vdev->flags); 703 set_bit(V4L2_FL_REGISTERED, &vdev->flags);
585 mutex_lock(&videodev_lock); 704 mutex_lock(&videodev_lock);
586 video_device[vdev->minor] = vdev; 705 video_device[vdev->minor] = vdev;
587 mutex_unlock(&videodev_lock); 706 mutex_unlock(&videodev_lock);
707
588 return 0; 708 return 0;
589 709
590cleanup: 710cleanup:
@@ -597,18 +717,7 @@ cleanup:
597 vdev->minor = -1; 717 vdev->minor = -1;
598 return ret; 718 return ret;
599} 719}
600 720EXPORT_SYMBOL(__video_register_device);
601int video_register_device(struct video_device *vdev, int type, int nr)
602{
603 return __video_register_device(vdev, type, nr, 1);
604}
605EXPORT_SYMBOL(video_register_device);
606
607int video_register_device_no_warn(struct video_device *vdev, int type, int nr)
608{
609 return __video_register_device(vdev, type, nr, 0);
610}
611EXPORT_SYMBOL(video_register_device_no_warn);
612 721
613/** 722/**
614 * video_unregister_device - unregister a video4linux device 723 * video_unregister_device - unregister a video4linux device
@@ -623,6 +732,11 @@ void video_unregister_device(struct video_device *vdev)
623 if (!vdev || !video_is_registered(vdev)) 732 if (!vdev || !video_is_registered(vdev))
624 return; 733 return;
625 734
735#if defined(CONFIG_MEDIA_CONTROLLER)
736 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
737 media_device_unregister_entity(&vdev->entity);
738#endif
739
626 mutex_lock(&videodev_lock); 740 mutex_lock(&videodev_lock);
627 /* This must be in a critical section to prevent a race with v4l2_open. 741 /* This must be in a critical section to prevent a race with v4l2_open.
628 * Once this bit has been cleared video_get may never be called again. 742 * Once this bit has been cleared video_get may never be called again.