PageRenderTime 77ms CodeModel.GetById 24ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/media/video/em28xx/em28xx-audio.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 545 lines | 415 code | 94 blank | 36 comment | 48 complexity | 006ca7bcb0307c297641163cf4125bc7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 *  Empiatech em28x1 audio extension
  3 *
  4 *  Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
  5 *
  6 *  Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@infradead.org>
  7 *	- Port to work with the in-kernel driver
  8 *	- Several cleanups
  9 *
 10 *  This driver is based on my previous au600 usb pstn audio driver
 11 *  and inherits all the copyrights
 12 *
 13 *  This program is free software; you can redistribute it and/or modify
 14 *  it under the terms of the GNU General Public License as published by
 15 *  the Free Software Foundation; either version 2 of the License, or
 16 *  (at your option) any later version.
 17 *
 18 *  This program is distributed in the hope that it will be useful,
 19 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21 *  GNU General Public License for more details.
 22 *
 23 *  You should have received a copy of the GNU General Public License
 24 *  along with this program; if not, write to the Free Software
 25 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 26 */
 27
 28#include <linux/kernel.h>
 29#include <linux/usb.h>
 30#include <linux/init.h>
 31#include <linux/sound.h>
 32#include <linux/spinlock.h>
 33#include <linux/soundcard.h>
 34#include <linux/slab.h>
 35#include <linux/vmalloc.h>
 36#include <linux/proc_fs.h>
 37#include <linux/module.h>
 38#include <sound/core.h>
 39#include <sound/pcm.h>
 40#include <sound/pcm_params.h>
 41#include <sound/info.h>
 42#include <sound/initval.h>
 43#include <sound/control.h>
 44#include <media/v4l2-common.h>
 45#include "em28xx.h"
 46
 47static int debug;
 48module_param(debug, int, 0644);
 49MODULE_PARM_DESC(debug, "activates debug info");
 50
 51#define dprintk(fmt, arg...) do {					\
 52	    if (debug)							\
 53		printk(KERN_INFO "em28xx-audio %s: " fmt,		\
 54				  __func__, ##arg); 		\
 55	} while (0)
 56
 57static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 58
 59static int em28xx_deinit_isoc_audio(struct em28xx *dev)
 60{
 61	int i;
 62
 63	dprintk("Stopping isoc\n");
 64	for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
 65		if (!irqs_disabled())
 66			usb_kill_urb(dev->adev.urb[i]);
 67		else
 68			usb_unlink_urb(dev->adev.urb[i]);
 69
 70		usb_free_urb(dev->adev.urb[i]);
 71		dev->adev.urb[i] = NULL;
 72
 73		kfree(dev->adev.transfer_buffer[i]);
 74		dev->adev.transfer_buffer[i] = NULL;
 75	}
 76
 77	return 0;
 78}
 79
 80static void em28xx_audio_isocirq(struct urb *urb)
 81{
 82	struct em28xx            *dev = urb->context;
 83	int                      i;
 84	unsigned int             oldptr;
 85	int                      period_elapsed = 0;
 86	int                      status;
 87	unsigned char            *cp;
 88	unsigned int             stride;
 89	struct snd_pcm_substream *substream;
 90	struct snd_pcm_runtime   *runtime;
 91
 92	switch (urb->status) {
 93	case 0:             /* success */
 94	case -ETIMEDOUT:    /* NAK */
 95		break;
 96	case -ECONNRESET:   /* kill */
 97	case -ENOENT:
 98	case -ESHUTDOWN:
 99		return;
100	default:            /* error */
101		dprintk("urb completition error %d.\n", urb->status);
102		break;
103	}
104
105	if (atomic_read(&dev->stream_started) == 0)
106		return;
107
108	if (dev->adev.capture_pcm_substream) {
109		substream = dev->adev.capture_pcm_substream;
110		runtime = substream->runtime;
111		stride = runtime->frame_bits >> 3;
112
113		for (i = 0; i < urb->number_of_packets; i++) {
114			int length =
115			    urb->iso_frame_desc[i].actual_length / stride;
116			cp = (unsigned char *)urb->transfer_buffer +
117			    urb->iso_frame_desc[i].offset;
118
119			if (!length)
120				continue;
121
122			oldptr = dev->adev.hwptr_done_capture;
123			if (oldptr + length >= runtime->buffer_size) {
124				unsigned int cnt =
125				    runtime->buffer_size - oldptr;
126				memcpy(runtime->dma_area + oldptr * stride, cp,
127				       cnt * stride);
128				memcpy(runtime->dma_area, cp + cnt * stride,
129				       length * stride - cnt * stride);
130			} else {
131				memcpy(runtime->dma_area + oldptr * stride, cp,
132				       length * stride);
133			}
134
135			snd_pcm_stream_lock(substream);
136
137			dev->adev.hwptr_done_capture += length;
138			if (dev->adev.hwptr_done_capture >=
139			    runtime->buffer_size)
140				dev->adev.hwptr_done_capture -=
141				    runtime->buffer_size;
142
143			dev->adev.capture_transfer_done += length;
144			if (dev->adev.capture_transfer_done >=
145			    runtime->period_size) {
146				dev->adev.capture_transfer_done -=
147				    runtime->period_size;
148				period_elapsed = 1;
149			}
150
151			snd_pcm_stream_unlock(substream);
152		}
153		if (period_elapsed)
154			snd_pcm_period_elapsed(substream);
155	}
156	urb->status = 0;
157
158	status = usb_submit_urb(urb, GFP_ATOMIC);
159	if (status < 0) {
160		em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
161			      status);
162	}
163	return;
164}
165
166static int em28xx_init_audio_isoc(struct em28xx *dev)
167{
168	int       i, errCode;
169	const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
170			    EM28XX_AUDIO_MAX_PACKET_SIZE;
171
172	dprintk("Starting isoc transfers\n");
173
174	for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
175		struct urb *urb;
176		int j, k;
177
178		dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
179		if (!dev->adev.transfer_buffer[i])
180			return -ENOMEM;
181
182		memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
183		urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
184		if (!urb) {
185			em28xx_errdev("usb_alloc_urb failed!\n");
186			for (j = 0; j < i; j++) {
187				usb_free_urb(dev->adev.urb[j]);
188				kfree(dev->adev.transfer_buffer[j]);
189			}
190			return -ENOMEM;
191		}
192
193		urb->dev = dev->udev;
194		urb->context = dev;
195		urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
196		urb->transfer_flags = URB_ISO_ASAP;
197		urb->transfer_buffer = dev->adev.transfer_buffer[i];
198		urb->interval = 1;
199		urb->complete = em28xx_audio_isocirq;
200		urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
201		urb->transfer_buffer_length = sb_size;
202
203		for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
204			     j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
205			urb->iso_frame_desc[j].offset = k;
206			urb->iso_frame_desc[j].length =
207			    EM28XX_AUDIO_MAX_PACKET_SIZE;
208		}
209		dev->adev.urb[i] = urb;
210	}
211
212	for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
213		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
214		if (errCode) {
215			em28xx_deinit_isoc_audio(dev);
216			return errCode;
217		}
218	}
219
220	return 0;
221}
222
223static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
224					size_t size)
225{
226	struct snd_pcm_runtime *runtime = subs->runtime;
227
228	dprintk("Allocating vbuffer\n");
229	if (runtime->dma_area) {
230		if (runtime->dma_bytes > size)
231			return 0;
232
233		vfree(runtime->dma_area);
234	}
235	runtime->dma_area = vmalloc(size);
236	if (!runtime->dma_area)
237		return -ENOMEM;
238
239	runtime->dma_bytes = size;
240
241	return 0;
242}
243
244static struct snd_pcm_hardware snd_em28xx_hw_capture = {
245	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
246		SNDRV_PCM_INFO_MMAP           |
247		SNDRV_PCM_INFO_INTERLEAVED    |
248		SNDRV_PCM_INFO_MMAP_VALID,
249
250	.formats = SNDRV_PCM_FMTBIT_S16_LE,
251
252	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
253
254	.rate_min = 48000,
255	.rate_max = 48000,
256	.channels_min = 2,
257	.channels_max = 2,
258	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
259	.period_bytes_min = 64,		/* 12544/2, */
260	.period_bytes_max = 12544,
261	.periods_min = 2,
262	.periods_max = 98,		/* 12544, */
263};
264
265static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
266{
267	struct em28xx *dev = snd_pcm_substream_chip(substream);
268	struct snd_pcm_runtime *runtime = substream->runtime;
269	int ret = 0;
270
271	dprintk("opening device and trying to acquire exclusive lock\n");
272
273	if (!dev) {
274		em28xx_err("BUG: em28xx can't find device struct."
275				" Can't proceed with open\n");
276		return -ENODEV;
277	}
278
279	/* Sets volume, mute, etc */
280
281	dev->mute = 0;
282	mutex_lock(&dev->lock);
283	ret = em28xx_audio_analog_set(dev);
284	if (ret < 0)
285		goto err;
286
287	runtime->hw = snd_em28xx_hw_capture;
288	if (dev->alt == 0 && dev->adev.users == 0) {
289		int errCode;
290		dev->alt = 7;
291		dprintk("changing alternate number to 7\n");
292		errCode = usb_set_interface(dev->udev, 0, 7);
293	}
294
295	dev->adev.users++;
296	mutex_unlock(&dev->lock);
297
298	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
299	dev->adev.capture_pcm_substream = substream;
300	runtime->private_data = dev;
301
302	return 0;
303err:
304	mutex_unlock(&dev->lock);
305
306	em28xx_err("Error while configuring em28xx mixer\n");
307	return ret;
308}
309
310static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
311{
312	struct em28xx *dev = snd_pcm_substream_chip(substream);
313
314	dprintk("closing device\n");
315
316	dev->mute = 1;
317	mutex_lock(&dev->lock);
318	dev->adev.users--;
319	if (atomic_read(&dev->stream_started) > 0) {
320		atomic_set(&dev->stream_started, 0);
321		schedule_work(&dev->wq_trigger);
322	}
323
324	em28xx_audio_analog_set(dev);
325	if (substream->runtime->dma_area) {
326		dprintk("freeing\n");
327		vfree(substream->runtime->dma_area);
328		substream->runtime->dma_area = NULL;
329	}
330	mutex_unlock(&dev->lock);
331
332	return 0;
333}
334
335static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
336					struct snd_pcm_hw_params *hw_params)
337{
338	unsigned int channels, rate, format;
339	int ret;
340
341	dprintk("Setting capture parameters\n");
342
343	ret = snd_pcm_alloc_vmalloc_buffer(substream,
344				params_buffer_bytes(hw_params));
345	format = params_format(hw_params);
346	rate = params_rate(hw_params);
347	channels = params_channels(hw_params);
348
349	/* TODO: set up em28xx audio chip to deliver the correct audio format,
350	   current default is 48000hz multiplexed => 96000hz mono
351	   which shouldn't matter since analogue TV only supports mono */
352	return 0;
353}
354
355static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
356{
357	struct em28xx *dev = snd_pcm_substream_chip(substream);
358
359	dprintk("Stop capture, if needed\n");
360
361	if (atomic_read(&dev->stream_started) > 0) {
362		atomic_set(&dev->stream_started, 0);
363		schedule_work(&dev->wq_trigger);
364	}
365
366	return 0;
367}
368
369static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
370{
371	struct em28xx *dev = snd_pcm_substream_chip(substream);
372
373	dev->adev.hwptr_done_capture = 0;
374	dev->adev.capture_transfer_done = 0;
375
376	return 0;
377}
378
379static void audio_trigger(struct work_struct *work)
380{
381	struct em28xx *dev = container_of(work, struct em28xx, wq_trigger);
382
383	if (atomic_read(&dev->stream_started)) {
384		dprintk("starting capture");
385		em28xx_init_audio_isoc(dev);
386	} else {
387		dprintk("stopping capture");
388		em28xx_deinit_isoc_audio(dev);
389	}
390}
391
392static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
393				      int cmd)
394{
395	struct em28xx *dev = snd_pcm_substream_chip(substream);
396	int retval;
397
398	switch (cmd) {
399	case SNDRV_PCM_TRIGGER_START:
400		atomic_set(&dev->stream_started, 1);
401		break;
402	case SNDRV_PCM_TRIGGER_STOP:
403		atomic_set(&dev->stream_started, 1);
404		break;
405	default:
406		retval = -EINVAL;
407	}
408	schedule_work(&dev->wq_trigger);
409	return 0;
410}
411
412static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
413						    *substream)
414{
415	unsigned long flags;
416	struct em28xx *dev;
417	snd_pcm_uframes_t hwptr_done;
418
419	dev = snd_pcm_substream_chip(substream);
420	spin_lock_irqsave(&dev->adev.slock, flags);
421	hwptr_done = dev->adev.hwptr_done_capture;
422	spin_unlock_irqrestore(&dev->adev.slock, flags);
423
424	return hwptr_done;
425}
426
427static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
428					     unsigned long offset)
429{
430	void *pageptr = subs->runtime->dma_area + offset;
431
432	return vmalloc_to_page(pageptr);
433}
434
435static struct snd_pcm_ops snd_em28xx_pcm_capture = {
436	.open      = snd_em28xx_capture_open,
437	.close     = snd_em28xx_pcm_close,
438	.ioctl     = snd_pcm_lib_ioctl,
439	.hw_params = snd_em28xx_hw_capture_params,
440	.hw_free   = snd_em28xx_hw_capture_free,
441	.prepare   = snd_em28xx_prepare,
442	.trigger   = snd_em28xx_capture_trigger,
443	.pointer   = snd_em28xx_capture_pointer,
444	.page      = snd_pcm_get_vmalloc_page,
445};
446
447static int em28xx_audio_init(struct em28xx *dev)
448{
449	struct em28xx_audio *adev = &dev->adev;
450	struct snd_pcm      *pcm;
451	struct snd_card     *card;
452	static int          devnr;
453	int                 err;
454
455	if (dev->has_alsa_audio != 1) {
456		/* This device does not support the extension (in this case
457		   the device is expecting the snd-usb-audio module or
458		   doesn't have analog audio support at all) */
459		return 0;
460	}
461
462	printk(KERN_INFO "em28xx-audio.c: probing for em28x1 "
463			 "non standard usbaudio\n");
464	printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
465			 "Rechberger\n");
466
467	err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
468			      &card);
469	if (err < 0)
470		return err;
471
472	spin_lock_init(&adev->slock);
473	err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
474	if (err < 0) {
475		snd_card_free(card);
476		return err;
477	}
478
479	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
480	pcm->info_flags = 0;
481	pcm->private_data = dev;
482	strcpy(pcm->name, "Empia 28xx Capture");
483
484	snd_card_set_dev(card, &dev->udev->dev);
485	strcpy(card->driver, "Em28xx-Audio");
486	strcpy(card->shortname, "Em28xx Audio");
487	strcpy(card->longname, "Empia Em28xx Audio");
488
489	INIT_WORK(&dev->wq_trigger, audio_trigger);
490
491	err = snd_card_register(card);
492	if (err < 0) {
493		snd_card_free(card);
494		return err;
495	}
496	adev->sndcard = card;
497	adev->udev = dev->udev;
498
499	return 0;
500}
501
502static int em28xx_audio_fini(struct em28xx *dev)
503{
504	if (dev == NULL)
505		return 0;
506
507	if (dev->has_alsa_audio != 1) {
508		/* This device does not support the extension (in this case
509		   the device is expecting the snd-usb-audio module or
510		   doesn't have analog audio support at all) */
511		return 0;
512	}
513
514	if (dev->adev.sndcard) {
515		snd_card_free(dev->adev.sndcard);
516		dev->adev.sndcard = NULL;
517	}
518
519	return 0;
520}
521
522static struct em28xx_ops audio_ops = {
523	.id   = EM28XX_AUDIO,
524	.name = "Em28xx Audio Extension",
525	.init = em28xx_audio_init,
526	.fini = em28xx_audio_fini,
527};
528
529static int __init em28xx_alsa_register(void)
530{
531	return em28xx_register_extension(&audio_ops);
532}
533
534static void __exit em28xx_alsa_unregister(void)
535{
536	em28xx_unregister_extension(&audio_ops);
537}
538
539MODULE_LICENSE("GPL");
540MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
541MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
542MODULE_DESCRIPTION("Em28xx Audio driver");
543
544module_init(em28xx_alsa_register);
545module_exit(em28xx_alsa_unregister);