1/* 2 * Conexant Cx231xx audio extension 3 * 4 * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> 5 * Based on em28xx driver 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23#include <linux/kernel.h> 24#include <linux/usb.h> 25#include <linux/init.h> 26#include <linux/sound.h> 27#include <linux/spinlock.h> 28#include <linux/soundcard.h> 29#include <linux/slab.h> 30#include <linux/vmalloc.h> 31#include <linux/proc_fs.h> 32#include <linux/module.h> 33#include <sound/core.h> 34#include <sound/pcm.h> 35#include <sound/pcm_params.h> 36#include <sound/info.h> 37#include <sound/initval.h> 38#include <sound/control.h> 39#include <media/v4l2-common.h> 40#include "cx231xx.h" 41 42static int debug; 43module_param(debug, int, 0644); 44MODULE_PARM_DESC(debug, "activates debug info"); 45 46#define dprintk(fmt, arg...) do { \ 47 if (debug) \ 48 printk(KERN_INFO "cx231xx-audio %s: " fmt, \ 49 __func__, ##arg); \ 50 } while (0) 51 52static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 53 54static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) 55{ 56 int i; 57 58 dprintk("Stopping isoc\n"); 59 60 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 61 if (dev->adev.urb[i]) { 62 if (!irqs_disabled()) 63 usb_kill_urb(dev->adev.urb[i]); 64 else 65 usb_unlink_urb(dev->adev.urb[i]); 66 67 usb_free_urb(dev->adev.urb[i]); 68 dev->adev.urb[i] = NULL; 69 70 kfree(dev->adev.transfer_buffer[i]); 71 dev->adev.transfer_buffer[i] = NULL; 72 } 73 } 74 75 return 0; 76} 77 78static void cx231xx_audio_isocirq(struct urb *urb) 79{ 80 struct cx231xx *dev = urb->context; 81 int i; 82 unsigned int oldptr; 83 int period_elapsed = 0; 84 int status; 85 unsigned char *cp; 86 unsigned int stride; 87 struct snd_pcm_substream *substream; 88 struct snd_pcm_runtime *runtime; 89 90 switch (urb->status) { 91 case 0: /* success */ 92 case -ETIMEDOUT: /* NAK */ 93 break; 94 case -ECONNRESET: /* kill */ 95 case -ENOENT: 96 case -ESHUTDOWN: 97 return; 98 default: /* error */ 99 dprintk("urb completition error %d.\n", urb->status); 100 break; 101 } 102 103 if (dev->adev.capture_pcm_substream) { 104 substream = dev->adev.capture_pcm_substream; 105 runtime = substream->runtime; 106 stride = runtime->frame_bits >> 3; 107 108 for (i = 0; i < urb->number_of_packets; i++) { 109 int length = urb->iso_frame_desc[i].actual_length / 110 stride; 111 cp = (unsigned char *)urb->transfer_buffer + 112 urb->iso_frame_desc[i].offset; 113 114 if (!length) 115 continue; 116 117 oldptr = dev->adev.hwptr_done_capture; 118 if (oldptr + length >= runtime->buffer_size) { 119 unsigned int cnt; 120 121 cnt = runtime->buffer_size - oldptr; 122 memcpy(runtime->dma_area + oldptr * stride, cp, 123 cnt * stride); 124 memcpy(runtime->dma_area, cp + cnt * stride, 125 length * stride - cnt * stride); 126 } else { 127 memcpy(runtime->dma_area + oldptr * stride, cp, 128 length * stride); 129 } 130 131 snd_pcm_stream_lock(substream); 132 133 dev->adev.hwptr_done_capture += length; 134 if (dev->adev.hwptr_done_capture >= 135 runtime->buffer_size) 136 dev->adev.hwptr_done_capture -= 137 runtime->buffer_size; 138 139 dev->adev.capture_transfer_done += length; 140 if (dev->adev.capture_transfer_done >= 141 runtime->period_size) { 142 dev->adev.capture_transfer_done -= 143 runtime->period_size; 144 period_elapsed = 1; 145 } 146 snd_pcm_stream_unlock(substream); 147 } 148 if (period_elapsed) 149 snd_pcm_period_elapsed(substream); 150 } 151 urb->status = 0; 152 153 status = usb_submit_urb(urb, GFP_ATOMIC); 154 if (status < 0) { 155 cx231xx_errdev("resubmit of audio urb failed (error=%i)\n", 156 status); 157 } 158 return; 159} 160 161static int cx231xx_init_audio_isoc(struct cx231xx *dev) 162{ 163 int i, errCode; 164 int sb_size; 165 166 cx231xx_info("%s: Starting AUDIO transfers\n", __func__); 167 168 sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; 169 170 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 171 struct urb *urb; 172 int j, k; 173 174 dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); 175 if (!dev->adev.transfer_buffer[i]) 176 return -ENOMEM; 177 178 memset(dev->adev.transfer_buffer[i], 0x80, sb_size); 179 urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); 180 if (!urb) { 181 cx231xx_errdev("usb_alloc_urb failed!\n"); 182 for (j = 0; j < i; j++) { 183 usb_free_urb(dev->adev.urb[j]); 184 kfree(dev->adev.transfer_buffer[j]); 185 } 186 return -ENOMEM; 187 } 188 189 urb->dev = dev->udev; 190 urb->context = dev; 191 urb->pipe = usb_rcvisocpipe(dev->udev, 192 dev->adev.end_point_addr); 193 urb->transfer_flags = URB_ISO_ASAP; 194 urb->transfer_buffer = dev->adev.transfer_buffer[i]; 195 urb->interval = 1; 196 urb->complete = cx231xx_audio_isocirq; 197 urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS; 198 urb->transfer_buffer_length = sb_size; 199 200 for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; 201 j++, k += dev->adev.max_pkt_size) { 202 urb->iso_frame_desc[j].offset = k; 203 urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; 204 } 205 dev->adev.urb[i] = urb; 206 } 207 208 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 209 errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); 210 if (errCode < 0) { 211 cx231xx_isoc_audio_deinit(dev); 212 return errCode; 213 } 214 } 215 216 return errCode; 217} 218 219static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) 220{ 221 dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ? 222 "stop" : "start"); 223 224 switch (cmd) { 225 case CX231XX_CAPTURE_STREAM_EN: 226 if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { 227 dev->adev.capture_stream = STREAM_ON; 228 cx231xx_init_audio_isoc(dev); 229 } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { 230 dev->adev.capture_stream = STREAM_OFF; 231 cx231xx_isoc_audio_deinit(dev); 232 } else { 233 cx231xx_errdev("An underrun very likely occurred. " 234 "Ignoring it.\n"); 235 } 236 return 0; 237 default: 238 return -EINVAL; 239 } 240} 241 242static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, 243 size_t size) 244{ 245 struct snd_pcm_runtime *runtime = subs->runtime; 246 247 dprintk("Allocating vbuffer\n"); 248 if (runtime->dma_area) { 249 if (runtime->dma_bytes > size) 250 return 0; 251 252 vfree(runtime->dma_area); 253 } 254 runtime->dma_area = vmalloc(size); 255 if (!runtime->dma_area) 256 return -ENOMEM; 257 258 runtime->dma_bytes = size; 259 260 return 0; 261} 262 263static struct snd_pcm_hardware snd_cx231xx_hw_capture = { 264 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | 265 SNDRV_PCM_INFO_MMAP | 266 SNDRV_PCM_INFO_INTERLEAVED | 267 SNDRV_PCM_INFO_MMAP_VALID, 268 269 .formats = SNDRV_PCM_FMTBIT_S16_LE, 270 271 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, 272 273 .rate_min = 48000, 274 .rate_max = 48000, 275 .channels_min = 2, 276 .channels_max = 2, 277 .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ 278 .period_bytes_min = 64, /* 12544/2, */ 279 .period_bytes_max = 12544, 280 .periods_min = 2, 281 .periods_max = 98, /* 12544, */ 282}; 283 284static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) 285{ 286 struct cx231xx *dev = snd_pcm_substream_chip(substream); 287 struct snd_pcm_runtime *runtime = substream->runtime; 288 int ret = 0; 289 290 dprintk("opening device and trying to acquire exclusive lock\n"); 291 292 if (!dev) { 293 cx231xx_errdev("BUG: cx231xx can't find device struct." 294 " Can't proceed with open\n"); 295 return -ENODEV; 296 } 297 298 /* Sets volume, mute, etc */ 299 dev->mute = 0; 300 301 /* set alternate setting for audio interface */ 302 /* 1 - 48000 samples per sec */ 303 ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); 304 if (ret < 0) { 305 cx231xx_errdev("failed to set alternate setting !\n"); 306 307 return ret; 308 } 309 310 /* inform hardware to start streaming */ 311 ret = cx231xx_capture_start(dev, 1, Audio); 312 313 runtime->hw = snd_cx231xx_hw_capture; 314 315 mutex_lock(&dev->lock); 316 dev->adev.users++; 317 mutex_unlock(&dev->lock); 318 319 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 320 dev->adev.capture_pcm_substream = substream; 321 runtime->private_data = dev; 322 323 return 0; 324} 325 326static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) 327{ 328 int ret; 329 struct cx231xx *dev = snd_pcm_substream_chip(substream); 330 331 dprintk("closing device\n"); 332 333 /* set alternate setting for audio interface */ 334 /* 1 - 48000 samples per sec */ 335 ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); 336 if (ret < 0) { 337 cx231xx_errdev("failed to set alternate setting !\n"); 338 339 return ret; 340 } 341 342 /* inform hardware to start streaming */ 343 ret = cx231xx_capture_start(dev, 0, Audio); 344 345 dev->mute = 1; 346 mutex_lock(&dev->lock); 347 dev->adev.users--; 348 mutex_unlock(&dev->lock); 349 350 if (dev->adev.users == 0 && dev->adev.shutdown == 1) { 351 dprintk("audio users: %d\n", dev->adev.users); 352 dprintk("disabling audio stream!\n"); 353 dev->adev.shutdown = 0; 354 dprintk("released lock\n"); 355 cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, 0); 356 } 357 return 0; 358} 359 360static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, 361 struct snd_pcm_hw_params *hw_params) 362{ 363 unsigned int channels, rate, format; 364 int ret; 365 366 dprintk("Setting capture parameters\n"); 367 368 ret = snd_pcm_alloc_vmalloc_buffer(substream, 369 params_buffer_bytes(hw_params)); 370 format = params_format(hw_params); 371 rate = params_rate(hw_params); 372 channels = params_channels(hw_params); 373 374 /* TODO: set up cx231xx audio chip to deliver the correct audio format, 375 current default is 48000hz multiplexed => 96000hz mono 376 which shouldn't matter since analogue TV only supports mono */ 377 return 0; 378} 379 380static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) 381{ 382 struct cx231xx *dev = snd_pcm_substream_chip(substream); 383 384 dprintk("Stop capture, if needed\n"); 385 386 if (dev->adev.capture_stream == STREAM_ON) 387 cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); 388 389 return 0; 390} 391 392static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) 393{ 394 return 0; 395} 396 397static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, 398 int cmd) 399{ 400 struct cx231xx *dev = snd_pcm_substream_chip(substream); 401 int retval; 402 403 dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START) ? 404 "start" : "stop"); 405 406 spin_lock(&dev->adev.slock); 407 switch (cmd) { 408 case SNDRV_PCM_TRIGGER_START: 409 cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, 410 CX231XX_START_AUDIO); 411 retval = 0; 412 break; 413 case SNDRV_PCM_TRIGGER_STOP: 414 cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO); 415 retval = 0; 416 break; 417 default: 418 retval = -EINVAL; 419 } 420 421 spin_unlock(&dev->adev.slock); 422 return retval; 423} 424 425static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream 426 *substream) 427{ 428 struct cx231xx *dev; 429 unsigned long flags; 430 snd_pcm_uframes_t hwptr_done; 431 432 dev = snd_pcm_substream_chip(substream); 433 434 spin_lock_irqsave(&dev->adev.slock, flags); 435 hwptr_done = dev->adev.hwptr_done_capture; 436 spin_unlock_irqrestore(&dev->adev.slock, flags); 437 438 return hwptr_done; 439} 440 441static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, 442 unsigned long offset) 443{ 444 void *pageptr = subs->runtime->dma_area + offset; 445 446 return vmalloc_to_page(pageptr); 447} 448 449static struct snd_pcm_ops snd_cx231xx_pcm_capture = { 450 .open = snd_cx231xx_capture_open, 451 .close = snd_cx231xx_pcm_close, 452 .ioctl = snd_pcm_lib_ioctl, 453 .hw_params = snd_cx231xx_hw_capture_params, 454 .hw_free = snd_cx231xx_hw_capture_free, 455 .prepare = snd_cx231xx_prepare, 456 .trigger = snd_cx231xx_capture_trigger, 457 .pointer = snd_cx231xx_capture_pointer, 458 .page = snd_pcm_get_vmalloc_page, 459}; 460 461static int cx231xx_audio_init(struct cx231xx *dev) 462{ 463 struct cx231xx_audio *adev = &dev->adev; 464 struct snd_pcm *pcm; 465 struct snd_card *card; 466 static int devnr; 467 int err; 468 struct usb_interface *uif; 469 int i, isoc_pipe = 0; 470 471 if (dev->has_alsa_audio != 1) { 472 /* This device does not support the extension (in this case 473 the device is expecting the snd-usb-audio module or 474 doesn't have analog audio support at all) */ 475 return 0; 476 } 477 478 cx231xx_info("cx231xx-audio.c: probing for cx231xx " 479 "non standard usbaudio\n"); 480 481 err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE, 482 0, &card); 483 if (err < 0) 484 return err; 485 486 spin_lock_init(&adev->slock); 487 err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); 488 if (err < 0) { 489 snd_card_free(card); 490 return err; 491 } 492 493 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 494 &snd_cx231xx_pcm_capture); 495 pcm->info_flags = 0; 496 pcm->private_data = dev; 497 strcpy(pcm->name, "Conexant cx231xx Capture"); 498 strcpy(card->driver, "Cx231xx-Audio"); 499 strcpy(card->shortname, "Cx231xx Audio"); 500 strcpy(card->longname, "Conexant cx231xx Audio"); 501 502 err = snd_card_register(card); 503 if (err < 0) { 504 snd_card_free(card); 505 return err; 506 } 507 adev->sndcard = card; 508 adev->udev = dev->udev; 509 510 /* compute alternate max packet sizes for Audio */ 511 uif = 512 dev->udev->actconfig->interface[dev->current_pcb_config. 513 hs_config_info[0].interface_info. 514 audio_index + 1]; 515 516 adev->end_point_addr = 517 le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc. 518 bEndpointAddress); 519 520 adev->num_alt = uif->num_altsetting; 521 cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", 522 adev->end_point_addr, adev->num_alt); 523 adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); 524 525 if (adev->alt_max_pkt_size == NULL) { 526 cx231xx_errdev("out of memory!\n"); 527 return -ENOMEM; 528 } 529 530 for (i = 0; i < adev->num_alt; i++) { 531 u16 tmp = 532 le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. 533 wMaxPacketSize); 534 adev->alt_max_pkt_size[i] = 535 (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); 536 cx231xx_info("Alternate setting %i, max size= %i\n", i, 537 adev->alt_max_pkt_size[i]); 538 } 539 540 return 0; 541} 542 543static int cx231xx_audio_fini(struct cx231xx *dev) 544{ 545 if (dev == NULL) 546 return 0; 547 548 if (dev->has_alsa_audio != 1) { 549 /* This device does not support the extension (in this case 550 the device is expecting the snd-usb-audio module or 551 doesn't have analog audio support at all) */ 552 return 0; 553 } 554 555 if (dev->adev.sndcard) { 556 snd_card_free(dev->adev.sndcard); 557 kfree(dev->adev.alt_max_pkt_size); 558 dev->adev.sndcard = NULL; 559 } 560 561 return 0; 562} 563 564static struct cx231xx_ops audio_ops = { 565 .id = CX231XX_AUDIO, 566 .name = "Cx231xx Audio Extension", 567 .init = cx231xx_audio_init, 568 .fini = cx231xx_audio_fini, 569}; 570 571static int __init cx231xx_alsa_register(void) 572{ 573 return cx231xx_register_extension(&audio_ops); 574} 575 576static void __exit cx231xx_alsa_unregister(void) 577{ 578 cx231xx_unregister_extension(&audio_ops); 579} 580 581MODULE_LICENSE("GPL"); 582MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); 583MODULE_DESCRIPTION("Cx231xx Audio driver"); 584 585module_init(cx231xx_alsa_register); 586module_exit(cx231xx_alsa_unregister); 587