1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Conexant Cx231xx audio extension 4 * 5 * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> 6 * Based on em28xx driver 7 */ 8 9 #include "cx231xx.h" 10 #include <linux/kernel.h> 11 #include <linux/init.h> 12 #include <linux/sound.h> 13 #include <linux/spinlock.h> 14 #include <linux/soundcard.h> 15 #include <linux/slab.h> 16 #include <linux/vmalloc.h> 17 #include <linux/module.h> 18 #include <sound/core.h> 19 #include <sound/pcm.h> 20 #include <sound/pcm_params.h> 21 #include <sound/info.h> 22 #include <sound/initval.h> 23 #include <sound/control.h> 24 #include <media/v4l2-common.h> 25 26 static int debug; 27 module_param(debug, int, 0644); 28 MODULE_PARM_DESC(debug, "activates debug info"); 29 30 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 31 32 static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) 33 { 34 int i; 35 36 dev_dbg(dev->dev, "Stopping isoc\n"); 37 38 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 39 if (dev->adev.urb[i]) { 40 if (!irqs_disabled()) 41 usb_kill_urb(dev->adev.urb[i]); 42 else 43 usb_unlink_urb(dev->adev.urb[i]); 44 45 usb_free_urb(dev->adev.urb[i]); 46 dev->adev.urb[i] = NULL; 47 48 kfree(dev->adev.transfer_buffer[i]); 49 dev->adev.transfer_buffer[i] = NULL; 50 } 51 } 52 53 return 0; 54 } 55 56 static int cx231xx_bulk_audio_deinit(struct cx231xx *dev) 57 { 58 int i; 59 60 dev_dbg(dev->dev, "Stopping bulk\n"); 61 62 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 63 if (dev->adev.urb[i]) { 64 if (!irqs_disabled()) 65 usb_kill_urb(dev->adev.urb[i]); 66 else 67 usb_unlink_urb(dev->adev.urb[i]); 68 69 usb_free_urb(dev->adev.urb[i]); 70 dev->adev.urb[i] = NULL; 71 72 kfree(dev->adev.transfer_buffer[i]); 73 dev->adev.transfer_buffer[i] = NULL; 74 } 75 } 76 77 return 0; 78 } 79 80 static void cx231xx_audio_isocirq(struct urb *urb) 81 { 82 struct cx231xx *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 if (dev->state & DEV_DISCONNECTED) 93 return; 94 95 switch (urb->status) { 96 case 0: /* success */ 97 case -ETIMEDOUT: /* NAK */ 98 break; 99 case -ECONNRESET: /* kill */ 100 case -ENOENT: 101 case -ESHUTDOWN: 102 return; 103 default: /* error */ 104 dev_dbg(dev->dev, "urb completion error %d.\n", 105 urb->status); 106 break; 107 } 108 109 if (atomic_read(&dev->stream_started) == 0) 110 return; 111 112 if (dev->adev.capture_pcm_substream) { 113 substream = dev->adev.capture_pcm_substream; 114 runtime = substream->runtime; 115 stride = runtime->frame_bits >> 3; 116 117 for (i = 0; i < urb->number_of_packets; i++) { 118 unsigned long flags; 119 int length = urb->iso_frame_desc[i].actual_length / 120 stride; 121 cp = (unsigned char *)urb->transfer_buffer + 122 urb->iso_frame_desc[i].offset; 123 124 if (!length) 125 continue; 126 127 oldptr = dev->adev.hwptr_done_capture; 128 if (oldptr + length >= runtime->buffer_size) { 129 unsigned int cnt; 130 131 cnt = runtime->buffer_size - oldptr; 132 memcpy(runtime->dma_area + oldptr * stride, cp, 133 cnt * stride); 134 memcpy(runtime->dma_area, cp + cnt * stride, 135 length * stride - cnt * stride); 136 } else { 137 memcpy(runtime->dma_area + oldptr * stride, cp, 138 length * stride); 139 } 140 141 snd_pcm_stream_lock_irqsave(substream, flags); 142 143 dev->adev.hwptr_done_capture += length; 144 if (dev->adev.hwptr_done_capture >= 145 runtime->buffer_size) 146 dev->adev.hwptr_done_capture -= 147 runtime->buffer_size; 148 149 dev->adev.capture_transfer_done += length; 150 if (dev->adev.capture_transfer_done >= 151 runtime->period_size) { 152 dev->adev.capture_transfer_done -= 153 runtime->period_size; 154 period_elapsed = 1; 155 } 156 snd_pcm_stream_unlock_irqrestore(substream, flags); 157 } 158 if (period_elapsed) 159 snd_pcm_period_elapsed(substream); 160 } 161 urb->status = 0; 162 163 status = usb_submit_urb(urb, GFP_ATOMIC); 164 if (status < 0) { 165 dev_err(dev->dev, 166 "resubmit of audio urb failed (error=%i)\n", 167 status); 168 } 169 return; 170 } 171 172 static void cx231xx_audio_bulkirq(struct urb *urb) 173 { 174 struct cx231xx *dev = urb->context; 175 unsigned int oldptr; 176 int period_elapsed = 0; 177 int status; 178 unsigned char *cp; 179 unsigned int stride; 180 struct snd_pcm_substream *substream; 181 struct snd_pcm_runtime *runtime; 182 183 if (dev->state & DEV_DISCONNECTED) 184 return; 185 186 switch (urb->status) { 187 case 0: /* success */ 188 case -ETIMEDOUT: /* NAK */ 189 break; 190 case -ECONNRESET: /* kill */ 191 case -ENOENT: 192 case -ESHUTDOWN: 193 return; 194 default: /* error */ 195 dev_dbg(dev->dev, "urb completion error %d.\n", 196 urb->status); 197 break; 198 } 199 200 if (atomic_read(&dev->stream_started) == 0) 201 return; 202 203 if (dev->adev.capture_pcm_substream) { 204 substream = dev->adev.capture_pcm_substream; 205 runtime = substream->runtime; 206 stride = runtime->frame_bits >> 3; 207 208 if (1) { 209 unsigned long flags; 210 int length = urb->actual_length / 211 stride; 212 cp = (unsigned char *)urb->transfer_buffer; 213 214 oldptr = dev->adev.hwptr_done_capture; 215 if (oldptr + length >= runtime->buffer_size) { 216 unsigned int cnt; 217 218 cnt = runtime->buffer_size - oldptr; 219 memcpy(runtime->dma_area + oldptr * stride, cp, 220 cnt * stride); 221 memcpy(runtime->dma_area, cp + cnt * stride, 222 length * stride - cnt * stride); 223 } else { 224 memcpy(runtime->dma_area + oldptr * stride, cp, 225 length * stride); 226 } 227 228 snd_pcm_stream_lock_irqsave(substream, flags); 229 230 dev->adev.hwptr_done_capture += length; 231 if (dev->adev.hwptr_done_capture >= 232 runtime->buffer_size) 233 dev->adev.hwptr_done_capture -= 234 runtime->buffer_size; 235 236 dev->adev.capture_transfer_done += length; 237 if (dev->adev.capture_transfer_done >= 238 runtime->period_size) { 239 dev->adev.capture_transfer_done -= 240 runtime->period_size; 241 period_elapsed = 1; 242 } 243 snd_pcm_stream_unlock_irqrestore(substream, flags); 244 } 245 if (period_elapsed) 246 snd_pcm_period_elapsed(substream); 247 } 248 urb->status = 0; 249 250 status = usb_submit_urb(urb, GFP_ATOMIC); 251 if (status < 0) { 252 dev_err(dev->dev, 253 "resubmit of audio urb failed (error=%i)\n", 254 status); 255 } 256 return; 257 } 258 259 static int cx231xx_init_audio_isoc(struct cx231xx *dev) 260 { 261 int i, errCode; 262 int sb_size; 263 264 dev_dbg(dev->dev, 265 "%s: Starting ISO AUDIO transfers\n", __func__); 266 267 if (dev->state & DEV_DISCONNECTED) 268 return -ENODEV; 269 270 sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; 271 272 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 273 struct urb *urb; 274 int j, k; 275 276 dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); 277 if (!dev->adev.transfer_buffer[i]) 278 return -ENOMEM; 279 280 memset(dev->adev.transfer_buffer[i], 0x80, sb_size); 281 urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC); 282 if (!urb) { 283 for (j = 0; j < i; j++) { 284 usb_free_urb(dev->adev.urb[j]); 285 kfree(dev->adev.transfer_buffer[j]); 286 } 287 return -ENOMEM; 288 } 289 290 urb->dev = dev->udev; 291 urb->context = dev; 292 urb->pipe = usb_rcvisocpipe(dev->udev, 293 dev->adev.end_point_addr); 294 urb->transfer_flags = URB_ISO_ASAP; 295 urb->transfer_buffer = dev->adev.transfer_buffer[i]; 296 urb->interval = 1; 297 urb->complete = cx231xx_audio_isocirq; 298 urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS; 299 urb->transfer_buffer_length = sb_size; 300 301 for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS; 302 j++, k += dev->adev.max_pkt_size) { 303 urb->iso_frame_desc[j].offset = k; 304 urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; 305 } 306 dev->adev.urb[i] = urb; 307 } 308 309 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 310 errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); 311 if (errCode < 0) { 312 cx231xx_isoc_audio_deinit(dev); 313 return errCode; 314 } 315 } 316 317 return errCode; 318 } 319 320 static int cx231xx_init_audio_bulk(struct cx231xx *dev) 321 { 322 int i, errCode; 323 int sb_size; 324 325 dev_dbg(dev->dev, 326 "%s: Starting BULK AUDIO transfers\n", __func__); 327 328 if (dev->state & DEV_DISCONNECTED) 329 return -ENODEV; 330 331 sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; 332 333 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 334 struct urb *urb; 335 int j; 336 337 dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC); 338 if (!dev->adev.transfer_buffer[i]) 339 return -ENOMEM; 340 341 memset(dev->adev.transfer_buffer[i], 0x80, sb_size); 342 urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); 343 if (!urb) { 344 for (j = 0; j < i; j++) { 345 usb_free_urb(dev->adev.urb[j]); 346 kfree(dev->adev.transfer_buffer[j]); 347 } 348 return -ENOMEM; 349 } 350 351 urb->dev = dev->udev; 352 urb->context = dev; 353 urb->pipe = usb_rcvbulkpipe(dev->udev, 354 dev->adev.end_point_addr); 355 urb->transfer_flags = 0; 356 urb->transfer_buffer = dev->adev.transfer_buffer[i]; 357 urb->complete = cx231xx_audio_bulkirq; 358 urb->transfer_buffer_length = sb_size; 359 360 dev->adev.urb[i] = urb; 361 362 } 363 364 for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { 365 errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); 366 if (errCode < 0) { 367 cx231xx_bulk_audio_deinit(dev); 368 return errCode; 369 } 370 } 371 372 return errCode; 373 } 374 375 static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, 376 size_t size) 377 { 378 struct snd_pcm_runtime *runtime = subs->runtime; 379 struct cx231xx *dev = snd_pcm_substream_chip(subs); 380 381 dev_dbg(dev->dev, "Allocating vbuffer\n"); 382 if (runtime->dma_area) { 383 if (runtime->dma_bytes > size) 384 return 0; 385 386 vfree(runtime->dma_area); 387 } 388 runtime->dma_area = vmalloc(size); 389 if (!runtime->dma_area) 390 return -ENOMEM; 391 392 runtime->dma_bytes = size; 393 394 return 0; 395 } 396 397 static const struct snd_pcm_hardware snd_cx231xx_hw_capture = { 398 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | 399 SNDRV_PCM_INFO_MMAP | 400 SNDRV_PCM_INFO_INTERLEAVED | 401 SNDRV_PCM_INFO_MMAP_VALID, 402 403 .formats = SNDRV_PCM_FMTBIT_S16_LE, 404 405 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, 406 407 .rate_min = 48000, 408 .rate_max = 48000, 409 .channels_min = 2, 410 .channels_max = 2, 411 .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ 412 .period_bytes_min = 64, /* 12544/2, */ 413 .period_bytes_max = 12544, 414 .periods_min = 2, 415 .periods_max = 98, /* 12544, */ 416 }; 417 418 static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) 419 { 420 struct cx231xx *dev = snd_pcm_substream_chip(substream); 421 struct snd_pcm_runtime *runtime = substream->runtime; 422 int ret = 0; 423 424 dev_dbg(dev->dev, 425 "opening device and trying to acquire exclusive lock\n"); 426 427 if (dev->state & DEV_DISCONNECTED) { 428 dev_err(dev->dev, 429 "Can't open. the device was removed.\n"); 430 return -ENODEV; 431 } 432 433 /* set alternate setting for audio interface */ 434 /* 1 - 48000 samples per sec */ 435 mutex_lock(&dev->lock); 436 if (dev->USE_ISO) 437 ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); 438 else 439 ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); 440 mutex_unlock(&dev->lock); 441 if (ret < 0) { 442 dev_err(dev->dev, 443 "failed to set alternate setting !\n"); 444 445 return ret; 446 } 447 448 runtime->hw = snd_cx231xx_hw_capture; 449 450 mutex_lock(&dev->lock); 451 /* inform hardware to start streaming */ 452 ret = cx231xx_capture_start(dev, 1, Audio); 453 454 dev->adev.users++; 455 mutex_unlock(&dev->lock); 456 457 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 458 dev->adev.capture_pcm_substream = substream; 459 runtime->private_data = dev; 460 461 return 0; 462 } 463 464 static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) 465 { 466 int ret; 467 struct cx231xx *dev = snd_pcm_substream_chip(substream); 468 469 dev_dbg(dev->dev, "closing device\n"); 470 471 /* inform hardware to stop streaming */ 472 mutex_lock(&dev->lock); 473 ret = cx231xx_capture_start(dev, 0, Audio); 474 475 /* set alternate setting for audio interface */ 476 /* 1 - 48000 samples per sec */ 477 ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); 478 if (ret < 0) { 479 dev_err(dev->dev, 480 "failed to set alternate setting !\n"); 481 482 mutex_unlock(&dev->lock); 483 return ret; 484 } 485 486 dev->adev.users--; 487 if (substream->runtime->dma_area) { 488 dev_dbg(dev->dev, "freeing\n"); 489 vfree(substream->runtime->dma_area); 490 substream->runtime->dma_area = NULL; 491 } 492 mutex_unlock(&dev->lock); 493 494 if (dev->adev.users == 0 && dev->adev.shutdown == 1) { 495 dev_dbg(dev->dev, "audio users: %d\n", dev->adev.users); 496 dev_dbg(dev->dev, "disabling audio stream!\n"); 497 dev->adev.shutdown = 0; 498 dev_dbg(dev->dev, "released lock\n"); 499 if (atomic_read(&dev->stream_started) > 0) { 500 atomic_set(&dev->stream_started, 0); 501 schedule_work(&dev->wq_trigger); 502 } 503 } 504 return 0; 505 } 506 507 static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream, 508 struct snd_pcm_hw_params *hw_params) 509 { 510 struct cx231xx *dev = snd_pcm_substream_chip(substream); 511 int ret; 512 513 dev_dbg(dev->dev, "Setting capture parameters\n"); 514 515 ret = snd_pcm_alloc_vmalloc_buffer(substream, 516 params_buffer_bytes(hw_params)); 517 #if 0 518 /* TODO: set up cx231xx audio chip to deliver the correct audio format, 519 current default is 48000hz multiplexed => 96000hz mono 520 which shouldn't matter since analogue TV only supports mono */ 521 unsigned int channels, rate, format; 522 523 format = params_format(hw_params); 524 rate = params_rate(hw_params); 525 channels = params_channels(hw_params); 526 #endif 527 528 return ret; 529 } 530 531 static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) 532 { 533 struct cx231xx *dev = snd_pcm_substream_chip(substream); 534 535 dev_dbg(dev->dev, "Stop capture, if needed\n"); 536 537 if (atomic_read(&dev->stream_started) > 0) { 538 atomic_set(&dev->stream_started, 0); 539 schedule_work(&dev->wq_trigger); 540 } 541 542 return 0; 543 } 544 545 static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) 546 { 547 struct cx231xx *dev = snd_pcm_substream_chip(substream); 548 549 dev->adev.hwptr_done_capture = 0; 550 dev->adev.capture_transfer_done = 0; 551 552 return 0; 553 } 554 555 static void audio_trigger(struct work_struct *work) 556 { 557 struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger); 558 559 if (atomic_read(&dev->stream_started)) { 560 dev_dbg(dev->dev, "starting capture"); 561 if (is_fw_load(dev) == 0) 562 cx25840_call(dev, core, load_fw); 563 if (dev->USE_ISO) 564 cx231xx_init_audio_isoc(dev); 565 else 566 cx231xx_init_audio_bulk(dev); 567 } else { 568 dev_dbg(dev->dev, "stopping capture"); 569 cx231xx_isoc_audio_deinit(dev); 570 } 571 } 572 573 static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, 574 int cmd) 575 { 576 struct cx231xx *dev = snd_pcm_substream_chip(substream); 577 int retval = 0; 578 579 if (dev->state & DEV_DISCONNECTED) 580 return -ENODEV; 581 582 spin_lock(&dev->adev.slock); 583 switch (cmd) { 584 case SNDRV_PCM_TRIGGER_START: 585 atomic_set(&dev->stream_started, 1); 586 break; 587 case SNDRV_PCM_TRIGGER_STOP: 588 atomic_set(&dev->stream_started, 0); 589 break; 590 default: 591 retval = -EINVAL; 592 break; 593 } 594 spin_unlock(&dev->adev.slock); 595 596 schedule_work(&dev->wq_trigger); 597 598 return retval; 599 } 600 601 static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream 602 *substream) 603 { 604 struct cx231xx *dev; 605 unsigned long flags; 606 snd_pcm_uframes_t hwptr_done; 607 608 dev = snd_pcm_substream_chip(substream); 609 610 spin_lock_irqsave(&dev->adev.slock, flags); 611 hwptr_done = dev->adev.hwptr_done_capture; 612 spin_unlock_irqrestore(&dev->adev.slock, flags); 613 614 return hwptr_done; 615 } 616 617 static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, 618 unsigned long offset) 619 { 620 void *pageptr = subs->runtime->dma_area + offset; 621 622 return vmalloc_to_page(pageptr); 623 } 624 625 static const struct snd_pcm_ops snd_cx231xx_pcm_capture = { 626 .open = snd_cx231xx_capture_open, 627 .close = snd_cx231xx_pcm_close, 628 .ioctl = snd_pcm_lib_ioctl, 629 .hw_params = snd_cx231xx_hw_capture_params, 630 .hw_free = snd_cx231xx_hw_capture_free, 631 .prepare = snd_cx231xx_prepare, 632 .trigger = snd_cx231xx_capture_trigger, 633 .pointer = snd_cx231xx_capture_pointer, 634 .page = snd_pcm_get_vmalloc_page, 635 }; 636 637 static int cx231xx_audio_init(struct cx231xx *dev) 638 { 639 struct cx231xx_audio *adev = &dev->adev; 640 struct snd_pcm *pcm; 641 struct snd_card *card; 642 static int devnr; 643 int err; 644 struct usb_interface *uif; 645 int i, isoc_pipe = 0; 646 647 if (dev->has_alsa_audio != 1) { 648 /* This device does not support the extension (in this case 649 the device is expecting the snd-usb-audio module or 650 doesn't have analog audio support at all) */ 651 return 0; 652 } 653 654 dev_dbg(dev->dev, 655 "probing for cx231xx non standard usbaudio\n"); 656 657 err = snd_card_new(dev->dev, index[devnr], "Cx231xx Audio", 658 THIS_MODULE, 0, &card); 659 if (err < 0) 660 return err; 661 662 spin_lock_init(&adev->slock); 663 err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); 664 if (err < 0) 665 goto err_free_card; 666 667 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 668 &snd_cx231xx_pcm_capture); 669 pcm->info_flags = 0; 670 pcm->private_data = dev; 671 strscpy(pcm->name, "Conexant cx231xx Capture", sizeof(pcm->name)); 672 strscpy(card->driver, "Cx231xx-Audio", sizeof(card->driver)); 673 strscpy(card->shortname, "Cx231xx Audio", sizeof(card->shortname)); 674 strscpy(card->longname, "Conexant cx231xx Audio", sizeof(card->longname)); 675 676 INIT_WORK(&dev->wq_trigger, audio_trigger); 677 678 err = snd_card_register(card); 679 if (err < 0) 680 goto err_free_card; 681 682 adev->sndcard = card; 683 adev->udev = dev->udev; 684 685 /* compute alternate max packet sizes for Audio */ 686 uif = 687 dev->udev->actconfig->interface[dev->current_pcb_config. 688 hs_config_info[0].interface_info. 689 audio_index + 1]; 690 691 if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { 692 err = -ENODEV; 693 goto err_free_card; 694 } 695 696 adev->end_point_addr = 697 uif->altsetting[0].endpoint[isoc_pipe].desc. 698 bEndpointAddress; 699 700 adev->num_alt = uif->num_altsetting; 701 dev_info(dev->dev, 702 "audio EndPoint Addr 0x%x, Alternate settings: %i\n", 703 adev->end_point_addr, adev->num_alt); 704 adev->alt_max_pkt_size = kmalloc_array(32, adev->num_alt, GFP_KERNEL); 705 if (!adev->alt_max_pkt_size) { 706 err = -ENOMEM; 707 goto err_free_card; 708 } 709 710 for (i = 0; i < adev->num_alt; i++) { 711 u16 tmp; 712 713 if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { 714 err = -ENODEV; 715 goto err_free_pkt_size; 716 } 717 718 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. 719 wMaxPacketSize); 720 adev->alt_max_pkt_size[i] = 721 (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); 722 dev_dbg(dev->dev, 723 "audio alternate setting %i, max size= %i\n", i, 724 adev->alt_max_pkt_size[i]); 725 } 726 727 return 0; 728 729 err_free_pkt_size: 730 kfree(adev->alt_max_pkt_size); 731 err_free_card: 732 snd_card_free(card); 733 734 return err; 735 } 736 737 static int cx231xx_audio_fini(struct cx231xx *dev) 738 { 739 if (dev == NULL) 740 return 0; 741 742 if (dev->has_alsa_audio != 1) { 743 /* This device does not support the extension (in this case 744 the device is expecting the snd-usb-audio module or 745 doesn't have analog audio support at all) */ 746 return 0; 747 } 748 749 if (dev->adev.sndcard) { 750 snd_card_free(dev->adev.sndcard); 751 kfree(dev->adev.alt_max_pkt_size); 752 dev->adev.sndcard = NULL; 753 } 754 755 return 0; 756 } 757 758 static struct cx231xx_ops audio_ops = { 759 .id = CX231XX_AUDIO, 760 .name = "Cx231xx Audio Extension", 761 .init = cx231xx_audio_init, 762 .fini = cx231xx_audio_fini, 763 }; 764 765 static int __init cx231xx_alsa_register(void) 766 { 767 return cx231xx_register_extension(&audio_ops); 768 } 769 770 static void __exit cx231xx_alsa_unregister(void) 771 { 772 cx231xx_unregister_extension(&audio_ops); 773 } 774 775 MODULE_LICENSE("GPL"); 776 MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); 777 MODULE_DESCRIPTION("Cx231xx Audio driver"); 778 779 module_init(cx231xx_alsa_register); 780 module_exit(cx231xx_alsa_unregister); 781