aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-01-05 07:57:31 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:04:32 -0500
commit6d79468dd8537530f4150e76ed9b4b63f80571c6 (patch)
treef785aeeec131c092b334e458127eb44fcf4ded2d /drivers/media/video
parent1a6f11e0e8db9e76ef34bc6731d5291e4df1ba37 (diff)
V4L/DVB (6951): Integrates em28xx-audio.c into em28xx kernel module
Also fixes the remaining CodingStyle issues that Lindent didn't fix. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/em28xx/Kconfig15
-rw-r--r--drivers/media/video/em28xx/Makefile3
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c507
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c63
-rw-r--r--drivers/media/video/em28xx/em28xx.h37
5 files changed, 365 insertions, 260 deletions
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index 813077b6ef7f..abbd38c1ebba 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -11,3 +11,18 @@ config VIDEO_EM28XX
11 11
12 To compile this driver as a module, choose M here: the 12 To compile this driver as a module, choose M here: the
13 module will be called em28xx 13 module will be called em28xx
14
15config VIDEO_EM28XX_ALSA
16 depends on VIDEO_EM28XX
17 tristate "Empia EM28xx ALSA audio module"
18 ---help---
19 This is an ALSA driver for some Empia 28xx based TV cards.
20
21 This is not required for em2800/em2820/em2821 boards. However,
22 newer em28xx devices uses Vendor Class for audio, instead of
23 implementing the USB Audio Class. For those chips, this module
24 will enable digital audio.
25
26 To compile this driver as a module, choose M here: the
27 module will be called em28xx-alsa
28
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
index 7e7a93d75c34..0924550992d0 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
@@ -1,7 +1,10 @@
1em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ 1em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \
2 em28xx-input.o 2 em28xx-input.o
3 3
4em28xx-alsa-objs := em28xx-audio.o
5
4obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o 6obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
7obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
5 8
6EXTRA_CFLAGS += -Idrivers/media/video 9EXTRA_CFLAGS += -Idrivers/media/video
7EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core 10EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index c631cac4c5d2..c91ff52aefad 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -3,6 +3,10 @@
3 * 3 *
4 * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> 4 * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
5 * 5 *
6 * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@infradead.org>
7 * - Port to work with the in-kernel driver
8 * - Several cleanups
9 *
6 * This driver is based on my previous au600 usb pstn audio driver 10 * This driver is based on my previous au600 usb pstn audio driver
7 * and inherits all the copyrights 11 * and inherits all the copyrights
8 * 12 *
@@ -30,7 +34,7 @@
30#include <linux/slab.h> 34#include <linux/slab.h>
31#include <linux/vmalloc.h> 35#include <linux/vmalloc.h>
32#include <linux/proc_fs.h> 36#include <linux/proc_fs.h>
33#include <linux/moduleparam.h> 37#include <linux/module.h>
34#include <sound/driver.h> 38#include <sound/driver.h>
35#include <sound/core.h> 39#include <sound/core.h>
36#include <sound/pcm.h> 40#include <sound/pcm.h>
@@ -38,222 +42,52 @@
38#include <sound/info.h> 42#include <sound/info.h>
39#include <sound/initval.h> 43#include <sound/initval.h>
40#include <sound/control.h> 44#include <sound/control.h>
41//#include <linux/video_decoder.h>
42//#include <media/tuner.h>
43#include <media/v4l2-common.h> 45#include <media/v4l2-common.h>
44#include "em28xx.h" 46#include "em28xx.h"
45 47
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 48static int debug;
47static int em28xx_cmd(struct em28xx *dev, int cmd, int arg); 49module_param(debug, int, 0644);
48 50MODULE_PARM_DESC(debug, "activates debug info");
49static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
50 size_t size)
51{
52 struct snd_pcm_runtime *runtime = subs->runtime;
53 if (runtime->dma_area) {
54 if (runtime->dma_bytes > size)
55 return 0;
56 vfree(runtime->dma_area);
57 }
58 runtime->dma_area = vmalloc(size);
59 if (!runtime->dma_area)
60 return -ENOMEM;
61 runtime->dma_bytes = size;
62 return 0;
63}
64 51
65static struct snd_pcm_hardware snd_em28xx_hw_capture = { 52#define dprintk(fmt, arg...) do { \
66 .info = 53 if (debug) \
67 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | 54 printk(KERN_INFO "em28xx-audio %s: " fmt, \
68 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID, 55 __FUNCTION__, ##arg); \
69 .formats = SNDRV_PCM_FMTBIT_S16_LE, 56 } while (0)
70 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
71 .rate_min = 48000,
72 .rate_max = 48000,
73 .channels_min = 2,
74 .channels_max = 2,
75 .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */
76 .period_bytes_min = 64, //12544/2,
77 .period_bytes_max = 12544,
78 .periods_min = 2,
79 .periods_max = 98, //12544,
80};
81 57
82static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) 58static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
83{
84 int ret = 0;
85 int mode;
86 struct em28xx *dev = snd_pcm_substream_chip(substream);
87 struct snd_pcm_runtime *runtime = substream->runtime;
88 printk("opening radio device and trying to acquire exclusive lock\n");
89 switch (dev->mode) {
90 case TUNER_STUB_DVBC_TV:
91 case TUNER_STUB_DVBT_TV:
92 case TUNER_STUB_ATSC_TV:
93 /* digital has no support for analog audio */
94 if (ret != 0) {
95 printk("device is already in use by DVB-T\n");
96 return -EINVAL;
97 } else {
98 struct v4l2_tuner tuner;
99 printk("switching device to FM mode\n");
100
101 mode = TUNER_STUB_RADIO;
102 memset(&tuner, 0x0, sizeof(struct v4l2_tuner));
103 tuner.type = V4L2_TUNER_RADIO;
104
105 /* enable GPIO for analog TV */
106 dev->em28xx_gpio_control(dev, EM28XX_MODE,
107 (void *)mode);
108 dev->mode = mode;
109 /* upload firmware */
110 tuner_run_cmd(dev->tobj, TUNER_CMD_INIT, (void *)mode);
111
112 /* required for devices which have kerneldriver dependencies */
113// em28xx_config(dev);
114// em28xx_config_i2c(dev);
115
116 /* this is moreover to switch the decoder to FM */
117 em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, &tuner);
118
119 dev->em28xx_write_regs(dev, 0x0f, "\x87", 1);
120 ret = dev->em28xx_acquire(dev, EM28XX_RADIO, 1);
121 em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, 0);
122 /* TODO switch to FM mode */
123
124 printk("em28xx-audio: %d mode\n", mode);
125 tuner_run_cmd(dev->tobj, TUNER_CMD_G_MODE, &mode);
126 printk("retrieved mode from tuner: %d\n", mode);
127 }
128 break;
129
130 case TUNER_STUB_ANALOG_TV:
131 printk("em28xx-audio: device is currently in analog TV mode\n");
132 /* unmute by default */
133 dev->em28xx_write_regs(dev, 0x0f, "\x87", 1);
134 break;
135 case TUNER_STUB_RADIO:
136 /* check current mode and put a hard lock onto it */
137 printk
138 ("em28xx-audio: device is currently in analogue FM mode\n");
139 /* unmute by default here */
140 dev->em28xx_write_regs(dev, 0x0f, "\x87", 1);
141 ret = dev->em28xx_acquire(dev, EM28XX_RADIO, 1);
142 if (ret == 0)
143 printk("device is locked in fmradio mode now\n");
144 break;
145 default:
146 printk("em28xx-audio: unhandled mode %d\n", dev->mode);
147 }
148
149 runtime->hw = snd_em28xx_hw_capture;
150 if (dev->alt == 0 && dev->adev->users == 0) {
151 int errCode;
152 dev->alt = 7;
153 errCode = usb_set_interface(dev->udev, 0, 7);
154 printk("changing alternate number to 7\n");
155 }
156 dev->adev->users++;
157 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
158 dev->adev->capture_pcm_substream = substream;
159 runtime->private_data = dev;
160 return 0;
161}
162
163static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
164{
165 struct em28xx *dev = snd_pcm_substream_chip(substream);
166 int amode = 0;
167 dev->adev->users--;
168
169 /* decrease audio reference */
170 switch (dev->mode) {
171 case TUNER_STUB_ANALOG_TV:
172 amode = EM28XX_VIDEO;
173 break;
174 case TUNER_STUB_RADIO:
175 amode = EM28XX_RADIO;
176 break;
177 default:
178 printk("invalid mode: %d\n", dev->mode);
179 break;
180 }
181
182 dev->em28xx_acquire(dev, amode, 0);
183
184 if (dev->adev->users == 0 && dev->adev->shutdown == 1) {
185 printk("audio users: %d\n", dev->adev->users);
186 printk("disabling audio stream!\n");
187 dev->adev->shutdown = 0;
188 printk("released lock\n");
189 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
190 }
191 return 0;
192}
193 59
194static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream, 60static int em28xx_isoc_audio_deinit(struct em28xx *dev)
195 struct snd_pcm_hw_params *hw_params)
196{ 61{
197 unsigned int channels, rate, format; 62 int i;
198 int ret;
199 ret =
200 snd_pcm_alloc_vmalloc_buffer(substream,
201 params_buffer_bytes(hw_params));
202 format = params_format(hw_params);
203 rate = params_rate(hw_params);
204 channels = params_channels(hw_params);
205 /* TODO: set up em28xx audio chip to deliver the correct audio format, current default is 48000hz multiplexed => 96000hz mono
206 which shouldn't matter since analogue TV only supports mono */
207 return 0;
208}
209 63
210static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) 64 dprintk("Stopping isoc\n");
211{ 65 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
212 struct em28xx *dev = snd_pcm_substream_chip(substream); 66 usb_kill_urb(dev->adev->urb[i]);
213 if (dev->adev->capture_stream == STREAM_ON) { 67 usb_free_urb(dev->adev->urb[i]);
214 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); 68 dev->adev->urb[i] = NULL;
215 } 69 }
216 return 0;
217}
218 70
219static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
220{
221 return 0; 71 return 0;
222} 72}
223 73
224static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
225 int cmd)
226{
227 struct em28xx *dev = snd_pcm_substream_chip(substream);
228 switch (cmd) {
229 case SNDRV_PCM_TRIGGER_START:
230 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1);
231 return 0;
232 case SNDRV_PCM_TRIGGER_STOP:
233 dev->adev->shutdown = 1;
234 return 0;
235 default:
236 return -EINVAL;
237 }
238}
239
240static void em28xx_audio_isocirq(struct urb *urb) 74static void em28xx_audio_isocirq(struct urb *urb)
241{ 75{
242 struct em28xx *dev = urb->context; 76 struct em28xx *dev = urb->context;
243 int i; 77 int i;
244 unsigned int oldptr; 78 unsigned int oldptr;
245 unsigned long flags; 79 unsigned long flags;
246 int period_elapsed = 0; 80 int period_elapsed = 0;
247 int status; 81 int status;
248 unsigned char *cp; 82 unsigned char *cp;
249 unsigned int stride; 83 unsigned int stride;
250 struct snd_pcm_substream *substream; 84 struct snd_pcm_substream *substream;
251 struct snd_pcm_runtime *runtime; 85 struct snd_pcm_runtime *runtime;
252 if (dev->adev->capture_pcm_substream) { 86 if (dev->adev->capture_pcm_substream) {
253 substream = dev->adev->capture_pcm_substream; 87 substream = dev->adev->capture_pcm_substream;
254 runtime = substream->runtime; 88 runtime = substream->runtime;
255
256 stride = runtime->frame_bits >> 3; 89 stride = runtime->frame_bits >> 3;
90
257 for (i = 0; i < urb->number_of_packets; i++) { 91 for (i = 0; i < urb->number_of_packets; i++) {
258 int length = 92 int length =
259 urb->iso_frame_desc[i].actual_length / stride; 93 urb->iso_frame_desc[i].actual_length / stride;
@@ -264,6 +98,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
264 continue; 98 continue;
265 99
266 spin_lock_irqsave(&dev->adev->slock, flags); 100 spin_lock_irqsave(&dev->adev->slock, flags);
101
267 oldptr = dev->adev->hwptr_done_capture; 102 oldptr = dev->adev->hwptr_done_capture;
268 dev->adev->hwptr_done_capture += length; 103 dev->adev->hwptr_done_capture += length;
269 if (dev->adev->hwptr_done_capture >= 104 if (dev->adev->hwptr_done_capture >=
@@ -278,6 +113,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
278 runtime->period_size; 113 runtime->period_size;
279 period_elapsed = 1; 114 period_elapsed = 1;
280 } 115 }
116
281 spin_unlock_irqrestore(&dev->adev->slock, flags); 117 spin_unlock_irqrestore(&dev->adev->slock, flags);
282 118
283 if (oldptr + length >= runtime->buffer_size) { 119 if (oldptr + length >= runtime->buffer_size) {
@@ -292,82 +128,79 @@ static void em28xx_audio_isocirq(struct urb *urb)
292 length * stride); 128 length * stride);
293 } 129 }
294 } 130 }
295 if (period_elapsed) { 131 if (period_elapsed)
296 snd_pcm_period_elapsed(substream); 132 snd_pcm_period_elapsed(substream);
297 }
298 } 133 }
299 urb->status = 0; 134 urb->status = 0;
300 135
301 if (dev->adev->shutdown) 136 if (dev->adev->shutdown)
302 return; 137 return;
303 138
304 if ((status = usb_submit_urb(urb, GFP_ATOMIC))) { 139 status = usb_submit_urb(urb, GFP_ATOMIC);
140 if (status < 0) {
305 em28xx_errdev("resubmit of audio urb failed (error=%i)\n", 141 em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
306 status); 142 status);
307 } 143 }
308 return; 144 return;
309} 145}
310 146
311static int em28xx_isoc_audio_deinit(struct em28xx *dev)
312{
313 int i;
314 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
315 usb_kill_urb(dev->adev->urb[i]);
316 usb_free_urb(dev->adev->urb[i]);
317 dev->adev->urb[i] = NULL;
318 }
319 return 0;
320}
321
322static int em28xx_init_audio_isoc(struct em28xx *dev) 147static int em28xx_init_audio_isoc(struct em28xx *dev)
323{ 148{
324 int i; 149 int i, errCode;
325 int errCode; 150 const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
326 const int sb_size = 151 EM28XX_AUDIO_MAX_PACKET_SIZE;
327 EM28XX_NUM_AUDIO_PACKETS * EM28XX_AUDIO_MAX_PACKET_SIZE; 152
153 dprintk("Starting isoc transfers\n");
328 154
329 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { 155 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
330 struct urb *urb; 156 struct urb *urb;
331 int j, k; 157 int j, k;
158
332 dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); 159 dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
333 if (!dev->adev->transfer_buffer[i]) { 160 if (!dev->adev->transfer_buffer[i])
334 return -ENOMEM; 161 return -ENOMEM;
335 } 162
336 memset(dev->adev->transfer_buffer[i], 0x80, sb_size); 163 memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
337 urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); 164 urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
338 if (urb) { 165 if (!urb)
339 urb->dev = dev->udev;
340 urb->context = dev;
341 urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
342 urb->transfer_flags = URB_ISO_ASAP;
343 urb->transfer_buffer = dev->adev->transfer_buffer[i];
344 urb->interval = 1;
345 urb->complete = em28xx_audio_isocirq;
346 urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
347 urb->transfer_buffer_length = sb_size;
348 for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
349 j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
350 urb->iso_frame_desc[j].offset = k;
351 urb->iso_frame_desc[j].length =
352 EM28XX_AUDIO_MAX_PACKET_SIZE;
353 }
354 dev->adev->urb[i] = urb;
355 } else {
356 return -ENOMEM; 166 return -ENOMEM;
167
168 urb->dev = dev->udev;
169 urb->context = dev;
170 urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
171 urb->transfer_flags = URB_ISO_ASAP;
172 urb->transfer_buffer = dev->adev->transfer_buffer[i];
173 urb->interval = 1;
174 urb->complete = em28xx_audio_isocirq;
175 urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
176 urb->transfer_buffer_length = sb_size;
177
178 for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
179 j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
180 urb->iso_frame_desc[j].offset = k;
181 urb->iso_frame_desc[j].length =
182 EM28XX_AUDIO_MAX_PACKET_SIZE;
357 } 183 }
184 dev->adev->urb[i] = urb;
358 } 185 }
186
359 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { 187 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
360 errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC); 188 errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC);
361 if (errCode) { 189 if (errCode) {
362 em28xx_isoc_audio_deinit(dev); 190 em28xx_isoc_audio_deinit(dev);
191
363 return errCode; 192 return errCode;
364 } 193 }
365 } 194 }
195
366 return 0; 196 return 0;
367} 197}
368 198
369static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) 199static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
370{ 200{
201 dprintk("%s transfer\n", (dev->adev->capture_stream == STREAM_ON)?
202 "stop" : "start");
203
371 switch (cmd) { 204 switch (cmd) {
372 case EM28XX_CAPTURE_STREAM_EN: 205 case EM28XX_CAPTURE_STREAM_EN:
373 if (dev->adev->capture_stream == STREAM_OFF && arg == 1) { 206 if (dev->adev->capture_stream == STREAM_OFF && arg == 1) {
@@ -377,8 +210,8 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
377 dev->adev->capture_stream = STREAM_OFF; 210 dev->adev->capture_stream = STREAM_OFF;
378 em28xx_isoc_audio_deinit(dev); 211 em28xx_isoc_audio_deinit(dev);
379 } else { 212 } else {
380 printk 213 printk(KERN_ERR "An underrun very likely occurred. "
381 ("An underrun occured very likely... ignoring it\n"); 214 "Ignoring it.\n");
382 } 215 }
383 return 0; 216 return 0;
384 default: 217 default:
@@ -386,13 +219,167 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
386 } 219 }
387} 220}
388 221
222static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
223 size_t size)
224{
225 struct snd_pcm_runtime *runtime = subs->runtime;
226
227 dprintk("Alocating vbuffer\n");
228 if (runtime->dma_area) {
229 if (runtime->dma_bytes > size)
230 return 0;
231
232 vfree(runtime->dma_area);
233 }
234 runtime->dma_area = vmalloc(size);
235 if (!runtime->dma_area)
236 return -ENOMEM;
237
238 runtime->dma_bytes = size;
239
240 return 0;
241}
242
243static struct snd_pcm_hardware snd_em28xx_hw_capture = {
244 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
245 SNDRV_PCM_INFO_MMAP |
246 SNDRV_PCM_INFO_INTERLEAVED |
247 SNDRV_PCM_INFO_MMAP_VALID,
248
249 .formats = SNDRV_PCM_FMTBIT_S16_LE,
250
251 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
252
253 .rate_min = 48000,
254 .rate_max = 48000,
255 .channels_min = 2,
256 .channels_max = 2,
257 .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */
258 .period_bytes_min = 64, /* 12544/2, */
259 .period_bytes_max = 12544,
260 .periods_min = 2,
261 .periods_max = 98, /* 12544, */
262};
263
264static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
265{
266 struct em28xx *dev = snd_pcm_substream_chip(substream);
267 struct snd_pcm_runtime *runtime = substream->runtime;
268 int ret = 0;
269
270 dprintk("opening device and trying to acquire exclusive lock\n");
271
272 /* Sets volume, mute, etc */
273 dev->mute = 0;
274 ret = em28xx_audio_analog_set(dev);
275 if (ret < 0)
276 goto err;
277
278 runtime->hw = snd_em28xx_hw_capture;
279 if (dev->alt == 0 && dev->adev->users == 0) {
280 int errCode;
281 dev->alt = 7;
282 errCode = usb_set_interface(dev->udev, 0, 7);
283 dprintk("changing alternate number to 7\n");
284 }
285
286 dev->adev->users++;
287
288 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
289 dev->adev->capture_pcm_substream = substream;
290 runtime->private_data = dev;
291
292 return 0;
293err:
294 printk(KERN_ERR "Error while configuring em28xx mixer\n");
295 return ret;
296}
297
298static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
299{
300 struct em28xx *dev = snd_pcm_substream_chip(substream);
301 dev->adev->users--;
302
303 dprintk("closing device\n");
304
305 dev->mute = 1;
306 em28xx_audio_analog_set(dev);
307
308 if (dev->adev->users == 0 && dev->adev->shutdown == 1) {
309 dprintk("audio users: %d\n", dev->adev->users);
310 dprintk("disabling audio stream!\n");
311 dev->adev->shutdown = 0;
312 dprintk("released lock\n");
313 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
314 }
315 return 0;
316}
317
318static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
319 struct snd_pcm_hw_params *hw_params)
320{
321 unsigned int channels, rate, format;
322 int ret;
323
324 dprintk("Setting capture parameters\n");
325
326 ret = snd_pcm_alloc_vmalloc_buffer(substream,
327 params_buffer_bytes(hw_params));
328 format = params_format(hw_params);
329 rate = params_rate(hw_params);
330 channels = params_channels(hw_params);
331
332 /* TODO: set up em28xx audio chip to deliver the correct audio format,
333 current default is 48000hz multiplexed => 96000hz mono
334 which shouldn't matter since analogue TV only supports mono */
335 return 0;
336}
337
338static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
339{
340 struct em28xx *dev = snd_pcm_substream_chip(substream);
341
342 dprintk("Stop capture, if needed\n");
343
344 if (dev->adev->capture_stream == STREAM_ON)
345 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
346
347 return 0;
348}
349
350static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
351{
352 return 0;
353}
354
355static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
356 int cmd)
357{
358 struct em28xx *dev = snd_pcm_substream_chip(substream);
359
360 dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)?
361 "start": "stop");
362 switch (cmd) {
363 case SNDRV_PCM_TRIGGER_START:
364 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1);
365 return 0;
366 case SNDRV_PCM_TRIGGER_STOP:
367 dev->adev->shutdown = 1;
368 return 0;
369 default:
370 return -EINVAL;
371 }
372}
373
389static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream 374static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
390 *substream) 375 *substream)
391{ 376{
392 struct em28xx *dev; 377 struct em28xx *dev;
378
393 snd_pcm_uframes_t hwptr_done; 379 snd_pcm_uframes_t hwptr_done;
394 dev = snd_pcm_substream_chip(substream); 380 dev = snd_pcm_substream_chip(substream);
395 hwptr_done = dev->adev->hwptr_done_capture; 381 hwptr_done = dev->adev->hwptr_done_capture;
382
396 return hwptr_done; 383 return hwptr_done;
397} 384}
398 385
@@ -400,34 +387,38 @@ static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
400 unsigned long offset) 387 unsigned long offset)
401{ 388{
402 void *pageptr = subs->runtime->dma_area + offset; 389 void *pageptr = subs->runtime->dma_area + offset;
390
403 return vmalloc_to_page(pageptr); 391 return vmalloc_to_page(pageptr);
404} 392}
405 393
406static struct snd_pcm_ops snd_em28xx_pcm_capture = { 394static struct snd_pcm_ops snd_em28xx_pcm_capture = {
407 .open = snd_em28xx_capture_open, 395 .open = snd_em28xx_capture_open,
408 .close = snd_em28xx_pcm_close, 396 .close = snd_em28xx_pcm_close,
409 .ioctl = snd_pcm_lib_ioctl, 397 .ioctl = snd_pcm_lib_ioctl,
410 .hw_params = snd_em28xx_hw_capture_params, 398 .hw_params = snd_em28xx_hw_capture_params,
411 .hw_free = snd_em28xx_hw_capture_free, 399 .hw_free = snd_em28xx_hw_capture_free,
412 .prepare = snd_em28xx_prepare, 400 .prepare = snd_em28xx_prepare,
413 .trigger = snd_em28xx_capture_trigger, 401 .trigger = snd_em28xx_capture_trigger,
414 .pointer = snd_em28xx_capture_pointer, 402 .pointer = snd_em28xx_capture_pointer,
415 .page = snd_pcm_get_vmalloc_page, 403 .page = snd_pcm_get_vmalloc_page,
416}; 404};
417 405
418static int em28xx_audio_init(struct em28xx *dev) 406static int em28xx_audio_init(struct em28xx *dev)
419{ 407{
420 struct em28xx_audio *adev; 408 struct em28xx_audio *adev;
421 struct snd_pcm *pcm; 409 struct snd_pcm *pcm;
422 struct snd_card *card; 410 struct snd_card *card;
423 static int devnr; 411 static int devnr;
424 int ret; 412 int ret, err;
425 int err; 413
426 printk("em28xx-audio.c: probing for em28x1 non standard usbaudio\n"); 414 printk(KERN_INFO "em28xx-audio.c: probing for em28x1 "
427 printk("em28xx-audio.c: Copyright (C) 2006 Markus Rechberger\n"); 415 "non standard usbaudio\n");
416 printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
417 "Rechberger\n");
418
428 adev = kzalloc(sizeof(*adev), GFP_KERNEL); 419 adev = kzalloc(sizeof(*adev), GFP_KERNEL);
429 if (!adev) { 420 if (!adev) {
430 printk("em28xx-audio.c: out of memory\n"); 421 printk(KERN_ERR "em28xx-audio.c: out of memory\n");
431 return -1; 422 return -1;
432 } 423 }
433 card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); 424 card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
@@ -446,13 +437,15 @@ static int em28xx_audio_init(struct em28xx *dev)
446 strcpy(card->shortname, "Em28xx Audio"); 437 strcpy(card->shortname, "Em28xx Audio");
447 strcpy(card->longname, "Empia Em28xx Audio"); 438 strcpy(card->longname, "Empia Em28xx Audio");
448 439
449 if ((err = snd_card_register(card)) < 0) { 440 err = snd_card_register(card);
441 if (err < 0) {
450 snd_card_free(card); 442 snd_card_free(card);
451 return -ENOMEM; 443 return -ENOMEM;
452 } 444 }
453 adev->sndcard = card; 445 adev->sndcard = card;
454 adev->udev = dev->udev; 446 adev->udev = dev->udev;
455 dev->adev = adev; 447 dev->adev = adev;
448
456 return 0; 449 return 0;
457} 450}
458 451
@@ -460,16 +453,18 @@ static int em28xx_audio_fini(struct em28xx *dev)
460{ 453{
461 if (dev == NULL) 454 if (dev == NULL)
462 return 0; 455 return 0;
456
463 if (dev->adev) { 457 if (dev->adev) {
464 snd_card_free(dev->adev->sndcard); 458 snd_card_free(dev->adev->sndcard);
465 kfree(dev->adev); 459 kfree(dev->adev);
466 dev->adev = NULL; 460 dev->adev = NULL;
467 } 461 }
462
468 return 0; 463 return 0;
469} 464}
470 465
471static struct em28xx_ops audio_ops = { 466static struct em28xx_ops audio_ops = {
472 .id = EM28XX_AUDIO, 467 .id = EM28XX_AUDIO,
473 .name = "Em28xx Audio Extension", 468 .name = "Em28xx Audio Extension",
474 .init = em28xx_audio_init, 469 .init = em28xx_audio_init,
475 .fini = em28xx_audio_fini, 470 .fini = em28xx_audio_fini,
@@ -478,7 +473,6 @@ static struct em28xx_ops audio_ops = {
478static int __init em28xx_alsa_register(void) 473static int __init em28xx_alsa_register(void)
479{ 474{
480 request_module("em28xx"); 475 request_module("em28xx");
481 request_module("tuner");
482 return em28xx_register_extension(&audio_ops); 476 return em28xx_register_extension(&audio_ops);
483} 477}
484 478
@@ -489,6 +483,7 @@ static void __exit em28xx_alsa_unregister(void)
489 483
490MODULE_LICENSE("GPL"); 484MODULE_LICENSE("GPL");
491MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>"); 485MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
486MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
492MODULE_DESCRIPTION("Em28xx Audio driver"); 487MODULE_DESCRIPTION("Em28xx Audio driver");
493 488
494module_init(em28xx_alsa_register); 489module_init(em28xx_alsa_register);
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 1a284cb18c24..caa4757b7eb6 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1599,9 +1599,48 @@ static const struct video_device em28xx_video_template = {
1599 .current_norm = V4L2_STD_PAL, 1599 .current_norm = V4L2_STD_PAL,
1600}; 1600};
1601 1601
1602
1603/******************************** usb interface *****************************************/ 1602/******************************** usb interface *****************************************/
1604 1603
1604
1605static LIST_HEAD(em28xx_extension_devlist);
1606static DEFINE_MUTEX(em28xx_extension_devlist_lock);
1607
1608int em28xx_register_extension(struct em28xx_ops *ops)
1609{
1610 struct em28xx *h, *dev = NULL;
1611
1612 list_for_each_entry(h, &em28xx_devlist, devlist)
1613 dev = h;
1614
1615 mutex_lock(&em28xx_extension_devlist_lock);
1616 list_add_tail(&ops->next, &em28xx_extension_devlist);
1617 if (dev)
1618 ops->init(dev);
1619
1620 printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
1621 mutex_unlock(&em28xx_extension_devlist_lock);
1622
1623 return 0;
1624}
1625EXPORT_SYMBOL(em28xx_register_extension);
1626
1627void em28xx_unregister_extension(struct em28xx_ops *ops)
1628{
1629 struct em28xx *h, *dev = NULL;
1630
1631 list_for_each_entry(h, &em28xx_devlist, devlist)
1632 dev = h;
1633
1634 if (dev)
1635 ops->fini(dev);
1636
1637 mutex_lock(&em28xx_extension_devlist_lock);
1638 printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
1639 list_del(&ops->next);
1640 mutex_unlock(&em28xx_extension_devlist_lock);
1641}
1642EXPORT_SYMBOL(em28xx_unregister_extension);
1643
1605/* 1644/*
1606 * em28xx_init_dev() 1645 * em28xx_init_dev()
1607 * allocates and inits the device structs, registers i2c bus and v4l device 1646 * allocates and inits the device structs, registers i2c bus and v4l device
@@ -1609,6 +1648,7 @@ static const struct video_device em28xx_video_template = {
1609static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, 1648static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1610 int minor) 1649 int minor)
1611{ 1650{
1651 struct em28xx_ops *ops = NULL;
1612 struct em28xx *dev = *devhandle; 1652 struct em28xx *dev = *devhandle;
1613 int retval = -ENOMEM; 1653 int retval = -ENOMEM;
1614 int errCode; 1654 int errCode;
@@ -1742,6 +1782,15 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1742 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, 1782 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
1743 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); 1783 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
1744 1784
1785 mutex_lock(&em28xx_extension_devlist_lock);
1786 if (!list_empty(&em28xx_extension_devlist)) {
1787 list_for_each_entry(ops, &em28xx_extension_devlist, next) {
1788 if (ops->id)
1789 ops->init(dev);
1790 }
1791 }
1792 mutex_unlock(&em28xx_extension_devlist_lock);
1793
1745 return 0; 1794 return 0;
1746} 1795}
1747 1796
@@ -1862,6 +1911,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
1862static void em28xx_usb_disconnect(struct usb_interface *interface) 1911static void em28xx_usb_disconnect(struct usb_interface *interface)
1863{ 1912{
1864 struct em28xx *dev; 1913 struct em28xx *dev;
1914 struct em28xx_ops *ops = NULL;
1865 1915
1866 dev = usb_get_intfdata(interface); 1916 dev = usb_get_intfdata(interface);
1867 usb_set_intfdata(interface, NULL); 1917 usb_set_intfdata(interface, NULL);
@@ -1891,15 +1941,20 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
1891 dev->state |= DEV_DISCONNECTED; 1941 dev->state |= DEV_DISCONNECTED;
1892 em28xx_release_resources(dev); 1942 em28xx_release_resources(dev);
1893 } 1943 }
1894
1895
1896 mutex_unlock(&dev->lock); 1944 mutex_unlock(&dev->lock);
1897 1945
1946 mutex_lock(&em28xx_extension_devlist_lock);
1947 if (!list_empty(&em28xx_extension_devlist)) {
1948 list_for_each_entry(ops, &em28xx_extension_devlist, next) {
1949 ops->fini(dev);
1950 }
1951 }
1952 mutex_unlock(&em28xx_extension_devlist_lock);
1953
1898 if (!dev->users) { 1954 if (!dev->users) {
1899 kfree(dev->alt_max_pkt_size); 1955 kfree(dev->alt_max_pkt_size);
1900 kfree(dev); 1956 kfree(dev);
1901 } 1957 }
1902
1903} 1958}
1904 1959
1905static struct usb_driver em28xx_usb_driver = { 1960static struct usb_driver em28xx_usb_driver = {
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 1fb3c230e232..c2d9ae0ac618 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -212,6 +212,28 @@ enum em28xx_dev_state {
212 DEV_MISCONFIGURED = 0x04, 212 DEV_MISCONFIGURED = 0x04,
213}; 213};
214 214
215#define EM28XX_AUDIO_BUFS 5
216#define EM28XX_NUM_AUDIO_PACKETS 64
217#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
218#define EM28XX_CAPTURE_STREAM_EN 1
219#define EM28XX_AUDIO 0x10
220
221struct em28xx_audio {
222 char name[50];
223 char *transfer_buffer[EM28XX_AUDIO_BUFS];
224 struct urb *urb[EM28XX_AUDIO_BUFS];
225 struct usb_device *udev;
226 unsigned int capture_transfer_done;
227 struct snd_pcm_substream *capture_pcm_substream;
228
229 unsigned int hwptr_done_capture;
230 struct snd_card *sndcard;
231
232 int users, shutdown;
233 enum em28xx_stream_state capture_stream;
234 spinlock_t slock;
235};
236
215/* main device struct */ 237/* main device struct */
216struct em28xx { 238struct em28xx {
217 /* generic device properties */ 239 /* generic device properties */
@@ -266,6 +288,8 @@ struct em28xx {
266 unsigned long hash; /* eeprom hash - for boards with generic ID */ 288 unsigned long hash; /* eeprom hash - for boards with generic ID */
267 unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */ 289 unsigned long i2c_hash; /* i2c devicelist hash - for boards with generic ID */
268 290
291 struct em28xx_audio *adev;
292
269 /* states */ 293 /* states */
270 enum em28xx_dev_state state; 294 enum em28xx_dev_state state;
271 enum em28xx_stream_state stream; 295 enum em28xx_stream_state stream;
@@ -302,6 +326,15 @@ struct em28xx {
302struct em28xx_fh { 326struct em28xx_fh {
303 struct em28xx *dev; 327 struct em28xx *dev;
304 unsigned int stream_on:1; /* Locks streams */ 328 unsigned int stream_on:1; /* Locks streams */
329 int radio;
330};
331
332struct em28xx_ops {
333 struct list_head next;
334 char *name;
335 int id;
336 int (*init)(struct em28xx *);
337 int (*fini)(struct em28xx *);
305}; 338};
306 339
307/* Provided by em28xx-i2c.c */ 340/* Provided by em28xx-i2c.c */
@@ -341,6 +374,10 @@ int em28xx_init_isoc(struct em28xx *dev);
341void em28xx_uninit_isoc(struct em28xx *dev); 374void em28xx_uninit_isoc(struct em28xx *dev);
342int em28xx_set_alternate(struct em28xx *dev); 375int em28xx_set_alternate(struct em28xx *dev);
343 376
377/* Provided by em28xx-video.c */
378int em28xx_register_extension(struct em28xx_ops *dev);
379void em28xx_unregister_extension(struct em28xx_ops *dev);
380
344/* Provided by em28xx-cards.c */ 381/* Provided by em28xx-cards.c */
345extern int em2800_variant_detect(struct usb_device* udev,int model); 382extern int em2800_variant_detect(struct usb_device* udev,int model);
346extern void em28xx_pre_card_setup(struct em28xx *dev); 383extern void em28xx_pre_card_setup(struct em28xx *dev);