em28xx-audio.c revision 758021bfa9ea25c58e62d2f68512628b19502ce7
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_isoc_audio_deinit(struct em28xx *dev) 60{ 61 int i; 62 63 dprintk("Stopping isoc\n"); 64 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { 65 usb_unlink_urb(dev->adev.urb[i]); 66 usb_free_urb(dev->adev.urb[i]); 67 dev->adev.urb[i] = NULL; 68 } 69 70 return 0; 71} 72 73static void em28xx_audio_isocirq(struct urb *urb) 74{ 75 struct em28xx *dev = urb->context; 76 int i; 77 unsigned int oldptr; 78 int period_elapsed = 0; 79 int status; 80 unsigned char *cp; 81 unsigned int stride; 82 struct snd_pcm_substream *substream; 83 struct snd_pcm_runtime *runtime; 84 if (dev->adev.capture_pcm_substream) { 85 substream = dev->adev.capture_pcm_substream; 86 runtime = substream->runtime; 87 stride = runtime->frame_bits >> 3; 88 89 for (i = 0; i < urb->number_of_packets; i++) { 90 int length = 91 urb->iso_frame_desc[i].actual_length / stride; 92 cp = (unsigned char *)urb->transfer_buffer + 93 urb->iso_frame_desc[i].offset; 94 95 if (!length) 96 continue; 97 98 oldptr = dev->adev.hwptr_done_capture; 99 if (oldptr + length >= runtime->buffer_size) { 100 unsigned int cnt = 101 runtime->buffer_size - oldptr; 102 memcpy(runtime->dma_area + oldptr * stride, cp, 103 cnt * stride); 104 memcpy(runtime->dma_area, cp + cnt * stride, 105 length * stride - cnt * stride); 106 } else { 107 memcpy(runtime->dma_area + oldptr * stride, cp, 108 length * stride); 109 } 110 111 snd_pcm_stream_lock(substream); 112 113 dev->adev.hwptr_done_capture += length; 114 if (dev->adev.hwptr_done_capture >= 115 runtime->buffer_size) 116 dev->adev.hwptr_done_capture -= 117 runtime->buffer_size; 118 119 dev->adev.capture_transfer_done += length; 120 if (dev->adev.capture_transfer_done >= 121 runtime->period_size) { 122 dev->adev.capture_transfer_done -= 123 runtime->period_size; 124 period_elapsed = 1; 125 } 126 127 snd_pcm_stream_unlock(substream); 128 } 129 if (period_elapsed) 130 snd_pcm_period_elapsed(substream); 131 } 132 urb->status = 0; 133 134 if (dev->adev.shutdown) 135 return; 136 137 status = usb_submit_urb(urb, GFP_ATOMIC); 138 if (status < 0) { 139 em28xx_errdev("resubmit of audio urb failed (error=%i)\n", 140 status); 141 } 142 return; 143} 144 145static int em28xx_init_audio_isoc(struct em28xx *dev) 146{ 147 int i, errCode; 148 const int sb_size = EM28XX_NUM_AUDIO_PACKETS * 149 EM28XX_AUDIO_MAX_PACKET_SIZE; 150 151 dprintk("Starting isoc transfers\n"); 152 153 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { 154 struct urb *urb; 155 int j, k; 156 157 dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); 158 if (!dev->adev.transfer_buffer[i]) 159 return -ENOMEM; 160 161 memset(dev->adev.transfer_buffer[i], 0x80, sb_size); 162 urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); 163 if (!urb) { 164 em28xx_errdev("usb_alloc_urb failed!\n"); 165 for (j = 0; j < i; j++) { 166 usb_free_urb(dev->adev.urb[j]); 167 kfree(dev->adev.transfer_buffer[j]); 168 } 169 return -ENOMEM; 170 } 171 172 urb->dev = dev->udev; 173 urb->context = dev; 174 urb->pipe = usb_rcvisocpipe(dev->udev, 0x83); 175 urb->transfer_flags = URB_ISO_ASAP; 176 urb->transfer_buffer = dev->adev.transfer_buffer[i]; 177 urb->interval = 1; 178 urb->complete = em28xx_audio_isocirq; 179 urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; 180 urb->transfer_buffer_length = sb_size; 181 182 for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; 183 j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { 184 urb->iso_frame_desc[j].offset = k; 185 urb->iso_frame_desc[j].length = 186 EM28XX_AUDIO_MAX_PACKET_SIZE; 187 } 188 dev->adev.urb[i] = urb; 189 } 190 191 for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { 192 errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); 193 if (errCode) { 194 em28xx_isoc_audio_deinit(dev); 195 196 return errCode; 197 } 198 } 199 200 return 0; 201} 202 203static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) 204{ 205 dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ? 206 "stop" : "start"); 207 208 switch (cmd) { 209 case EM28XX_CAPTURE_STREAM_EN: 210 if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { 211 dev->adev.capture_stream = STREAM_ON; 212 em28xx_init_audio_isoc(dev); 213 } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { 214 dev->adev.capture_stream = STREAM_OFF; 215 em28xx_isoc_audio_deinit(dev); 216 } else { 217 printk(KERN_ERR "An underrun very likely occurred. " 218 "Ignoring it.\n"); 219 } 220 return 0; 221 default: 222 return -EINVAL; 223 } 224} 225 226static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, 227 size_t size) 228{ 229 struct snd_pcm_runtime *runtime = subs->runtime; 230 231 dprintk("Alocating vbuffer\n"); 232 if (runtime->dma_area) { 233 if (runtime->dma_bytes > size) 234 return 0; 235 236 vfree(runtime->dma_area); 237 } 238 runtime->dma_area = vmalloc(size); 239 if (!runtime->dma_area) 240 return -ENOMEM; 241 242 runtime->dma_bytes = size; 243 244 return 0; 245} 246 247static struct snd_pcm_hardware snd_em28xx_hw_capture = { 248 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | 249 SNDRV_PCM_INFO_MMAP | 250 SNDRV_PCM_INFO_INTERLEAVED | 251 SNDRV_PCM_INFO_MMAP_VALID, 252 253 .formats = SNDRV_PCM_FMTBIT_S16_LE, 254 255 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, 256 257 .rate_min = 48000, 258 .rate_max = 48000, 259 .channels_min = 2, 260 .channels_max = 2, 261 .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ 262 .period_bytes_min = 64, /* 12544/2, */ 263 .period_bytes_max = 12544, 264 .periods_min = 2, 265 .periods_max = 98, /* 12544, */ 266}; 267 268static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) 269{ 270 struct em28xx *dev = snd_pcm_substream_chip(substream); 271 struct snd_pcm_runtime *runtime = substream->runtime; 272 int ret = 0; 273 274 dprintk("opening device and trying to acquire exclusive lock\n"); 275 276 if (!dev) { 277 printk(KERN_ERR "BUG: em28xx can't find device struct." 278 " Can't proceed with open\n"); 279 return -ENODEV; 280 } 281 282 /* Sets volume, mute, etc */ 283 284 dev->mute = 0; 285 mutex_lock(&dev->lock); 286 ret = em28xx_audio_analog_set(dev); 287 mutex_unlock(&dev->lock); 288 if (ret < 0) 289 goto err; 290 291 runtime->hw = snd_em28xx_hw_capture; 292 if (dev->alt == 0 && dev->adev.users == 0) { 293 int errCode; 294 dev->alt = 7; 295 errCode = usb_set_interface(dev->udev, 0, 7); 296 dprintk("changing alternate number to 7\n"); 297 } 298 299 dev->adev.users++; 300 301 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 302 dev->adev.capture_pcm_substream = substream; 303 runtime->private_data = dev; 304 305 return 0; 306err: 307 printk(KERN_ERR "Error while configuring em28xx mixer\n"); 308 return ret; 309} 310 311static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) 312{ 313 struct em28xx *dev = snd_pcm_substream_chip(substream); 314 dev->adev.users--; 315 316 dprintk("closing device\n"); 317 318 dev->mute = 1; 319 mutex_lock(&dev->lock); 320 em28xx_audio_analog_set(dev); 321 mutex_unlock(&dev->lock); 322 323 if (dev->adev.users == 0 && dev->adev.shutdown == 1) { 324 dprintk("audio users: %d\n", dev->adev.users); 325 dprintk("disabling audio stream!\n"); 326 dev->adev.shutdown = 0; 327 dprintk("released lock\n"); 328 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); 329 } 330 return 0; 331} 332 333static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream, 334 struct snd_pcm_hw_params *hw_params) 335{ 336 unsigned int channels, rate, format; 337 int ret; 338 339 dprintk("Setting capture parameters\n"); 340 341 ret = snd_pcm_alloc_vmalloc_buffer(substream, 342 params_buffer_bytes(hw_params)); 343 format = params_format(hw_params); 344 rate = params_rate(hw_params); 345 channels = params_channels(hw_params); 346 347 /* TODO: set up em28xx audio chip to deliver the correct audio format, 348 current default is 48000hz multiplexed => 96000hz mono 349 which shouldn't matter since analogue TV only supports mono */ 350 return 0; 351} 352 353static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) 354{ 355 struct em28xx *dev = snd_pcm_substream_chip(substream); 356 357 dprintk("Stop capture, if needed\n"); 358 359 if (dev->adev.capture_stream == STREAM_ON) 360 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); 361 362 return 0; 363} 364 365static int snd_em28xx_prepare(struct snd_pcm_substream *substream) 366{ 367 return 0; 368} 369 370static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, 371 int cmd) 372{ 373 struct em28xx *dev = snd_pcm_substream_chip(substream); 374 375 dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? 376 "start": "stop"); 377 switch (cmd) { 378 case SNDRV_PCM_TRIGGER_START: 379 em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); 380 return 0; 381 case SNDRV_PCM_TRIGGER_STOP: 382 dev->adev.shutdown = 1; 383 return 0; 384 default: 385 return -EINVAL; 386 } 387} 388 389static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream 390 *substream) 391{ 392 struct em28xx *dev; 393 394 snd_pcm_uframes_t hwptr_done; 395 dev = snd_pcm_substream_chip(substream); 396 hwptr_done = dev->adev.hwptr_done_capture; 397 398 return hwptr_done; 399} 400 401static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, 402 unsigned long offset) 403{ 404 void *pageptr = subs->runtime->dma_area + offset; 405 406 return vmalloc_to_page(pageptr); 407} 408 409static struct snd_pcm_ops snd_em28xx_pcm_capture = { 410 .open = snd_em28xx_capture_open, 411 .close = snd_em28xx_pcm_close, 412 .ioctl = snd_pcm_lib_ioctl, 413 .hw_params = snd_em28xx_hw_capture_params, 414 .hw_free = snd_em28xx_hw_capture_free, 415 .prepare = snd_em28xx_prepare, 416 .trigger = snd_em28xx_capture_trigger, 417 .pointer = snd_em28xx_capture_pointer, 418 .page = snd_pcm_get_vmalloc_page, 419}; 420 421static int em28xx_audio_init(struct em28xx *dev) 422{ 423 struct em28xx_audio *adev = &dev->adev; 424 struct snd_pcm *pcm; 425 struct snd_card *card; 426 static int devnr; 427 int err; 428 429 if (dev->has_alsa_audio != 1) { 430 /* This device does not support the extension (in this case 431 the device is expecting the snd-usb-audio module or 432 doesn't have analog audio support at all) */ 433 return 0; 434 } 435 436 printk(KERN_INFO "em28xx-audio.c: probing for em28x1 " 437 "non standard usbaudio\n"); 438 printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " 439 "Rechberger\n"); 440 441 err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, 442 &card); 443 if (err < 0) 444 return err; 445 446 spin_lock_init(&adev->slock); 447 err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); 448 if (err < 0) { 449 snd_card_free(card); 450 return err; 451 } 452 453 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture); 454 pcm->info_flags = 0; 455 pcm->private_data = dev; 456 strcpy(pcm->name, "Empia 28xx Capture"); 457 strcpy(card->driver, "Empia Em28xx Audio"); 458 strcpy(card->shortname, "Em28xx Audio"); 459 strcpy(card->longname, "Empia Em28xx Audio"); 460 461 err = snd_card_register(card); 462 if (err < 0) { 463 snd_card_free(card); 464 return err; 465 } 466 adev->sndcard = card; 467 adev->udev = dev->udev; 468 469 return 0; 470} 471 472static int em28xx_audio_fini(struct em28xx *dev) 473{ 474 if (dev == NULL) 475 return 0; 476 477 if (dev->has_alsa_audio != 1) { 478 /* This device does not support the extension (in this case 479 the device is expecting the snd-usb-audio module or 480 doesn't have analog audio support at all) */ 481 return 0; 482 } 483 484 if (dev->adev.sndcard) { 485 snd_card_free(dev->adev.sndcard); 486 dev->adev.sndcard = NULL; 487 } 488 489 return 0; 490} 491 492static struct em28xx_ops audio_ops = { 493 .id = EM28XX_AUDIO, 494 .name = "Em28xx Audio Extension", 495 .init = em28xx_audio_init, 496 .fini = em28xx_audio_fini, 497}; 498 499static int __init em28xx_alsa_register(void) 500{ 501 return em28xx_register_extension(&audio_ops); 502} 503 504static void __exit em28xx_alsa_unregister(void) 505{ 506 em28xx_unregister_extension(&audio_ops); 507} 508 509MODULE_LICENSE("GPL"); 510MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>"); 511MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 512MODULE_DESCRIPTION("Em28xx Audio driver"); 513 514module_init(em28xx_alsa_register); 515module_exit(em28xx_alsa_unregister); 516