diff options
Diffstat (limited to 'sound/usb/usbaudio.c')
-rw-r--r-- | sound/usb/usbaudio.c | 168 |
1 files changed, 128 insertions, 40 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index d5013383fad7..4e614ac39f21 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/usb.h> | 47 | #include <linux/usb.h> |
48 | #include <linux/vmalloc.h> | 48 | #include <linux/vmalloc.h> |
49 | #include <linux/moduleparam.h> | 49 | #include <linux/moduleparam.h> |
50 | #include <linux/mutex.h> | ||
50 | #include <sound/core.h> | 51 | #include <sound/core.h> |
51 | #include <sound/info.h> | 52 | #include <sound/info.h> |
52 | #include <sound/pcm.h> | 53 | #include <sound/pcm.h> |
@@ -69,6 +70,7 @@ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for | |||
69 | static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ | 70 | static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ |
70 | static int nrpacks = 4; /* max. number of packets per urb */ | 71 | static int nrpacks = 4; /* max. number of packets per urb */ |
71 | static int async_unlink = 1; | 72 | static int async_unlink = 1; |
73 | static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/ | ||
72 | 74 | ||
73 | module_param_array(index, int, NULL, 0444); | 75 | module_param_array(index, int, NULL, 0444); |
74 | MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); | 76 | MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); |
@@ -84,6 +86,8 @@ module_param(nrpacks, int, 0644); | |||
84 | MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); | 86 | MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); |
85 | module_param(async_unlink, bool, 0444); | 87 | module_param(async_unlink, bool, 0444); |
86 | MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); | 88 | MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); |
89 | module_param_array(device_setup, int, NULL, 0444); | ||
90 | MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); | ||
87 | 91 | ||
88 | 92 | ||
89 | /* | 93 | /* |
@@ -202,7 +206,7 @@ struct snd_usb_stream { | |||
202 | * the all interfaces on the same card as one sound device. | 206 | * the all interfaces on the same card as one sound device. |
203 | */ | 207 | */ |
204 | 208 | ||
205 | static DECLARE_MUTEX(register_mutex); | 209 | static DEFINE_MUTEX(register_mutex); |
206 | static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; | 210 | static struct snd_usb_audio *usb_chip[SNDRV_CARDS]; |
207 | 211 | ||
208 | 212 | ||
@@ -475,6 +479,18 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs, | |||
475 | return 0; | 479 | return 0; |
476 | } | 480 | } |
477 | 481 | ||
482 | /* determine the number of frames in the next packet */ | ||
483 | static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs) | ||
484 | { | ||
485 | if (subs->fill_max) | ||
486 | return subs->maxframesize; | ||
487 | else { | ||
488 | subs->phase = (subs->phase & 0xffff) | ||
489 | + (subs->freqm << subs->datainterval); | ||
490 | return min(subs->phase >> 16, subs->maxframesize); | ||
491 | } | ||
492 | } | ||
493 | |||
478 | /* | 494 | /* |
479 | * Prepare urb for streaming before playback starts. | 495 | * Prepare urb for streaming before playback starts. |
480 | * | 496 | * |
@@ -492,16 +508,7 @@ static int prepare_startup_playback_urb(struct snd_usb_substream *subs, | |||
492 | urb->dev = ctx->subs->dev; | 508 | urb->dev = ctx->subs->dev; |
493 | urb->number_of_packets = subs->packs_per_ms; | 509 | urb->number_of_packets = subs->packs_per_ms; |
494 | for (i = 0; i < subs->packs_per_ms; ++i) { | 510 | for (i = 0; i < subs->packs_per_ms; ++i) { |
495 | /* calculate the size of a packet */ | 511 | counts = snd_usb_audio_next_packet_size(subs); |
496 | if (subs->fill_max) | ||
497 | counts = subs->maxframesize; /* fixed */ | ||
498 | else { | ||
499 | subs->phase = (subs->phase & 0xffff) | ||
500 | + (subs->freqm << subs->datainterval); | ||
501 | counts = subs->phase >> 16; | ||
502 | if (counts > subs->maxframesize) | ||
503 | counts = subs->maxframesize; | ||
504 | } | ||
505 | urb->iso_frame_desc[i].offset = offs * stride; | 512 | urb->iso_frame_desc[i].offset = offs * stride; |
506 | urb->iso_frame_desc[i].length = counts * stride; | 513 | urb->iso_frame_desc[i].length = counts * stride; |
507 | offs += counts; | 514 | offs += counts; |
@@ -538,16 +545,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, | |||
538 | urb->number_of_packets = 0; | 545 | urb->number_of_packets = 0; |
539 | spin_lock_irqsave(&subs->lock, flags); | 546 | spin_lock_irqsave(&subs->lock, flags); |
540 | for (i = 0; i < ctx->packets; i++) { | 547 | for (i = 0; i < ctx->packets; i++) { |
541 | /* calculate the size of a packet */ | 548 | counts = snd_usb_audio_next_packet_size(subs); |
542 | if (subs->fill_max) | ||
543 | counts = subs->maxframesize; /* fixed */ | ||
544 | else { | ||
545 | subs->phase = (subs->phase & 0xffff) | ||
546 | + (subs->freqm << subs->datainterval); | ||
547 | counts = subs->phase >> 16; | ||
548 | if (counts > subs->maxframesize) | ||
549 | counts = subs->maxframesize; | ||
550 | } | ||
551 | /* set up descriptor */ | 549 | /* set up descriptor */ |
552 | urb->iso_frame_desc[i].offset = offs * stride; | 550 | urb->iso_frame_desc[i].offset = offs * stride; |
553 | urb->iso_frame_desc[i].length = counts * stride; | 551 | urb->iso_frame_desc[i].length = counts * stride; |
@@ -725,10 +723,9 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s | |||
725 | static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs) | 723 | static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs) |
726 | { | 724 | { |
727 | struct snd_pcm_runtime *runtime = subs->runtime; | 725 | struct snd_pcm_runtime *runtime = subs->runtime; |
728 | if (runtime->dma_area) { | 726 | |
729 | vfree(runtime->dma_area); | 727 | vfree(runtime->dma_area); |
730 | runtime->dma_area = NULL; | 728 | runtime->dma_area = NULL; |
731 | } | ||
732 | return 0; | 729 | return 0; |
733 | } | 730 | } |
734 | 731 | ||
@@ -779,6 +776,35 @@ static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sl | |||
779 | } | 776 | } |
780 | 777 | ||
781 | 778 | ||
779 | static const char *usb_error_string(int err) | ||
780 | { | ||
781 | switch (err) { | ||
782 | case -ENODEV: | ||
783 | return "no device"; | ||
784 | case -ENOENT: | ||
785 | return "endpoint not enabled"; | ||
786 | case -EPIPE: | ||
787 | return "endpoint stalled"; | ||
788 | case -ENOSPC: | ||
789 | return "not enough bandwidth"; | ||
790 | case -ESHUTDOWN: | ||
791 | return "device disabled"; | ||
792 | case -EHOSTUNREACH: | ||
793 | return "device suspended"; | ||
794 | #ifndef CONFIG_USB_EHCI_SPLIT_ISO | ||
795 | case -ENOSYS: | ||
796 | return "enable CONFIG_USB_EHCI_SPLIT_ISO to play through a hub"; | ||
797 | #endif | ||
798 | case -EINVAL: | ||
799 | case -EAGAIN: | ||
800 | case -EFBIG: | ||
801 | case -EMSGSIZE: | ||
802 | return "internal error"; | ||
803 | default: | ||
804 | return "unknown error"; | ||
805 | } | ||
806 | } | ||
807 | |||
782 | /* | 808 | /* |
783 | * set up and start data/sync urbs | 809 | * set up and start data/sync urbs |
784 | */ | 810 | */ |
@@ -811,16 +837,22 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru | |||
811 | subs->unlink_mask = 0; | 837 | subs->unlink_mask = 0; |
812 | subs->running = 1; | 838 | subs->running = 1; |
813 | for (i = 0; i < subs->nurbs; i++) { | 839 | for (i = 0; i < subs->nurbs; i++) { |
814 | if ((err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC)) < 0) { | 840 | err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC); |
815 | snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); | 841 | if (err < 0) { |
842 | snd_printk(KERN_ERR "cannot submit datapipe " | ||
843 | "for urb %d, error %d: %s\n", | ||
844 | i, err, usb_error_string(err)); | ||
816 | goto __error; | 845 | goto __error; |
817 | } | 846 | } |
818 | set_bit(i, &subs->active_mask); | 847 | set_bit(i, &subs->active_mask); |
819 | } | 848 | } |
820 | if (subs->syncpipe) { | 849 | if (subs->syncpipe) { |
821 | for (i = 0; i < SYNC_URBS; i++) { | 850 | for (i = 0; i < SYNC_URBS; i++) { |
822 | if ((err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC)) < 0) { | 851 | err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC); |
823 | snd_printk(KERN_ERR "cannot submit syncpipe for urb %d, err = %d\n", i, err); | 852 | if (err < 0) { |
853 | snd_printk(KERN_ERR "cannot submit syncpipe " | ||
854 | "for urb %d, error %d: %s\n", | ||
855 | i, err, usb_error_string(err)); | ||
824 | goto __error; | 856 | goto __error; |
825 | } | 857 | } |
826 | set_bit(i + 16, &subs->active_mask); | 858 | set_bit(i + 16, &subs->active_mask); |
@@ -1390,8 +1422,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
1390 | channels = params_channels(hw_params); | 1422 | channels = params_channels(hw_params); |
1391 | fmt = find_format(subs, format, rate, channels); | 1423 | fmt = find_format(subs, format, rate, channels); |
1392 | if (! fmt) { | 1424 | if (! fmt) { |
1393 | snd_printd(KERN_DEBUG "cannot set format: format = %s, rate = %d, channels = %d\n", | 1425 | snd_printd(KERN_DEBUG "cannot set format: format = 0x%x, rate = %d, channels = %d\n", |
1394 | snd_pcm_format_name(format), rate, channels); | 1426 | format, rate, channels); |
1395 | return -EINVAL; | 1427 | return -EINVAL; |
1396 | } | 1428 | } |
1397 | 1429 | ||
@@ -2017,6 +2049,8 @@ static struct usb_driver usb_audio_driver = { | |||
2017 | }; | 2049 | }; |
2018 | 2050 | ||
2019 | 2051 | ||
2052 | #if defined(CONFIG_PROCFS) && defined(CONFIG_SND_VERBOSE_PROCFS) | ||
2053 | |||
2020 | /* | 2054 | /* |
2021 | * proc interface for list the supported pcm formats | 2055 | * proc interface for list the supported pcm formats |
2022 | */ | 2056 | */ |
@@ -2032,7 +2066,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s | |||
2032 | fp = list_entry(p, struct audioformat, list); | 2066 | fp = list_entry(p, struct audioformat, list); |
2033 | snd_iprintf(buffer, " Interface %d\n", fp->iface); | 2067 | snd_iprintf(buffer, " Interface %d\n", fp->iface); |
2034 | snd_iprintf(buffer, " Altset %d\n", fp->altsetting); | 2068 | snd_iprintf(buffer, " Altset %d\n", fp->altsetting); |
2035 | snd_iprintf(buffer, " Format: %s\n", snd_pcm_format_name(fp->format)); | 2069 | snd_iprintf(buffer, " Format: 0x%x\n", fp->format); |
2036 | snd_iprintf(buffer, " Channels: %d\n", fp->channels); | 2070 | snd_iprintf(buffer, " Channels: %d\n", fp->channels); |
2037 | snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", | 2071 | snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", |
2038 | fp->endpoint & USB_ENDPOINT_NUMBER_MASK, | 2072 | fp->endpoint & USB_ENDPOINT_NUMBER_MASK, |
@@ -2107,6 +2141,13 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream) | |||
2107 | snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read); | 2141 | snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read); |
2108 | } | 2142 | } |
2109 | 2143 | ||
2144 | #else | ||
2145 | |||
2146 | static inline void proc_pcm_format_add(struct snd_usb_stream *stream) | ||
2147 | { | ||
2148 | } | ||
2149 | |||
2150 | #endif | ||
2110 | 2151 | ||
2111 | /* | 2152 | /* |
2112 | * initialize the substream instance. | 2153 | * initialize the substream instance. |
@@ -2509,6 +2550,8 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp | |||
2509 | return 0; | 2550 | return 0; |
2510 | } | 2551 | } |
2511 | 2552 | ||
2553 | static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, | ||
2554 | int iface, int altno); | ||
2512 | static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | 2555 | static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) |
2513 | { | 2556 | { |
2514 | struct usb_device *dev; | 2557 | struct usb_device *dev; |
@@ -2543,6 +2586,12 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2543 | stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? | 2586 | stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? |
2544 | SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | 2587 | SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; |
2545 | altno = altsd->bAlternateSetting; | 2588 | altno = altsd->bAlternateSetting; |
2589 | |||
2590 | /* audiophile usb: skip altsets incompatible with device_setup | ||
2591 | */ | ||
2592 | if (chip->usb_id == USB_ID(0x0763, 0x2003) && | ||
2593 | audiophile_skip_setting_quirk(chip, iface_no, altno)) | ||
2594 | continue; | ||
2546 | 2595 | ||
2547 | /* get audio formats */ | 2596 | /* get audio formats */ |
2548 | fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, AS_GENERAL); | 2597 | fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, AS_GENERAL); |
@@ -2637,7 +2686,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2637 | continue; | 2686 | continue; |
2638 | } | 2687 | } |
2639 | 2688 | ||
2640 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, i, fp->endpoint); | 2689 | snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint 0x%x\n", dev->devnum, iface_no, altno, fp->endpoint); |
2641 | err = add_audio_endpoint(chip, stream, fp); | 2690 | err = add_audio_endpoint(chip, stream, fp); |
2642 | if (err < 0) { | 2691 | if (err < 0) { |
2643 | kfree(fp->rate_table); | 2692 | kfree(fp->rate_table); |
@@ -3045,6 +3094,45 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) | |||
3045 | return 0; | 3094 | return 0; |
3046 | } | 3095 | } |
3047 | 3096 | ||
3097 | /* | ||
3098 | * Setup quirks | ||
3099 | */ | ||
3100 | #define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */ | ||
3101 | #define AUDIOPHILE_SET_DTS 0x02 /* if set, enable DTS Digital Output */ | ||
3102 | #define AUDIOPHILE_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */ | ||
3103 | #define AUDIOPHILE_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ | ||
3104 | #define AUDIOPHILE_SET_DI 0x10 /* if set, enable Digital Input */ | ||
3105 | #define AUDIOPHILE_SET_MASK 0x1F /* bit mask for setup value */ | ||
3106 | #define AUDIOPHILE_SET_24B_48K_DI 0x19 /* value for 24bits+48KHz+Digital Input */ | ||
3107 | #define AUDIOPHILE_SET_24B_48K_NOTDI 0x09 /* value for 24bits+48KHz+No Digital Input */ | ||
3108 | #define AUDIOPHILE_SET_16B_48K_DI 0x11 /* value for 16bits+48KHz+Digital Input */ | ||
3109 | #define AUDIOPHILE_SET_16B_48K_NOTDI 0x01 /* value for 16bits+48KHz+No Digital Input */ | ||
3110 | |||
3111 | static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, | ||
3112 | int iface, int altno) | ||
3113 | { | ||
3114 | if (device_setup[chip->index] & AUDIOPHILE_SET) { | ||
3115 | if ((device_setup[chip->index] & AUDIOPHILE_SET_DTS) | ||
3116 | && altno != 6) | ||
3117 | return 1; /* skip this altsetting */ | ||
3118 | if ((device_setup[chip->index] & AUDIOPHILE_SET_96K) | ||
3119 | && altno != 1) | ||
3120 | return 1; /* skip this altsetting */ | ||
3121 | if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) == | ||
3122 | AUDIOPHILE_SET_24B_48K_DI && altno != 2) | ||
3123 | return 1; /* skip this altsetting */ | ||
3124 | if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) == | ||
3125 | AUDIOPHILE_SET_24B_48K_NOTDI && altno != 3) | ||
3126 | return 1; /* skip this altsetting */ | ||
3127 | if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) == | ||
3128 | AUDIOPHILE_SET_16B_48K_DI && altno != 4) | ||
3129 | return 1; /* skip this altsetting */ | ||
3130 | if ((device_setup[chip->index] & AUDIOPHILE_SET_MASK) == | ||
3131 | AUDIOPHILE_SET_16B_48K_NOTDI && altno != 5) | ||
3132 | return 1; /* skip this altsetting */ | ||
3133 | } | ||
3134 | return 0; /* keep this altsetting */ | ||
3135 | } | ||
3048 | 3136 | ||
3049 | /* | 3137 | /* |
3050 | * audio-interface quirks | 3138 | * audio-interface quirks |
@@ -3070,7 +3158,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, | |||
3070 | [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, | 3158 | [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, |
3071 | [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, | 3159 | [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, |
3072 | [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, | 3160 | [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, |
3073 | [QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface, | 3161 | [QUIRK_MIDI_CME] = snd_usb_create_midi_interface, |
3074 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, | 3162 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, |
3075 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, | 3163 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
3076 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, | 3164 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, |
@@ -3282,7 +3370,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3282 | 3370 | ||
3283 | /* check whether it's already registered */ | 3371 | /* check whether it's already registered */ |
3284 | chip = NULL; | 3372 | chip = NULL; |
3285 | down(®ister_mutex); | 3373 | mutex_lock(®ister_mutex); |
3286 | for (i = 0; i < SNDRV_CARDS; i++) { | 3374 | for (i = 0; i < SNDRV_CARDS; i++) { |
3287 | if (usb_chip[i] && usb_chip[i]->dev == dev) { | 3375 | if (usb_chip[i] && usb_chip[i]->dev == dev) { |
3288 | if (usb_chip[i]->shutdown) { | 3376 | if (usb_chip[i]->shutdown) { |
@@ -3335,13 +3423,13 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3335 | 3423 | ||
3336 | usb_chip[chip->index] = chip; | 3424 | usb_chip[chip->index] = chip; |
3337 | chip->num_interfaces++; | 3425 | chip->num_interfaces++; |
3338 | up(®ister_mutex); | 3426 | mutex_unlock(®ister_mutex); |
3339 | return chip; | 3427 | return chip; |
3340 | 3428 | ||
3341 | __error: | 3429 | __error: |
3342 | if (chip && !chip->num_interfaces) | 3430 | if (chip && !chip->num_interfaces) |
3343 | snd_card_free(chip->card); | 3431 | snd_card_free(chip->card); |
3344 | up(®ister_mutex); | 3432 | mutex_unlock(®ister_mutex); |
3345 | __err_val: | 3433 | __err_val: |
3346 | return NULL; | 3434 | return NULL; |
3347 | } | 3435 | } |
@@ -3361,7 +3449,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3361 | 3449 | ||
3362 | chip = ptr; | 3450 | chip = ptr; |
3363 | card = chip->card; | 3451 | card = chip->card; |
3364 | down(®ister_mutex); | 3452 | mutex_lock(®ister_mutex); |
3365 | chip->shutdown = 1; | 3453 | chip->shutdown = 1; |
3366 | chip->num_interfaces--; | 3454 | chip->num_interfaces--; |
3367 | if (chip->num_interfaces <= 0) { | 3455 | if (chip->num_interfaces <= 0) { |
@@ -3379,10 +3467,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3379 | snd_usb_mixer_disconnect(p); | 3467 | snd_usb_mixer_disconnect(p); |
3380 | } | 3468 | } |
3381 | usb_chip[chip->index] = NULL; | 3469 | usb_chip[chip->index] = NULL; |
3382 | up(®ister_mutex); | 3470 | mutex_unlock(®ister_mutex); |
3383 | snd_card_free(card); | 3471 | snd_card_free(card); |
3384 | } else { | 3472 | } else { |
3385 | up(®ister_mutex); | 3473 | mutex_unlock(®ister_mutex); |
3386 | } | 3474 | } |
3387 | } | 3475 | } |
3388 | 3476 | ||