aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-audio.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c507
1 files changed, 251 insertions, 256 deletions
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);