diff options
| -rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 128 |
1 files changed, 75 insertions, 53 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c32fc7d24a42..90a11b5ac0b1 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
| @@ -73,6 +73,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
| 73 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
| 74 | 74 | ||
| 75 | static LIST_HEAD(em28xx_devlist); | 75 | static LIST_HEAD(em28xx_devlist); |
| 76 | static DEFINE_MUTEX(em28xx_devlist_mutex); | ||
| 76 | 77 | ||
| 77 | static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | 78 | static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; |
| 78 | static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; | 79 | static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; |
| @@ -1519,7 +1520,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1519 | struct em28xx_fh *fh; | 1520 | struct em28xx_fh *fh; |
| 1520 | enum v4l2_buf_type fh_type = 0; | 1521 | enum v4l2_buf_type fh_type = 0; |
| 1521 | 1522 | ||
| 1522 | lock_kernel(); | 1523 | mutex_lock(&em28xx_devlist_mutex); |
| 1523 | list_for_each_entry(h, &em28xx_devlist, devlist) { | 1524 | list_for_each_entry(h, &em28xx_devlist, devlist) { |
| 1524 | if (h->vdev->minor == minor) { | 1525 | if (h->vdev->minor == minor) { |
| 1525 | dev = h; | 1526 | dev = h; |
| @@ -1535,10 +1536,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1535 | dev = h; | 1536 | dev = h; |
| 1536 | } | 1537 | } |
| 1537 | } | 1538 | } |
| 1538 | if (NULL == dev) { | 1539 | mutex_unlock(&em28xx_devlist_mutex); |
| 1539 | unlock_kernel(); | 1540 | if (NULL == dev) |
| 1540 | return -ENODEV; | 1541 | return -ENODEV; |
| 1541 | } | 1542 | |
| 1543 | mutex_lock(&dev->lock); | ||
| 1542 | 1544 | ||
| 1543 | em28xx_videodbg("open minor=%d type=%s users=%d\n", | 1545 | em28xx_videodbg("open minor=%d type=%s users=%d\n", |
| 1544 | minor, v4l2_type_names[fh_type], dev->users); | 1546 | minor, v4l2_type_names[fh_type], dev->users); |
| @@ -1547,10 +1549,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1547 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); | 1549 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); |
| 1548 | if (!fh) { | 1550 | if (!fh) { |
| 1549 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); | 1551 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); |
| 1550 | unlock_kernel(); | 1552 | mutex_unlock(&dev->lock); |
| 1551 | return -ENOMEM; | 1553 | return -ENOMEM; |
| 1552 | } | 1554 | } |
| 1553 | mutex_lock(&dev->lock); | ||
| 1554 | fh->dev = dev; | 1555 | fh->dev = dev; |
| 1555 | fh->radio = radio; | 1556 | fh->radio = radio; |
| 1556 | fh->type = fh_type; | 1557 | fh->type = fh_type; |
| @@ -1584,7 +1585,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1584 | sizeof(struct em28xx_buffer), fh); | 1585 | sizeof(struct em28xx_buffer), fh); |
| 1585 | 1586 | ||
| 1586 | mutex_unlock(&dev->lock); | 1587 | mutex_unlock(&dev->lock); |
| 1587 | unlock_kernel(); | ||
| 1588 | 1588 | ||
| 1589 | return errCode; | 1589 | return errCode; |
| 1590 | } | 1590 | } |
| @@ -1871,6 +1871,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) | |||
| 1871 | { | 1871 | { |
| 1872 | struct em28xx *dev = NULL; | 1872 | struct em28xx *dev = NULL; |
| 1873 | 1873 | ||
| 1874 | mutex_lock(&em28xx_devlist_mutex); | ||
| 1874 | mutex_lock(&em28xx_extension_devlist_lock); | 1875 | mutex_lock(&em28xx_extension_devlist_lock); |
| 1875 | list_add_tail(&ops->next, &em28xx_extension_devlist); | 1876 | list_add_tail(&ops->next, &em28xx_extension_devlist); |
| 1876 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | 1877 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
| @@ -1879,6 +1880,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) | |||
| 1879 | } | 1880 | } |
| 1880 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); | 1881 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); |
| 1881 | mutex_unlock(&em28xx_extension_devlist_lock); | 1882 | mutex_unlock(&em28xx_extension_devlist_lock); |
| 1883 | mutex_unlock(&em28xx_devlist_mutex); | ||
| 1882 | return 0; | 1884 | return 0; |
| 1883 | } | 1885 | } |
| 1884 | EXPORT_SYMBOL(em28xx_register_extension); | 1886 | EXPORT_SYMBOL(em28xx_register_extension); |
| @@ -1887,6 +1889,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) | |||
| 1887 | { | 1889 | { |
| 1888 | struct em28xx *dev = NULL; | 1890 | struct em28xx *dev = NULL; |
| 1889 | 1891 | ||
| 1892 | mutex_lock(&em28xx_devlist_mutex); | ||
| 1890 | list_for_each_entry(dev, &em28xx_devlist, devlist) { | 1893 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
| 1891 | if (dev) | 1894 | if (dev) |
| 1892 | ops->fini(dev); | 1895 | ops->fini(dev); |
| @@ -1896,6 +1899,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) | |||
| 1896 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); | 1899 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); |
| 1897 | list_del(&ops->next); | 1900 | list_del(&ops->next); |
| 1898 | mutex_unlock(&em28xx_extension_devlist_lock); | 1901 | mutex_unlock(&em28xx_extension_devlist_lock); |
| 1902 | mutex_unlock(&em28xx_devlist_mutex); | ||
| 1899 | } | 1903 | } |
| 1900 | EXPORT_SYMBOL(em28xx_unregister_extension); | 1904 | EXPORT_SYMBOL(em28xx_unregister_extension); |
| 1901 | 1905 | ||
| @@ -1921,6 +1925,60 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
| 1921 | } | 1925 | } |
| 1922 | 1926 | ||
| 1923 | 1927 | ||
| 1928 | static int register_analog_devices(struct em28xx *dev) | ||
| 1929 | { | ||
| 1930 | int ret; | ||
| 1931 | |||
| 1932 | /* allocate and fill video video_device struct */ | ||
| 1933 | dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); | ||
| 1934 | if (!dev->vdev) { | ||
| 1935 | em28xx_errdev("cannot allocate video_device.\n"); | ||
| 1936 | return -ENODEV; | ||
| 1937 | } | ||
| 1938 | |||
| 1939 | /* register v4l2 video video_device */ | ||
| 1940 | ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, | ||
| 1941 | video_nr[dev->devno]); | ||
| 1942 | if (ret) { | ||
| 1943 | em28xx_errdev("unable to register video device (error=%i).\n", | ||
| 1944 | ret); | ||
| 1945 | return ret; | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | /* Allocate and fill vbi video_device struct */ | ||
| 1949 | dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); | ||
| 1950 | |||
| 1951 | /* register v4l2 vbi video_device */ | ||
| 1952 | ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | ||
| 1953 | vbi_nr[dev->devno]); | ||
| 1954 | if (ret < 0) { | ||
| 1955 | em28xx_errdev("unable to register vbi device\n"); | ||
| 1956 | return ret; | ||
| 1957 | } | ||
| 1958 | |||
| 1959 | if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { | ||
| 1960 | dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); | ||
| 1961 | if (!dev->radio_dev) { | ||
| 1962 | em28xx_errdev("cannot allocate video_device.\n"); | ||
| 1963 | return -ENODEV; | ||
| 1964 | } | ||
| 1965 | ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, | ||
| 1966 | radio_nr[dev->devno]); | ||
| 1967 | if (ret < 0) { | ||
| 1968 | em28xx_errdev("can't register radio device\n"); | ||
| 1969 | return ret; | ||
| 1970 | } | ||
| 1971 | em28xx_info("Registered radio device as /dev/radio%d\n", | ||
| 1972 | dev->radio_dev->num); | ||
| 1973 | } | ||
| 1974 | |||
| 1975 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | ||
| 1976 | dev->vdev->num, dev->vbi_dev->num); | ||
| 1977 | |||
| 1978 | return 0; | ||
| 1979 | } | ||
| 1980 | |||
| 1981 | |||
| 1924 | /* | 1982 | /* |
| 1925 | * em28xx_init_dev() | 1983 | * em28xx_init_dev() |
| 1926 | * allocates and inits the device structs, registers i2c bus and v4l device | 1984 | * allocates and inits the device structs, registers i2c bus and v4l device |
| @@ -2000,50 +2058,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 2000 | return errCode; | 2058 | return errCode; |
| 2001 | } | 2059 | } |
| 2002 | 2060 | ||
| 2003 | list_add_tail(&dev->devlist, &em28xx_devlist); | ||
| 2004 | |||
| 2005 | /* allocate and fill video video_device struct */ | ||
| 2006 | dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); | ||
| 2007 | if (NULL == dev->vdev) { | ||
| 2008 | em28xx_errdev("cannot allocate video_device.\n"); | ||
| 2009 | goto fail_unreg; | ||
| 2010 | } | ||
| 2011 | |||
| 2012 | /* register v4l2 video video_device */ | ||
| 2013 | retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, | ||
| 2014 | video_nr[dev->devno]); | ||
| 2015 | if (retval) { | ||
| 2016 | em28xx_errdev("unable to register video device (error=%i).\n", | ||
| 2017 | retval); | ||
| 2018 | goto fail_unreg; | ||
| 2019 | } | ||
| 2020 | |||
| 2021 | /* Allocate and fill vbi video_device struct */ | ||
| 2022 | dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); | ||
| 2023 | /* register v4l2 vbi video_device */ | ||
| 2024 | if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | ||
| 2025 | vbi_nr[dev->devno]) < 0) { | ||
| 2026 | em28xx_errdev("unable to register vbi device\n"); | ||
| 2027 | retval = -ENODEV; | ||
| 2028 | goto fail_unreg; | ||
| 2029 | } | ||
| 2030 | |||
| 2031 | if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { | ||
| 2032 | dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); | ||
| 2033 | if (NULL == dev->radio_dev) { | ||
| 2034 | em28xx_errdev("cannot allocate video_device.\n"); | ||
| 2035 | goto fail_unreg; | ||
| 2036 | } | ||
| 2037 | retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, | ||
| 2038 | radio_nr[dev->devno]); | ||
| 2039 | if (retval < 0) { | ||
| 2040 | em28xx_errdev("can't register radio device\n"); | ||
| 2041 | goto fail_unreg; | ||
| 2042 | } | ||
| 2043 | em28xx_info("Registered radio device as /dev/radio%d\n", | ||
| 2044 | dev->radio_dev->num); | ||
| 2045 | } | ||
| 2046 | |||
| 2047 | /* init video dma queues */ | 2061 | /* init video dma queues */ |
| 2048 | INIT_LIST_HEAD(&dev->vidq.active); | 2062 | INIT_LIST_HEAD(&dev->vidq.active); |
| 2049 | INIT_LIST_HEAD(&dev->vidq.queued); | 2063 | INIT_LIST_HEAD(&dev->vidq.queued); |
| @@ -2070,8 +2084,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 2070 | 2084 | ||
| 2071 | video_mux(dev, 0); | 2085 | video_mux(dev, 0); |
| 2072 | 2086 | ||
| 2073 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | 2087 | mutex_lock(&em28xx_devlist_mutex); |
| 2074 | dev->vdev->num, dev->vbi_dev->num); | 2088 | list_add_tail(&dev->devlist, &em28xx_devlist); |
| 2089 | retval = register_analog_devices(dev); | ||
| 2090 | if (retval < 0) { | ||
| 2091 | em28xx_release_resources(dev); | ||
| 2092 | mutex_unlock(&em28xx_devlist_mutex); | ||
| 2093 | goto fail_reg_devices; | ||
| 2094 | } | ||
| 2075 | 2095 | ||
| 2076 | mutex_lock(&em28xx_extension_devlist_lock); | 2096 | mutex_lock(&em28xx_extension_devlist_lock); |
| 2077 | if (!list_empty(&em28xx_extension_devlist)) { | 2097 | if (!list_empty(&em28xx_extension_devlist)) { |
| @@ -2081,11 +2101,13 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 2081 | } | 2101 | } |
| 2082 | } | 2102 | } |
| 2083 | mutex_unlock(&em28xx_extension_devlist_lock); | 2103 | mutex_unlock(&em28xx_extension_devlist_lock); |
| 2104 | mutex_unlock(&em28xx_devlist_mutex); | ||
| 2084 | 2105 | ||
| 2085 | return 0; | 2106 | return 0; |
| 2086 | 2107 | ||
| 2087 | fail_unreg: | 2108 | fail_unreg: |
| 2088 | em28xx_release_resources(dev); | 2109 | em28xx_release_resources(dev); |
| 2110 | fail_reg_devices: | ||
| 2089 | mutex_unlock(&dev->lock); | 2111 | mutex_unlock(&dev->lock); |
| 2090 | return retval; | 2112 | return retval; |
| 2091 | } | 2113 | } |
