aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/media-device.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>2016-03-15 06:48:28 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2016-03-15 06:48:28 -0400
commit8331c055b23c4155b896a2c3791704ae68992d2b (patch)
tree7b8055caa7363b2194dd33de8ba27ee96a9d2505 /drivers/media/media-device.c
parentb562e44f507e863c6792946e4e1b1449fbbac85d (diff)
parent840f5b0572ea9ddaca2bf5540a171013e92c97bd (diff)
Merge commit '840f5b0572ea' into v4l_for_linus
* commit '840f5b0572ea': (381 commits) media: au0828 disable tuner to demod link in au0828_media_device_register() [media] touptek: cast char types on %x printk [media] touptek: don't DMA at the stack [media] mceusb: use %*ph for small buffer dumps [media] v4l: exynos4-is: Drop unneeded check when setting up fimc-lite links [media] v4l: vsp1: Check if an entity is a subdev with the right function [media] hide unused functions for !MEDIA_CONTROLLER [media] em28xx: fix Terratec Grabby AC97 codec detection [media] media: add prefixes to interface types [media] media: rc: nuvoton: switch attribute wakeup_data to text [media] v4l2-ioctl: fix YUV422P pixel format description [media] media: fix null pointer dereference in v4l_vb2q_enable_media_source() [media] v4l2-mc.h: fix yet more compiler errors [media] staging/media: add missing TODO files [media] media.h: always start with 1 for the audio entities [media] sound/usb: Use meaninful names for goto labels [media] v4l2-mc.h: fix compiler warnings [media] media: au0828 audio mixer isn't connected to decoder [media] sound/usb: Use Media Controller API to share media resources [media] dw2102: add support for TeVii S662 ...
Diffstat (limited to 'drivers/media/media-device.c')
-rw-r--r--drivers/media/media-device.c145
1 files changed, 134 insertions, 11 deletions
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index e9219f528d7e..6e43c95629ea 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -30,6 +30,8 @@
30#include <linux/media.h> 30#include <linux/media.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/pci.h>
34#include <linux/usb.h>
33 35
34#include <media/media-device.h> 36#include <media/media-device.h>
35#include <media/media-devnode.h> 37#include <media/media-devnode.h>
@@ -41,6 +43,11 @@
41 * Userspace API 43 * Userspace API
42 */ 44 */
43 45
46static inline void __user *media_get_uptr(__u64 arg)
47{
48 return (void __user *)(uintptr_t)arg;
49}
50
44static int media_device_open(struct file *filp) 51static int media_device_open(struct file *filp)
45{ 52{
46 return 0; 53 return 0;
@@ -58,7 +65,11 @@ static int media_device_get_info(struct media_device *dev,
58 65
59 memset(&info, 0, sizeof(info)); 66 memset(&info, 0, sizeof(info));
60 67
61 strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver)); 68 if (dev->driver_name[0])
69 strlcpy(info.driver, dev->driver_name, sizeof(info.driver));
70 else
71 strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver));
72
62 strlcpy(info.model, dev->model, sizeof(info.model)); 73 strlcpy(info.model, dev->model, sizeof(info.model));
63 strlcpy(info.serial, dev->serial, sizeof(info.serial)); 74 strlcpy(info.serial, dev->serial, sizeof(info.serial));
64 strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info)); 75 strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info));
@@ -257,7 +268,6 @@ static long media_device_setup_link(struct media_device *mdev,
257 return ret; 268 return ret;
258} 269}
259 270
260#if 0 /* Let's postpone it to Kernel 4.6 */
261static long __media_device_get_topology(struct media_device *mdev, 271static long __media_device_get_topology(struct media_device *mdev,
262 struct media_v2_topology *topo) 272 struct media_v2_topology *topo)
263{ 273{
@@ -265,10 +275,10 @@ static long __media_device_get_topology(struct media_device *mdev,
265 struct media_interface *intf; 275 struct media_interface *intf;
266 struct media_pad *pad; 276 struct media_pad *pad;
267 struct media_link *link; 277 struct media_link *link;
268 struct media_v2_entity kentity, *uentity; 278 struct media_v2_entity kentity, __user *uentity;
269 struct media_v2_interface kintf, *uintf; 279 struct media_v2_interface kintf, __user *uintf;
270 struct media_v2_pad kpad, *upad; 280 struct media_v2_pad kpad, __user *upad;
271 struct media_v2_link klink, *ulink; 281 struct media_v2_link klink, __user *ulink;
272 unsigned int i; 282 unsigned int i;
273 int ret = 0; 283 int ret = 0;
274 284
@@ -413,7 +423,6 @@ static long media_device_get_topology(struct media_device *mdev,
413 423
414 return 0; 424 return 0;
415} 425}
416#endif
417 426
418static long media_device_ioctl(struct file *filp, unsigned int cmd, 427static long media_device_ioctl(struct file *filp, unsigned int cmd,
419 unsigned long arg) 428 unsigned long arg)
@@ -447,14 +456,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd,
447 mutex_unlock(&dev->graph_mutex); 456 mutex_unlock(&dev->graph_mutex);
448 break; 457 break;
449 458
450#if 0 /* Let's postpone it to Kernel 4.6 */
451 case MEDIA_IOC_G_TOPOLOGY: 459 case MEDIA_IOC_G_TOPOLOGY:
452 mutex_lock(&dev->graph_mutex); 460 mutex_lock(&dev->graph_mutex);
453 ret = media_device_get_topology(dev, 461 ret = media_device_get_topology(dev,
454 (struct media_v2_topology __user *)arg); 462 (struct media_v2_topology __user *)arg);
455 mutex_unlock(&dev->graph_mutex); 463 mutex_unlock(&dev->graph_mutex);
456 break; 464 break;
457#endif 465
458 default: 466 default:
459 ret = -ENOIOCTLCMD; 467 ret = -ENOIOCTLCMD;
460 } 468 }
@@ -503,9 +511,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd,
503 case MEDIA_IOC_DEVICE_INFO: 511 case MEDIA_IOC_DEVICE_INFO:
504 case MEDIA_IOC_ENUM_ENTITIES: 512 case MEDIA_IOC_ENUM_ENTITIES:
505 case MEDIA_IOC_SETUP_LINK: 513 case MEDIA_IOC_SETUP_LINK:
506#if 0 /* Let's postpone it to Kernel 4.6 */
507 case MEDIA_IOC_G_TOPOLOGY: 514 case MEDIA_IOC_G_TOPOLOGY:
508#endif
509 return media_device_ioctl(filp, cmd, arg); 515 return media_device_ioctl(filp, cmd, arg);
510 516
511 case MEDIA_IOC_ENUM_LINKS32: 517 case MEDIA_IOC_ENUM_LINKS32:
@@ -564,6 +570,7 @@ static void media_device_release(struct media_devnode *mdev)
564int __must_check media_device_register_entity(struct media_device *mdev, 570int __must_check media_device_register_entity(struct media_device *mdev,
565 struct media_entity *entity) 571 struct media_entity *entity)
566{ 572{
573 struct media_entity_notify *notify, *next;
567 unsigned int i; 574 unsigned int i;
568 int ret; 575 int ret;
569 576
@@ -603,8 +610,33 @@ int __must_check media_device_register_entity(struct media_device *mdev,
603 media_gobj_create(mdev, MEDIA_GRAPH_PAD, 610 media_gobj_create(mdev, MEDIA_GRAPH_PAD,
604 &entity->pads[i].graph_obj); 611 &entity->pads[i].graph_obj);
605 612
613 /* invoke entity_notify callbacks */
614 list_for_each_entry_safe(notify, next, &mdev->entity_notify, list) {
615 (notify)->notify(entity, notify->notify_data);
616 }
617
606 spin_unlock(&mdev->lock); 618 spin_unlock(&mdev->lock);
607 619
620 mutex_lock(&mdev->graph_mutex);
621 if (mdev->entity_internal_idx_max
622 >= mdev->pm_count_walk.ent_enum.idx_max) {
623 struct media_entity_graph new = { .top = 0 };
624
625 /*
626 * Initialise the new graph walk before cleaning up
627 * the old one in order not to spoil the graph walk
628 * object of the media device if graph walk init fails.
629 */
630 ret = media_entity_graph_walk_init(&new, mdev);
631 if (ret) {
632 mutex_unlock(&mdev->graph_mutex);
633 return ret;
634 }
635 media_entity_graph_walk_cleanup(&mdev->pm_count_walk);
636 mdev->pm_count_walk = new;
637 }
638 mutex_unlock(&mdev->graph_mutex);
639
608 return 0; 640 return 0;
609} 641}
610EXPORT_SYMBOL_GPL(media_device_register_entity); 642EXPORT_SYMBOL_GPL(media_device_register_entity);
@@ -636,6 +668,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
636 /* Remove the entity */ 668 /* Remove the entity */
637 media_gobj_destroy(&entity->graph_obj); 669 media_gobj_destroy(&entity->graph_obj);
638 670
671 /* invoke entity_notify callbacks to handle entity removal?? */
672
639 entity->graph_obj.mdev = NULL; 673 entity->graph_obj.mdev = NULL;
640} 674}
641 675
@@ -668,6 +702,7 @@ void media_device_init(struct media_device *mdev)
668 INIT_LIST_HEAD(&mdev->interfaces); 702 INIT_LIST_HEAD(&mdev->interfaces);
669 INIT_LIST_HEAD(&mdev->pads); 703 INIT_LIST_HEAD(&mdev->pads);
670 INIT_LIST_HEAD(&mdev->links); 704 INIT_LIST_HEAD(&mdev->links);
705 INIT_LIST_HEAD(&mdev->entity_notify);
671 spin_lock_init(&mdev->lock); 706 spin_lock_init(&mdev->lock);
672 mutex_init(&mdev->graph_mutex); 707 mutex_init(&mdev->graph_mutex);
673 ida_init(&mdev->entity_internal_idx); 708 ida_init(&mdev->entity_internal_idx);
@@ -680,6 +715,7 @@ void media_device_cleanup(struct media_device *mdev)
680{ 715{
681 ida_destroy(&mdev->entity_internal_idx); 716 ida_destroy(&mdev->entity_internal_idx);
682 mdev->entity_internal_idx_max = 0; 717 mdev->entity_internal_idx_max = 0;
718 media_entity_graph_walk_cleanup(&mdev->pm_count_walk);
683 mutex_destroy(&mdev->graph_mutex); 719 mutex_destroy(&mdev->graph_mutex);
684} 720}
685EXPORT_SYMBOL_GPL(media_device_cleanup); 721EXPORT_SYMBOL_GPL(media_device_cleanup);
@@ -713,11 +749,40 @@ int __must_check __media_device_register(struct media_device *mdev,
713} 749}
714EXPORT_SYMBOL_GPL(__media_device_register); 750EXPORT_SYMBOL_GPL(__media_device_register);
715 751
752int __must_check media_device_register_entity_notify(struct media_device *mdev,
753 struct media_entity_notify *nptr)
754{
755 spin_lock(&mdev->lock);
756 list_add_tail(&nptr->list, &mdev->entity_notify);
757 spin_unlock(&mdev->lock);
758 return 0;
759}
760EXPORT_SYMBOL_GPL(media_device_register_entity_notify);
761
762/*
763 * Note: Should be called with mdev->lock held.
764 */
765static void __media_device_unregister_entity_notify(struct media_device *mdev,
766 struct media_entity_notify *nptr)
767{
768 list_del(&nptr->list);
769}
770
771void media_device_unregister_entity_notify(struct media_device *mdev,
772 struct media_entity_notify *nptr)
773{
774 spin_lock(&mdev->lock);
775 __media_device_unregister_entity_notify(mdev, nptr);
776 spin_unlock(&mdev->lock);
777}
778EXPORT_SYMBOL_GPL(media_device_unregister_entity_notify);
779
716void media_device_unregister(struct media_device *mdev) 780void media_device_unregister(struct media_device *mdev)
717{ 781{
718 struct media_entity *entity; 782 struct media_entity *entity;
719 struct media_entity *next; 783 struct media_entity *next;
720 struct media_interface *intf, *tmp_intf; 784 struct media_interface *intf, *tmp_intf;
785 struct media_entity_notify *notify, *nextp;
721 786
722 if (mdev == NULL) 787 if (mdev == NULL)
723 return; 788 return;
@@ -734,6 +799,10 @@ void media_device_unregister(struct media_device *mdev)
734 list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list) 799 list_for_each_entry_safe(entity, next, &mdev->entities, graph_obj.list)
735 __media_device_unregister_entity(entity); 800 __media_device_unregister_entity(entity);
736 801
802 /* Remove all entity_notify callbacks from the media device */
803 list_for_each_entry_safe(notify, nextp, &mdev->entity_notify, list)
804 __media_device_unregister_entity_notify(mdev, notify);
805
737 /* Remove all interfaces from the media device */ 806 /* Remove all interfaces from the media device */
738 list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces, 807 list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
739 graph_obj.list) { 808 graph_obj.list) {
@@ -777,4 +846,58 @@ struct media_device *media_device_find_devres(struct device *dev)
777} 846}
778EXPORT_SYMBOL_GPL(media_device_find_devres); 847EXPORT_SYMBOL_GPL(media_device_find_devres);
779 848
849void media_device_pci_init(struct media_device *mdev,
850 struct pci_dev *pci_dev,
851 const char *name)
852{
853#ifdef CONFIG_PCI
854 mdev->dev = &pci_dev->dev;
855
856 if (name)
857 strlcpy(mdev->model, name, sizeof(mdev->model));
858 else
859 strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model));
860
861 sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev));
862
863 mdev->hw_revision = (pci_dev->subsystem_vendor << 16)
864 | pci_dev->subsystem_device;
865
866 mdev->driver_version = LINUX_VERSION_CODE;
867
868 media_device_init(mdev);
869#endif
870}
871EXPORT_SYMBOL_GPL(media_device_pci_init);
872
873void __media_device_usb_init(struct media_device *mdev,
874 struct usb_device *udev,
875 const char *board_name,
876 const char *driver_name)
877{
878#ifdef CONFIG_USB
879 mdev->dev = &udev->dev;
880
881 if (driver_name)
882 strlcpy(mdev->driver_name, driver_name,
883 sizeof(mdev->driver_name));
884
885 if (board_name)
886 strlcpy(mdev->model, board_name, sizeof(mdev->model));
887 else if (udev->product)
888 strlcpy(mdev->model, udev->product, sizeof(mdev->model));
889 else
890 strlcpy(mdev->model, "unknown model", sizeof(mdev->model));
891 if (udev->serial)
892 strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
893 usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info));
894 mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
895 mdev->driver_version = LINUX_VERSION_CODE;
896
897 media_device_init(mdev);
898#endif
899}
900EXPORT_SYMBOL_GPL(__media_device_usb_init);
901
902
780#endif /* CONFIG_MEDIA_CONTROLLER */ 903#endif /* CONFIG_MEDIA_CONTROLLER */