diff options
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-audio.c')
| -rw-r--r-- | drivers/media/usb/em28xx/em28xx-audio.c | 128 |
1 files changed, 73 insertions, 55 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index e5120430ec80..30ee389a07f0 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> | 4 | * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com> | 6 | * Copyright (C) 2007-2014 Mauro Carvalho Chehab |
| 7 | * - Port to work with the in-kernel driver | 7 | * - Port to work with the in-kernel driver |
| 8 | * - Cleanups, fixes, alsa-controls, etc. | 8 | * - Cleanups, fixes, alsa-controls, etc. |
| 9 | * | 9 | * |
| @@ -70,16 +70,6 @@ static int em28xx_deinit_isoc_audio(struct em28xx *dev) | |||
| 70 | usb_kill_urb(urb); | 70 | usb_kill_urb(urb); |
| 71 | else | 71 | else |
| 72 | usb_unlink_urb(urb); | 72 | usb_unlink_urb(urb); |
| 73 | |||
| 74 | usb_free_coherent(dev->udev, | ||
| 75 | urb->transfer_buffer_length, | ||
| 76 | dev->adev.transfer_buffer[i], | ||
| 77 | urb->transfer_dma); | ||
| 78 | |||
| 79 | dev->adev.transfer_buffer[i] = NULL; | ||
| 80 | |||
| 81 | usb_free_urb(urb); | ||
| 82 | dev->adev.urb[i] = NULL; | ||
| 83 | } | 73 | } |
| 84 | 74 | ||
| 85 | return 0; | 75 | return 0; |
| @@ -174,53 +164,14 @@ static void em28xx_audio_isocirq(struct urb *urb) | |||
| 174 | static int em28xx_init_audio_isoc(struct em28xx *dev) | 164 | static int em28xx_init_audio_isoc(struct em28xx *dev) |
| 175 | { | 165 | { |
| 176 | int i, errCode; | 166 | int i, errCode; |
| 177 | const int sb_size = EM28XX_NUM_AUDIO_PACKETS * | ||
| 178 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
| 179 | 167 | ||
| 180 | dprintk("Starting isoc transfers\n"); | 168 | dprintk("Starting isoc transfers\n"); |
| 181 | 169 | ||
| 170 | /* Start streaming */ | ||
| 182 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | 171 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { |
| 183 | struct urb *urb; | 172 | memset(dev->adev.transfer_buffer[i], 0x80, |
| 184 | int j, k; | 173 | dev->adev.urb[i]->transfer_buffer_length); |
| 185 | void *buf; | ||
| 186 | |||
| 187 | urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); | ||
| 188 | if (!urb) { | ||
| 189 | em28xx_errdev("usb_alloc_urb failed!\n"); | ||
| 190 | for (j = 0; j < i; j++) { | ||
| 191 | usb_free_urb(dev->adev.urb[j]); | ||
| 192 | kfree(dev->adev.transfer_buffer[j]); | ||
| 193 | } | ||
| 194 | return -ENOMEM; | ||
| 195 | } | ||
| 196 | |||
| 197 | buf = usb_alloc_coherent(dev->udev, sb_size, GFP_ATOMIC, | ||
| 198 | &urb->transfer_dma); | ||
| 199 | if (!buf) | ||
| 200 | return -ENOMEM; | ||
| 201 | dev->adev.transfer_buffer[i] = buf; | ||
| 202 | memset(buf, 0x80, sb_size); | ||
| 203 | |||
| 204 | urb->dev = dev->udev; | ||
| 205 | urb->context = dev; | ||
| 206 | urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); | ||
| 207 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
| 208 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | ||
| 209 | urb->interval = 1; | ||
| 210 | urb->complete = em28xx_audio_isocirq; | ||
| 211 | urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; | ||
| 212 | urb->transfer_buffer_length = sb_size; | ||
| 213 | |||
| 214 | for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; | ||
| 215 | j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { | ||
| 216 | urb->iso_frame_desc[j].offset = k; | ||
| 217 | urb->iso_frame_desc[j].length = | ||
| 218 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
| 219 | } | ||
| 220 | dev->adev.urb[i] = urb; | ||
| 221 | } | ||
| 222 | 174 | ||
| 223 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | ||
| 224 | errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); | 175 | errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); |
| 225 | if (errCode) { | 176 | if (errCode) { |
| 226 | em28xx_errdev("submit of audio urb failed\n"); | 177 | em28xx_errdev("submit of audio urb failed\n"); |
| @@ -643,13 +594,36 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = { | |||
| 643 | .page = snd_pcm_get_vmalloc_page, | 594 | .page = snd_pcm_get_vmalloc_page, |
| 644 | }; | 595 | }; |
| 645 | 596 | ||
| 597 | static void em28xx_audio_free_urb(struct em28xx *dev) | ||
| 598 | { | ||
| 599 | int i; | ||
| 600 | |||
| 601 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | ||
| 602 | struct urb *urb = dev->adev.urb[i]; | ||
| 603 | |||
| 604 | if (!dev->adev.urb[i]) | ||
| 605 | continue; | ||
| 606 | |||
| 607 | usb_free_coherent(dev->udev, | ||
| 608 | urb->transfer_buffer_length, | ||
| 609 | dev->adev.transfer_buffer[i], | ||
| 610 | urb->transfer_dma); | ||
| 611 | |||
| 612 | usb_free_urb(urb); | ||
| 613 | dev->adev.urb[i] = NULL; | ||
| 614 | dev->adev.transfer_buffer[i] = NULL; | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 646 | static int em28xx_audio_init(struct em28xx *dev) | 618 | static int em28xx_audio_init(struct em28xx *dev) |
| 647 | { | 619 | { |
| 648 | struct em28xx_audio *adev = &dev->adev; | 620 | struct em28xx_audio *adev = &dev->adev; |
| 649 | struct snd_pcm *pcm; | 621 | struct snd_pcm *pcm; |
| 650 | struct snd_card *card; | 622 | struct snd_card *card; |
| 651 | static int devnr; | 623 | static int devnr; |
| 652 | int err; | 624 | int err, i; |
| 625 | const int sb_size = EM28XX_NUM_AUDIO_PACKETS * | ||
| 626 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
| 653 | 627 | ||
| 654 | if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { | 628 | if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { |
| 655 | /* This device does not support the extension (in this case | 629 | /* This device does not support the extension (in this case |
| @@ -662,7 +636,8 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
| 662 | 636 | ||
| 663 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " | 637 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " |
| 664 | "Rechberger\n"); | 638 | "Rechberger\n"); |
| 665 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n"); | 639 | printk(KERN_INFO |
| 640 | "em28xx-audio.c: Copyright (C) 2007-2014 Mauro Carvalho Chehab\n"); | ||
| 666 | 641 | ||
| 667 | err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, | 642 | err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, |
| 668 | &card); | 643 | &card); |
| @@ -704,6 +679,47 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
| 704 | em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER); | 679 | em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER); |
| 705 | } | 680 | } |
| 706 | 681 | ||
| 682 | /* Alloc URB and transfer buffers */ | ||
| 683 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | ||
| 684 | struct urb *urb; | ||
| 685 | int j, k; | ||
| 686 | void *buf; | ||
| 687 | |||
| 688 | urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); | ||
| 689 | if (!urb) { | ||
| 690 | em28xx_errdev("usb_alloc_urb failed!\n"); | ||
| 691 | em28xx_audio_free_urb(dev); | ||
| 692 | return -ENOMEM; | ||
| 693 | } | ||
| 694 | dev->adev.urb[i] = urb; | ||
| 695 | |||
| 696 | buf = usb_alloc_coherent(dev->udev, sb_size, GFP_ATOMIC, | ||
| 697 | &urb->transfer_dma); | ||
| 698 | if (!buf) { | ||
| 699 | em28xx_errdev("usb_alloc_coherent failed!\n"); | ||
| 700 | em28xx_audio_free_urb(dev); | ||
| 701 | return -ENOMEM; | ||
| 702 | } | ||
| 703 | dev->adev.transfer_buffer[i] = buf; | ||
| 704 | |||
| 705 | urb->dev = dev->udev; | ||
| 706 | urb->context = dev; | ||
| 707 | urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); | ||
| 708 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
| 709 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | ||
| 710 | urb->interval = 1; | ||
| 711 | urb->complete = em28xx_audio_isocirq; | ||
| 712 | urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; | ||
| 713 | urb->transfer_buffer_length = sb_size; | ||
| 714 | |||
| 715 | for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; | ||
| 716 | j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { | ||
| 717 | urb->iso_frame_desc[j].offset = k; | ||
| 718 | urb->iso_frame_desc[j].length = | ||
| 719 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 707 | err = snd_card_register(card); | 723 | err = snd_card_register(card); |
| 708 | if (err < 0) { | 724 | if (err < 0) { |
| 709 | snd_card_free(card); | 725 | snd_card_free(card); |
| @@ -728,6 +744,8 @@ static int em28xx_audio_fini(struct em28xx *dev) | |||
| 728 | return 0; | 744 | return 0; |
| 729 | } | 745 | } |
| 730 | 746 | ||
| 747 | em28xx_audio_free_urb(dev); | ||
| 748 | |||
| 731 | if (dev->adev.sndcard) { | 749 | if (dev->adev.sndcard) { |
| 732 | snd_card_free(dev->adev.sndcard); | 750 | snd_card_free(dev->adev.sndcard); |
| 733 | dev->adev.sndcard = NULL; | 751 | dev->adev.sndcard = NULL; |
