diff options
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 33 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 58 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-i2c.c | 10 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 140 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 6 |
5 files changed, 145 insertions, 102 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index ac3292d7646c..7a8d49ef646e 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) | |||
62 | 62 | ||
63 | dprintk("Stopping isoc\n"); | 63 | dprintk("Stopping isoc\n"); |
64 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | 64 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { |
65 | usb_kill_urb(dev->adev->urb[i]); | 65 | usb_unlink_urb(dev->adev->urb[i]); |
66 | usb_free_urb(dev->adev->urb[i]); | 66 | usb_free_urb(dev->adev->urb[i]); |
67 | dev->adev->urb[i] = NULL; | 67 | dev->adev->urb[i] = NULL; |
68 | } | 68 | } |
@@ -75,7 +75,6 @@ static void em28xx_audio_isocirq(struct urb *urb) | |||
75 | struct em28xx *dev = urb->context; | 75 | struct em28xx *dev = urb->context; |
76 | int i; | 76 | int i; |
77 | unsigned int oldptr; | 77 | unsigned int oldptr; |
78 | unsigned long flags; | ||
79 | int period_elapsed = 0; | 78 | int period_elapsed = 0; |
80 | int status; | 79 | int status; |
81 | unsigned char *cp; | 80 | unsigned char *cp; |
@@ -96,9 +95,21 @@ static void em28xx_audio_isocirq(struct urb *urb) | |||
96 | if (!length) | 95 | if (!length) |
97 | continue; | 96 | continue; |
98 | 97 | ||
99 | spin_lock_irqsave(&dev->adev->slock, flags); | ||
100 | |||
101 | oldptr = dev->adev->hwptr_done_capture; | 98 | oldptr = dev->adev->hwptr_done_capture; |
99 | if (oldptr + length >= runtime->buffer_size) { | ||
100 | unsigned int cnt = | ||
101 | runtime->buffer_size - oldptr; | ||
102 | memcpy(runtime->dma_area + oldptr * stride, cp, | ||
103 | cnt * stride); | ||
104 | memcpy(runtime->dma_area, cp + cnt * stride, | ||
105 | length * stride - cnt * stride); | ||
106 | } else { | ||
107 | memcpy(runtime->dma_area + oldptr * stride, cp, | ||
108 | length * stride); | ||
109 | } | ||
110 | |||
111 | snd_pcm_stream_lock(substream); | ||
112 | |||
102 | dev->adev->hwptr_done_capture += length; | 113 | dev->adev->hwptr_done_capture += length; |
103 | if (dev->adev->hwptr_done_capture >= | 114 | if (dev->adev->hwptr_done_capture >= |
104 | runtime->buffer_size) | 115 | runtime->buffer_size) |
@@ -113,19 +124,7 @@ static void em28xx_audio_isocirq(struct urb *urb) | |||
113 | period_elapsed = 1; | 124 | period_elapsed = 1; |
114 | } | 125 | } |
115 | 126 | ||
116 | spin_unlock_irqrestore(&dev->adev->slock, flags); | 127 | snd_pcm_stream_unlock(substream); |
117 | |||
118 | if (oldptr + length >= runtime->buffer_size) { | ||
119 | unsigned int cnt = | ||
120 | runtime->buffer_size - oldptr; | ||
121 | memcpy(runtime->dma_area + oldptr * stride, cp, | ||
122 | cnt * stride); | ||
123 | memcpy(runtime->dma_area, cp + cnt * stride, | ||
124 | length * stride - cnt * stride); | ||
125 | } else { | ||
126 | memcpy(runtime->dma_area + oldptr * stride, cp, | ||
127 | length * stride); | ||
128 | } | ||
129 | } | 128 | } |
130 | if (period_elapsed) | 129 | if (period_elapsed) |
131 | snd_pcm_period_elapsed(substream); | 130 | snd_pcm_period_elapsed(substream); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 5d837c16ee22..15e2b525310d 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -69,19 +69,33 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, | |||
69 | int ret, byte; | 69 | int ret, byte; |
70 | 70 | ||
71 | if (dev->state & DEV_DISCONNECTED) | 71 | if (dev->state & DEV_DISCONNECTED) |
72 | return(-ENODEV); | 72 | return -ENODEV; |
73 | |||
74 | if (len > URB_MAX_CTRL_SIZE) | ||
75 | return -EINVAL; | ||
73 | 76 | ||
74 | em28xx_regdbg("req=%02x, reg=%02x ", req, reg); | 77 | em28xx_regdbg("req=%02x, reg=%02x ", req, reg); |
75 | 78 | ||
79 | mutex_lock(&dev->ctrl_urb_lock); | ||
76 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, | 80 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, |
77 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 81 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
78 | 0x0000, reg, buf, len, HZ); | 82 | 0x0000, reg, dev->urb_buf, len, HZ); |
83 | if (ret < 0) { | ||
84 | if (reg_debug) | ||
85 | printk(" failed!\n"); | ||
86 | mutex_unlock(&dev->ctrl_urb_lock); | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | if (len) | ||
91 | memcpy(buf, dev->urb_buf, len); | ||
92 | |||
93 | mutex_unlock(&dev->ctrl_urb_lock); | ||
79 | 94 | ||
80 | if (reg_debug) { | 95 | if (reg_debug) { |
81 | printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); | 96 | printk("%02x values: ", ret); |
82 | for (byte = 0; byte < len; byte++) | 97 | for (byte = 0; byte < len; byte++) |
83 | printk(" %02x", (unsigned char)buf[byte]); | 98 | printk(" %02x", (unsigned char)buf[byte]); |
84 | |||
85 | printk("\n"); | 99 | printk("\n"); |
86 | } | 100 | } |
87 | 101 | ||
@@ -102,16 +116,20 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) | |||
102 | 116 | ||
103 | em28xx_regdbg("req=%02x, reg=%02x:", req, reg); | 117 | em28xx_regdbg("req=%02x, reg=%02x:", req, reg); |
104 | 118 | ||
119 | mutex_lock(&dev->ctrl_urb_lock); | ||
105 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, | 120 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, |
106 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 121 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
107 | 0x0000, reg, &val, 1, HZ); | 122 | 0x0000, reg, dev->urb_buf, 1, HZ); |
108 | 123 | val = dev->urb_buf[0]; | |
109 | if (reg_debug) | 124 | mutex_unlock(&dev->ctrl_urb_lock); |
110 | printk(ret < 0 ? " failed!\n" : | ||
111 | "%02x\n", (unsigned char) val); | ||
112 | 125 | ||
113 | if (ret < 0) | 126 | if (ret < 0) { |
127 | printk(" failed!\n"); | ||
114 | return ret; | 128 | return ret; |
129 | } | ||
130 | |||
131 | if (reg_debug) | ||
132 | printk("%02x\n", (unsigned char) val); | ||
115 | 133 | ||
116 | return val; | 134 | return val; |
117 | } | 135 | } |
@@ -130,19 +148,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
130 | { | 148 | { |
131 | int ret; | 149 | int ret; |
132 | 150 | ||
133 | /*usb_control_msg seems to expect a kmalloced buffer */ | ||
134 | unsigned char *bufs; | ||
135 | |||
136 | if (dev->state & DEV_DISCONNECTED) | 151 | if (dev->state & DEV_DISCONNECTED) |
137 | return -ENODEV; | 152 | return -ENODEV; |
138 | 153 | ||
139 | if (len < 1) | 154 | if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) |
140 | return -EINVAL; | 155 | return -EINVAL; |
141 | 156 | ||
142 | bufs = kmalloc(len, GFP_KERNEL); | ||
143 | |||
144 | em28xx_regdbg("req=%02x reg=%02x:", req, reg); | 157 | em28xx_regdbg("req=%02x reg=%02x:", req, reg); |
145 | |||
146 | if (reg_debug) { | 158 | if (reg_debug) { |
147 | int i; | 159 | int i; |
148 | for (i = 0; i < len; ++i) | 160 | for (i = 0; i < len; ++i) |
@@ -150,16 +162,16 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
150 | printk("\n"); | 162 | printk("\n"); |
151 | } | 163 | } |
152 | 164 | ||
153 | if (!bufs) | 165 | mutex_lock(&dev->ctrl_urb_lock); |
154 | return -ENOMEM; | 166 | memcpy(dev->urb_buf, buf, len); |
155 | memcpy(bufs, buf, len); | ||
156 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, | 167 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, |
157 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 168 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
158 | 0x0000, reg, bufs, len, HZ); | 169 | 0x0000, reg, dev->urb_buf, len, HZ); |
170 | mutex_unlock(&dev->ctrl_urb_lock); | ||
171 | |||
159 | if (dev->wait_after_write) | 172 | if (dev->wait_after_write) |
160 | msleep(dev->wait_after_write); | 173 | msleep(dev->wait_after_write); |
161 | 174 | ||
162 | kfree(bufs); | ||
163 | return ret; | 175 | return ret; |
164 | } | 176 | } |
165 | 177 | ||
@@ -270,6 +282,8 @@ static int em28xx_set_audio_source(struct em28xx *dev) | |||
270 | break; | 282 | break; |
271 | case EM28XX_AMUX_LINE_IN: | 283 | case EM28XX_AMUX_LINE_IN: |
272 | input = EM28XX_AUDIO_SRC_LINE; | 284 | input = EM28XX_AUDIO_SRC_LINE; |
285 | video = disable; | ||
286 | line = enable; | ||
273 | break; | 287 | break; |
274 | case EM28XX_AMUX_AC97_VIDEO: | 288 | case EM28XX_AMUX_AC97_VIDEO: |
275 | input = EM28XX_AUDIO_SRC_LINE; | 289 | input = EM28XX_AUDIO_SRC_LINE; |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 3bab56b997fc..2360c61ddca9 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -337,9 +337,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
337 | /* Check if board has eeprom */ | 337 | /* Check if board has eeprom */ |
338 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); | 338 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); |
339 | if (err < 0) { | 339 | if (err < 0) { |
340 | em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", | 340 | em28xx_errdev("board has no eeprom\n"); |
341 | __func__, err); | 341 | memset(eedata, 0, len); |
342 | return err; | 342 | return -ENODEV; |
343 | } | 343 | } |
344 | 344 | ||
345 | buf = 0; | 345 | buf = 0; |
@@ -609,14 +609,16 @@ int em28xx_i2c_register(struct em28xx *dev) | |||
609 | dev->i2c_client.adapter = &dev->i2c_adap; | 609 | dev->i2c_client.adapter = &dev->i2c_adap; |
610 | 610 | ||
611 | retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); | 611 | retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); |
612 | if (retval < 0) { | 612 | if ((retval < 0) && (retval != -ENODEV)) { |
613 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", | 613 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", |
614 | __func__, retval); | 614 | __func__, retval); |
615 | |||
615 | return retval; | 616 | return retval; |
616 | } | 617 | } |
617 | 618 | ||
618 | if (i2c_scan) | 619 | if (i2c_scan) |
619 | em28xx_do_i2c_scan(dev); | 620 | em28xx_do_i2c_scan(dev); |
621 | |||
620 | return 0; | 622 | return 0; |
621 | } | 623 | } |
622 | 624 | ||
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a1ab2ef45578..610f535a257c 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 |
@@ -1936,6 +1994,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1936 | 1994 | ||
1937 | dev->udev = udev; | 1995 | dev->udev = udev; |
1938 | mutex_init(&dev->lock); | 1996 | mutex_init(&dev->lock); |
1997 | mutex_init(&dev->ctrl_urb_lock); | ||
1939 | spin_lock_init(&dev->slock); | 1998 | spin_lock_init(&dev->slock); |
1940 | init_waitqueue_head(&dev->open); | 1999 | init_waitqueue_head(&dev->open); |
1941 | init_waitqueue_head(&dev->wait_frame); | 2000 | init_waitqueue_head(&dev->wait_frame); |
@@ -1953,8 +2012,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1953 | errCode = em28xx_config(dev); | 2012 | errCode = em28xx_config(dev); |
1954 | if (errCode) { | 2013 | if (errCode) { |
1955 | em28xx_errdev("error configuring device\n"); | 2014 | em28xx_errdev("error configuring device\n"); |
1956 | em28xx_devused &= ~(1<<dev->devno); | ||
1957 | kfree(dev); | ||
1958 | return -ENOMEM; | 2015 | return -ENOMEM; |
1959 | } | 2016 | } |
1960 | 2017 | ||
@@ -2001,50 +2058,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2001 | return errCode; | 2058 | return errCode; |
2002 | } | 2059 | } |
2003 | 2060 | ||
2004 | list_add_tail(&dev->devlist, &em28xx_devlist); | ||
2005 | |||
2006 | /* allocate and fill video video_device struct */ | ||
2007 | dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); | ||
2008 | if (NULL == dev->vdev) { | ||
2009 | em28xx_errdev("cannot allocate video_device.\n"); | ||
2010 | goto fail_unreg; | ||
2011 | } | ||
2012 | |||
2013 | /* register v4l2 video video_device */ | ||
2014 | retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, | ||
2015 | video_nr[dev->devno]); | ||
2016 | if (retval) { | ||
2017 | em28xx_errdev("unable to register video device (error=%i).\n", | ||
2018 | retval); | ||
2019 | goto fail_unreg; | ||
2020 | } | ||
2021 | |||
2022 | /* Allocate and fill vbi video_device struct */ | ||
2023 | dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); | ||
2024 | /* register v4l2 vbi video_device */ | ||
2025 | if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | ||
2026 | vbi_nr[dev->devno]) < 0) { | ||
2027 | em28xx_errdev("unable to register vbi device\n"); | ||
2028 | retval = -ENODEV; | ||
2029 | goto fail_unreg; | ||
2030 | } | ||
2031 | |||
2032 | if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { | ||
2033 | dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); | ||
2034 | if (NULL == dev->radio_dev) { | ||
2035 | em28xx_errdev("cannot allocate video_device.\n"); | ||
2036 | goto fail_unreg; | ||
2037 | } | ||
2038 | retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, | ||
2039 | radio_nr[dev->devno]); | ||
2040 | if (retval < 0) { | ||
2041 | em28xx_errdev("can't register radio device\n"); | ||
2042 | goto fail_unreg; | ||
2043 | } | ||
2044 | em28xx_info("Registered radio device as /dev/radio%d\n", | ||
2045 | dev->radio_dev->num); | ||
2046 | } | ||
2047 | |||
2048 | /* init video dma queues */ | 2061 | /* init video dma queues */ |
2049 | INIT_LIST_HEAD(&dev->vidq.active); | 2062 | INIT_LIST_HEAD(&dev->vidq.active); |
2050 | INIT_LIST_HEAD(&dev->vidq.queued); | 2063 | INIT_LIST_HEAD(&dev->vidq.queued); |
@@ -2071,8 +2084,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2071 | 2084 | ||
2072 | video_mux(dev, 0); | 2085 | video_mux(dev, 0); |
2073 | 2086 | ||
2074 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | 2087 | mutex_lock(&em28xx_devlist_mutex); |
2075 | 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 | } | ||
2076 | 2095 | ||
2077 | mutex_lock(&em28xx_extension_devlist_lock); | 2096 | mutex_lock(&em28xx_extension_devlist_lock); |
2078 | if (!list_empty(&em28xx_extension_devlist)) { | 2097 | if (!list_empty(&em28xx_extension_devlist)) { |
@@ -2082,13 +2101,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2082 | } | 2101 | } |
2083 | } | 2102 | } |
2084 | mutex_unlock(&em28xx_extension_devlist_lock); | 2103 | mutex_unlock(&em28xx_extension_devlist_lock); |
2104 | mutex_unlock(&em28xx_devlist_mutex); | ||
2085 | 2105 | ||
2086 | return 0; | 2106 | return 0; |
2087 | 2107 | ||
2088 | fail_unreg: | 2108 | fail_reg_devices: |
2089 | em28xx_release_resources(dev); | ||
2090 | mutex_unlock(&dev->lock); | 2109 | mutex_unlock(&dev->lock); |
2091 | kfree(dev); | ||
2092 | return retval; | 2110 | return retval; |
2093 | } | 2111 | } |
2094 | 2112 | ||
@@ -2231,8 +2249,12 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2231 | 2249 | ||
2232 | /* allocate device struct */ | 2250 | /* allocate device struct */ |
2233 | retval = em28xx_init_dev(&dev, udev, nr); | 2251 | retval = em28xx_init_dev(&dev, udev, nr); |
2234 | if (retval) | 2252 | if (retval) { |
2253 | em28xx_devused &= ~(1<<dev->devno); | ||
2254 | kfree(dev); | ||
2255 | |||
2235 | return retval; | 2256 | return retval; |
2257 | } | ||
2236 | 2258 | ||
2237 | em28xx_info("Found %s\n", em28xx_boards[dev->model].name); | 2259 | em28xx_info("Found %s\n", em28xx_boards[dev->model].name); |
2238 | 2260 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 82781178e0a3..5956e9b3062f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -102,6 +102,9 @@ | |||
102 | #define EM28XX_MIN_BUF 4 | 102 | #define EM28XX_MIN_BUF 4 |
103 | #define EM28XX_DEF_BUF 8 | 103 | #define EM28XX_DEF_BUF 8 |
104 | 104 | ||
105 | /*Limits the max URB message size */ | ||
106 | #define URB_MAX_CTRL_SIZE 80 | ||
107 | |||
105 | /* Params for validated field */ | 108 | /* Params for validated field */ |
106 | #define EM28XX_BOARD_NOT_VALIDATED 1 | 109 | #define EM28XX_BOARD_NOT_VALIDATED 1 |
107 | #define EM28XX_BOARD_VALIDATED 0 | 110 | #define EM28XX_BOARD_VALIDATED 0 |
@@ -430,6 +433,7 @@ struct em28xx { | |||
430 | 433 | ||
431 | /* locks */ | 434 | /* locks */ |
432 | struct mutex lock; | 435 | struct mutex lock; |
436 | struct mutex ctrl_urb_lock; /* protects urb_buf */ | ||
433 | /* spinlock_t queue_lock; */ | 437 | /* spinlock_t queue_lock; */ |
434 | struct list_head inqueue, outqueue; | 438 | struct list_head inqueue, outqueue; |
435 | wait_queue_head_t open, wait_frame, wait_stream; | 439 | wait_queue_head_t open, wait_frame, wait_stream; |
@@ -451,6 +455,8 @@ struct em28xx { | |||
451 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | 455 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ |
452 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ | 456 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ |
453 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ | 457 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ |
458 | char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ | ||
459 | |||
454 | /* helper funcs that call usb_control_msg */ | 460 | /* helper funcs that call usb_control_msg */ |
455 | int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, | 461 | int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, |
456 | char *buf, int len); | 462 | char *buf, int len); |