]> err.no Git - linux-2.6/blob - drivers/media/video/em28xx/em28xx-audio.c
V4L/DVB (6950): Lindent em28xx-audio.c
[linux-2.6] / drivers / media / video / em28xx / em28xx-audio.c
1 /*
2  *  Empiatech em28x1 audio extension
3  *
4  *  Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
5  *
6  *  This driver is based on my previous au600 usb pstn audio driver
7  *  and inherits all the copyrights
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/usb.h>
26 #include <linux/init.h>
27 #include <linux/sound.h>
28 #include <linux/spinlock.h>
29 #include <linux/soundcard.h>
30 #include <linux/slab.h>
31 #include <linux/vmalloc.h>
32 #include <linux/proc_fs.h>
33 #include <linux/moduleparam.h>
34 #include <sound/driver.h>
35 #include <sound/core.h>
36 #include <sound/pcm.h>
37 #include <sound/pcm_params.h>
38 #include <sound/info.h>
39 #include <sound/initval.h>
40 #include <sound/control.h>
41 //#include <linux/video_decoder.h>
42 //#include <media/tuner.h>
43 #include <media/v4l2-common.h>
44 #include "em28xx.h"
45
46 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
47 static int em28xx_cmd(struct em28xx *dev, int cmd, int arg);
48
49 static 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
65 static struct snd_pcm_hardware snd_em28xx_hw_capture = {
66         .info =
67             SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP |
68             SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID,
69         .formats = SNDRV_PCM_FMTBIT_S16_LE,
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
82 static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
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
163 static 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
194 static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
195                                         struct snd_pcm_hw_params *hw_params)
196 {
197         unsigned int channels, rate, format;
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
210 static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
211 {
212         struct em28xx *dev = snd_pcm_substream_chip(substream);
213         if (dev->adev->capture_stream == STREAM_ON) {
214                 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
215         }
216         return 0;
217 }
218
219 static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
220 {
221         return 0;
222 }
223
224 static 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
240 static void em28xx_audio_isocirq(struct urb *urb)
241 {
242         struct em28xx *dev = urb->context;
243         int i;
244         unsigned int oldptr;
245         unsigned long flags;
246         int period_elapsed = 0;
247         int status;
248         unsigned char *cp;
249         unsigned int stride;
250         struct snd_pcm_substream *substream;
251         struct snd_pcm_runtime *runtime;
252         if (dev->adev->capture_pcm_substream) {
253                 substream = dev->adev->capture_pcm_substream;
254                 runtime = substream->runtime;
255
256                 stride = runtime->frame_bits >> 3;
257                 for (i = 0; i < urb->number_of_packets; i++) {
258                         int length =
259                             urb->iso_frame_desc[i].actual_length / stride;
260                         cp = (unsigned char *)urb->transfer_buffer +
261                             urb->iso_frame_desc[i].offset;
262
263                         if (!length)
264                                 continue;
265
266                         spin_lock_irqsave(&dev->adev->slock, flags);
267                         oldptr = dev->adev->hwptr_done_capture;
268                         dev->adev->hwptr_done_capture += length;
269                         if (dev->adev->hwptr_done_capture >=
270                             runtime->buffer_size)
271                                 dev->adev->hwptr_done_capture -=
272                                     runtime->buffer_size;
273
274                         dev->adev->capture_transfer_done += length;
275                         if (dev->adev->capture_transfer_done >=
276                             runtime->period_size) {
277                                 dev->adev->capture_transfer_done -=
278                                     runtime->period_size;
279                                 period_elapsed = 1;
280                         }
281                         spin_unlock_irqrestore(&dev->adev->slock, flags);
282
283                         if (oldptr + length >= runtime->buffer_size) {
284                                 unsigned int cnt =
285                                     runtime->buffer_size - oldptr - 1;
286                                 memcpy(runtime->dma_area + oldptr * stride, cp,
287                                        cnt * stride);
288                                 memcpy(runtime->dma_area, cp + cnt,
289                                        length * stride - cnt * stride);
290                         } else {
291                                 memcpy(runtime->dma_area + oldptr * stride, cp,
292                                        length * stride);
293                         }
294                 }
295                 if (period_elapsed) {
296                         snd_pcm_period_elapsed(substream);
297                 }
298         }
299         urb->status = 0;
300
301         if (dev->adev->shutdown)
302                 return;
303
304         if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {
305                 em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
306                               status);
307         }
308         return;
309 }
310
311 static 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
322 static int em28xx_init_audio_isoc(struct em28xx *dev)
323 {
324         int i;
325         int errCode;
326         const int sb_size =
327             EM28XX_NUM_AUDIO_PACKETS * EM28XX_AUDIO_MAX_PACKET_SIZE;
328
329         for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
330                 struct urb *urb;
331                 int j, k;
332                 dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
333                 if (!dev->adev->transfer_buffer[i]) {
334                         return -ENOMEM;
335                 }
336                 memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
337                 urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
338                 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;
357                 }
358         }
359         for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
360                 errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC);
361                 if (errCode) {
362                         em28xx_isoc_audio_deinit(dev);
363                         return errCode;
364                 }
365         }
366         return 0;
367 }
368
369 static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
370 {
371         switch (cmd) {
372         case EM28XX_CAPTURE_STREAM_EN:
373                 if (dev->adev->capture_stream == STREAM_OFF && arg == 1) {
374                         dev->adev->capture_stream = STREAM_ON;
375                         em28xx_init_audio_isoc(dev);
376                 } else if (dev->adev->capture_stream == STREAM_ON && arg == 0) {
377                         dev->adev->capture_stream = STREAM_OFF;
378                         em28xx_isoc_audio_deinit(dev);
379                 } else {
380                         printk
381                             ("An underrun occured very likely... ignoring it\n");
382                 }
383                 return 0;
384         default:
385                 return -EINVAL;
386         }
387 }
388
389 static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
390                                                     *substream)
391 {
392         struct em28xx *dev;
393         snd_pcm_uframes_t hwptr_done;
394         dev = snd_pcm_substream_chip(substream);
395         hwptr_done = dev->adev->hwptr_done_capture;
396         return hwptr_done;
397 }
398
399 static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
400                                              unsigned long offset)
401 {
402         void *pageptr = subs->runtime->dma_area + offset;
403         return vmalloc_to_page(pageptr);
404 }
405
406 static struct snd_pcm_ops snd_em28xx_pcm_capture = {
407         .open = snd_em28xx_capture_open,
408         .close = snd_em28xx_pcm_close,
409         .ioctl = snd_pcm_lib_ioctl,
410         .hw_params = snd_em28xx_hw_capture_params,
411         .hw_free = snd_em28xx_hw_capture_free,
412         .prepare = snd_em28xx_prepare,
413         .trigger = snd_em28xx_capture_trigger,
414         .pointer = snd_em28xx_capture_pointer,
415         .page = snd_pcm_get_vmalloc_page,
416 };
417
418 static int em28xx_audio_init(struct em28xx *dev)
419 {
420         struct em28xx_audio *adev;
421         struct snd_pcm *pcm;
422         struct snd_card *card;
423         static int devnr;
424         int ret;
425         int err;
426         printk("em28xx-audio.c: probing for em28x1 non standard usbaudio\n");
427         printk("em28xx-audio.c: Copyright (C) 2006 Markus Rechberger\n");
428         adev = kzalloc(sizeof(*adev), GFP_KERNEL);
429         if (!adev) {
430                 printk("em28xx-audio.c: out of memory\n");
431                 return -1;
432         }
433         card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
434         if (card == NULL) {
435                 kfree(adev);
436                 return -ENOMEM;
437         }
438
439         spin_lock_init(&adev->slock);
440         ret = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
441         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
442         pcm->info_flags = 0;
443         pcm->private_data = dev;
444         strcpy(pcm->name, "Empia 28xx Capture");
445         strcpy(card->driver, "Empia Em28xx Audio");
446         strcpy(card->shortname, "Em28xx Audio");
447         strcpy(card->longname, "Empia Em28xx Audio");
448
449         if ((err = snd_card_register(card)) < 0) {
450                 snd_card_free(card);
451                 return -ENOMEM;
452         }
453         adev->sndcard = card;
454         adev->udev = dev->udev;
455         dev->adev = adev;
456         return 0;
457 }
458
459 static int em28xx_audio_fini(struct em28xx *dev)
460 {
461         if (dev == NULL)
462                 return 0;
463         if (dev->adev) {
464                 snd_card_free(dev->adev->sndcard);
465                 kfree(dev->adev);
466                 dev->adev = NULL;
467         }
468         return 0;
469 }
470
471 static struct em28xx_ops audio_ops = {
472         .id = EM28XX_AUDIO,
473         .name = "Em28xx Audio Extension",
474         .init = em28xx_audio_init,
475         .fini = em28xx_audio_fini,
476 };
477
478 static int __init em28xx_alsa_register(void)
479 {
480         request_module("em28xx");
481         request_module("tuner");
482         return em28xx_register_extension(&audio_ops);
483 }
484
485 static void __exit em28xx_alsa_unregister(void)
486 {
487         em28xx_unregister_extension(&audio_ops);
488 }
489
490 MODULE_LICENSE("GPL");
491 MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
492 MODULE_DESCRIPTION("Em28xx Audio driver");
493
494 module_init(em28xx_alsa_register);
495 module_exit(em28xx_alsa_unregister);