diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/caiaq/device.c | 2 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 73 | ||||
-rw-r--r-- | sound/usb/mixer_maps.c | 8 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 159 | ||||
-rw-r--r-- | sound/usb/pcm.c | 61 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 30 |
6 files changed, 185 insertions, 148 deletions
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 64aed432ae2..7da0d0aa72c 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -485,7 +485,7 @@ static int __devinit snd_probe(struct usb_interface *intf, | |||
485 | const struct usb_device_id *id) | 485 | const struct usb_device_id *id) |
486 | { | 486 | { |
487 | int ret; | 487 | int ret; |
488 | struct snd_card *card; | 488 | struct snd_card *card = NULL; |
489 | struct usb_device *device = interface_to_usbdev(intf); | 489 | struct usb_device *device = interface_to_usbdev(intf); |
490 | 490 | ||
491 | ret = create_card(device, intf, &card); | 491 | ret = create_card(device, intf, &card); |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e6906901deb..0f647d22cb4 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
@@ -414,7 +414,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
414 | { | 414 | { |
415 | struct list_head *p; | 415 | struct list_head *p; |
416 | struct snd_usb_endpoint *ep; | 416 | struct snd_usb_endpoint *ep; |
417 | int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; | 417 | int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; |
418 | 418 | ||
419 | mutex_lock(&chip->mutex); | 419 | mutex_lock(&chip->mutex); |
420 | 420 | ||
@@ -434,16 +434,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
434 | type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", | 434 | type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", |
435 | ep_num); | 435 | ep_num); |
436 | 436 | ||
437 | /* select the alt setting once so the endpoints become valid */ | ||
438 | ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber, | ||
439 | alts->desc.bAlternateSetting); | ||
440 | if (ret < 0) { | ||
441 | snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", | ||
442 | __func__, ret); | ||
443 | ep = NULL; | ||
444 | goto __exit_unlock; | ||
445 | } | ||
446 | |||
447 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 437 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
448 | if (!ep) | 438 | if (!ep) |
449 | goto __exit_unlock; | 439 | goto __exit_unlock; |
@@ -831,9 +821,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) | |||
831 | if (++ep->use_count != 1) | 821 | if (++ep->use_count != 1) |
832 | return 0; | 822 | return 0; |
833 | 823 | ||
834 | if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) | ||
835 | return -EINVAL; | ||
836 | |||
837 | /* just to be sure */ | 824 | /* just to be sure */ |
838 | deactivate_urbs(ep, 0, 1); | 825 | deactivate_urbs(ep, 0, 1); |
839 | wait_clear_urbs(ep); | 826 | wait_clear_urbs(ep); |
@@ -911,9 +898,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
911 | if (snd_BUG_ON(ep->use_count == 0)) | 898 | if (snd_BUG_ON(ep->use_count == 0)) |
912 | return; | 899 | return; |
913 | 900 | ||
914 | if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) | ||
915 | return; | ||
916 | |||
917 | if (--ep->use_count == 0) { | 901 | if (--ep->use_count == 0) { |
918 | deactivate_urbs(ep, force, can_sleep); | 902 | deactivate_urbs(ep, force, can_sleep); |
919 | ep->data_subs = NULL; | 903 | ep->data_subs = NULL; |
@@ -927,42 +911,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
927 | } | 911 | } |
928 | 912 | ||
929 | /** | 913 | /** |
930 | * snd_usb_endpoint_activate: activate an snd_usb_endpoint | ||
931 | * | ||
932 | * @ep: the endpoint to activate | ||
933 | * | ||
934 | * If the endpoint is not currently in use, this functions will select the | ||
935 | * correct alternate interface setting for the interface of this endpoint. | ||
936 | * | ||
937 | * In case of any active users, this functions does nothing. | ||
938 | * | ||
939 | * Returns an error if usb_set_interface() failed, 0 in all other | ||
940 | * cases. | ||
941 | */ | ||
942 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep) | ||
943 | { | ||
944 | if (ep->use_count != 0) | ||
945 | return 0; | ||
946 | |||
947 | if (!ep->chip->shutdown && | ||
948 | !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) { | ||
949 | int ret; | ||
950 | |||
951 | ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx); | ||
952 | if (ret < 0) { | ||
953 | snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n", | ||
954 | __func__, ret); | ||
955 | clear_bit(EP_FLAG_ACTIVATED, &ep->flags); | ||
956 | return ret; | ||
957 | } | ||
958 | |||
959 | return 0; | ||
960 | } | ||
961 | |||
962 | return -EBUSY; | ||
963 | } | ||
964 | |||
965 | /** | ||
966 | * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint | 914 | * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint |
967 | * | 915 | * |
968 | * @ep: the endpoint to deactivate | 916 | * @ep: the endpoint to deactivate |
@@ -980,24 +928,15 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) | |||
980 | if (!ep) | 928 | if (!ep) |
981 | return -EINVAL; | 929 | return -EINVAL; |
982 | 930 | ||
931 | deactivate_urbs(ep, 1, 1); | ||
932 | wait_clear_urbs(ep); | ||
933 | |||
983 | if (ep->use_count != 0) | 934 | if (ep->use_count != 0) |
984 | return 0; | 935 | return 0; |
985 | 936 | ||
986 | if (!ep->chip->shutdown && | 937 | clear_bit(EP_FLAG_ACTIVATED, &ep->flags); |
987 | test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) { | ||
988 | int ret; | ||
989 | |||
990 | ret = usb_set_interface(ep->chip->dev, ep->iface, 0); | ||
991 | if (ret < 0) { | ||
992 | snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", | ||
993 | __func__, ret); | ||
994 | return ret; | ||
995 | } | ||
996 | 938 | ||
997 | return 0; | 939 | return 0; |
998 | } | ||
999 | |||
1000 | return -EBUSY; | ||
1001 | } | 940 | } |
1002 | 941 | ||
1003 | /** | 942 | /** |
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index 41daaa24c25..e71fe55cebe 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c | |||
@@ -341,6 +341,14 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { | |||
341 | .map = audigy2nx_map, | 341 | .map = audigy2nx_map, |
342 | .selector_map = audigy2nx_selectors, | 342 | .selector_map = audigy2nx_selectors, |
343 | }, | 343 | }, |
344 | { /* Logitech, Inc. QuickCam Pro for Notebooks */ | ||
345 | .id = USB_ID(0x046d, 0x0991), | ||
346 | .ignore_ctl_error = 1, | ||
347 | }, | ||
348 | { /* Logitech, Inc. QuickCam E 3500 */ | ||
349 | .id = USB_ID(0x046d, 0x09a4), | ||
350 | .ignore_ctl_error = 1, | ||
351 | }, | ||
344 | { | 352 | { |
345 | /* Hercules DJ Console (Windows Edition) */ | 353 | /* Hercules DJ Console (Windows Edition) */ |
346 | .id = USB_ID(0x06f8, 0xb000), | 354 | .id = USB_ID(0x06f8, 0xb000), |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b691192..690000db0ec 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -42,6 +42,13 @@ | |||
42 | 42 | ||
43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; | 43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; |
44 | 44 | ||
45 | struct std_mono_table { | ||
46 | unsigned int unitid, control, cmask; | ||
47 | int val_type; | ||
48 | const char *name; | ||
49 | snd_kcontrol_tlv_rw_t *tlv_callback; | ||
50 | }; | ||
51 | |||
45 | /* private_free callback */ | 52 | /* private_free callback */ |
46 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | 53 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) |
47 | { | 54 | { |
@@ -114,6 +121,25 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, | |||
114 | } | 121 | } |
115 | 122 | ||
116 | /* | 123 | /* |
124 | * Create a set of standard UAC controls from a table | ||
125 | */ | ||
126 | static int snd_create_std_mono_table(struct usb_mixer_interface *mixer, | ||
127 | struct std_mono_table *t) | ||
128 | { | ||
129 | int err; | ||
130 | |||
131 | while (t->name != NULL) { | ||
132 | err = snd_create_std_mono_ctl(mixer, t->unitid, t->control, | ||
133 | t->cmask, t->val_type, t->name, t->tlv_callback); | ||
134 | if (err < 0) | ||
135 | return err; | ||
136 | t++; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /* | ||
117 | * Sound Blaster remote control configuration | 143 | * Sound Blaster remote control configuration |
118 | * | 144 | * |
119 | * format of remote control data: | 145 | * format of remote control data: |
@@ -916,61 +942,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) | |||
916 | return 0; | 942 | return 0; |
917 | } | 943 | } |
918 | 944 | ||
919 | |||
920 | /* | ||
921 | * Create mixer for Electrix Ebox-44 | ||
922 | * | ||
923 | * The mixer units from this device are corrupt, and even where they | ||
924 | * are valid they presents mono controls as L and R channels of | ||
925 | * stereo. So we create a good mixer in code. | ||
926 | */ | ||
927 | |||
928 | static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) | ||
929 | { | ||
930 | int err; | ||
931 | |||
932 | err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
933 | "Headphone Playback Switch", NULL); | ||
934 | if (err < 0) | ||
935 | return err; | ||
936 | err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, | ||
937 | "Headphone A Mix Playback Volume", NULL); | ||
938 | if (err < 0) | ||
939 | return err; | ||
940 | err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, | ||
941 | "Headphone B Mix Playback Volume", NULL); | ||
942 | if (err < 0) | ||
943 | return err; | ||
944 | |||
945 | err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
946 | "Output Playback Switch", NULL); | ||
947 | if (err < 0) | ||
948 | return err; | ||
949 | err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, | ||
950 | "Output A Playback Volume", NULL); | ||
951 | if (err < 0) | ||
952 | return err; | ||
953 | err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, | ||
954 | "Output B Playback Volume", NULL); | ||
955 | if (err < 0) | ||
956 | return err; | ||
957 | |||
958 | err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
959 | "Input Capture Switch", NULL); | ||
960 | if (err < 0) | ||
961 | return err; | ||
962 | err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, | ||
963 | "Input A Capture Volume", NULL); | ||
964 | if (err < 0) | ||
965 | return err; | ||
966 | err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, | ||
967 | "Input B Capture Volume", NULL); | ||
968 | if (err < 0) | ||
969 | return err; | ||
970 | |||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | 945 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, |
975 | unsigned char samplerate_id) | 946 | unsigned char samplerate_id) |
976 | { | 947 | { |
@@ -990,6 +961,81 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | |||
990 | } | 961 | } |
991 | } | 962 | } |
992 | 963 | ||
964 | /* | ||
965 | * The mixer units for Ebox-44 are corrupt, and even where they | ||
966 | * are valid they presents mono controls as L and R channels of | ||
967 | * stereo. So we provide a good mixer here. | ||
968 | */ | ||
969 | struct std_mono_table ebox44_table[] = { | ||
970 | { | ||
971 | .unitid = 4, | ||
972 | .control = 1, | ||
973 | .cmask = 0x0, | ||
974 | .val_type = USB_MIXER_INV_BOOLEAN, | ||
975 | .name = "Headphone Playback Switch" | ||
976 | }, | ||
977 | { | ||
978 | .unitid = 4, | ||
979 | .control = 2, | ||
980 | .cmask = 0x1, | ||
981 | .val_type = USB_MIXER_S16, | ||
982 | .name = "Headphone A Mix Playback Volume" | ||
983 | }, | ||
984 | { | ||
985 | .unitid = 4, | ||
986 | .control = 2, | ||
987 | .cmask = 0x2, | ||
988 | .val_type = USB_MIXER_S16, | ||
989 | .name = "Headphone B Mix Playback Volume" | ||
990 | }, | ||
991 | |||
992 | { | ||
993 | .unitid = 7, | ||
994 | .control = 1, | ||
995 | .cmask = 0x0, | ||
996 | .val_type = USB_MIXER_INV_BOOLEAN, | ||
997 | .name = "Output Playback Switch" | ||
998 | }, | ||
999 | { | ||
1000 | .unitid = 7, | ||
1001 | .control = 2, | ||
1002 | .cmask = 0x1, | ||
1003 | .val_type = USB_MIXER_S16, | ||
1004 | .name = "Output A Playback Volume" | ||
1005 | }, | ||
1006 | { | ||
1007 | .unitid = 7, | ||
1008 | .control = 2, | ||
1009 | .cmask = 0x2, | ||
1010 | .val_type = USB_MIXER_S16, | ||
1011 | .name = "Output B Playback Volume" | ||
1012 | }, | ||
1013 | |||
1014 | { | ||
1015 | .unitid = 10, | ||
1016 | .control = 1, | ||
1017 | .cmask = 0x0, | ||
1018 | .val_type = USB_MIXER_INV_BOOLEAN, | ||
1019 | .name = "Input Capture Switch" | ||
1020 | }, | ||
1021 | { | ||
1022 | .unitid = 10, | ||
1023 | .control = 2, | ||
1024 | .cmask = 0x1, | ||
1025 | .val_type = USB_MIXER_S16, | ||
1026 | .name = "Input A Capture Volume" | ||
1027 | }, | ||
1028 | { | ||
1029 | .unitid = 10, | ||
1030 | .control = 2, | ||
1031 | .cmask = 0x2, | ||
1032 | .val_type = USB_MIXER_S16, | ||
1033 | .name = "Input B Capture Volume" | ||
1034 | }, | ||
1035 | |||
1036 | {} | ||
1037 | }; | ||
1038 | |||
993 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 1039 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
994 | { | 1040 | { |
995 | int err = 0; | 1041 | int err = 0; |
@@ -1035,7 +1081,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
1035 | break; | 1081 | break; |
1036 | 1082 | ||
1037 | case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ | 1083 | case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ |
1038 | err = snd_ebox44_create_mixer(mixer); | 1084 | /* detection is disabled in mixer_maps.c */ |
1085 | err = snd_create_std_mono_table(mixer, ebox44_table); | ||
1039 | break; | 1086 | break; |
1040 | } | 1087 | } |
1041 | 1088 | ||
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 54607f8c4f6..a1298f37942 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -261,19 +261,6 @@ static void stop_endpoints(struct snd_usb_substream *subs, | |||
261 | force, can_sleep, wait); | 261 | force, can_sleep, wait); |
262 | } | 262 | } |
263 | 263 | ||
264 | static int activate_endpoints(struct snd_usb_substream *subs) | ||
265 | { | ||
266 | if (subs->sync_endpoint) { | ||
267 | int ret; | ||
268 | |||
269 | ret = snd_usb_endpoint_activate(subs->sync_endpoint); | ||
270 | if (ret < 0) | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | return snd_usb_endpoint_activate(subs->data_endpoint); | ||
275 | } | ||
276 | |||
277 | static int deactivate_endpoints(struct snd_usb_substream *subs) | 264 | static int deactivate_endpoints(struct snd_usb_substream *subs) |
278 | { | 265 | { |
279 | int reta, retb; | 266 | int reta, retb; |
@@ -314,6 +301,33 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
314 | if (fmt == subs->cur_audiofmt) | 301 | if (fmt == subs->cur_audiofmt) |
315 | return 0; | 302 | return 0; |
316 | 303 | ||
304 | /* close the old interface */ | ||
305 | if (subs->interface >= 0 && subs->interface != fmt->iface) { | ||
306 | err = usb_set_interface(subs->dev, subs->interface, 0); | ||
307 | if (err < 0) { | ||
308 | snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n", | ||
309 | dev->devnum, fmt->iface, fmt->altsetting, err); | ||
310 | return -EIO; | ||
311 | } | ||
312 | subs->interface = -1; | ||
313 | subs->altset_idx = 0; | ||
314 | } | ||
315 | |||
316 | /* set interface */ | ||
317 | if (subs->interface != fmt->iface || | ||
318 | subs->altset_idx != fmt->altset_idx) { | ||
319 | err = usb_set_interface(dev, fmt->iface, fmt->altsetting); | ||
320 | if (err < 0) { | ||
321 | snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n", | ||
322 | dev->devnum, fmt->iface, fmt->altsetting, err); | ||
323 | return -EIO; | ||
324 | } | ||
325 | snd_printdd(KERN_INFO "setting usb interface %d:%d\n", | ||
326 | fmt->iface, fmt->altsetting); | ||
327 | subs->interface = fmt->iface; | ||
328 | subs->altset_idx = fmt->altset_idx; | ||
329 | } | ||
330 | |||
317 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, | 331 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, |
318 | alts, fmt->endpoint, subs->direction, | 332 | alts, fmt->endpoint, subs->direction, |
319 | SND_USB_ENDPOINT_TYPE_DATA); | 333 | SND_USB_ENDPOINT_TYPE_DATA); |
@@ -387,7 +401,7 @@ add_sync_ep: | |||
387 | subs->data_endpoint->sync_master = subs->sync_endpoint; | 401 | subs->data_endpoint->sync_master = subs->sync_endpoint; |
388 | } | 402 | } |
389 | 403 | ||
390 | if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) | 404 | if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0) |
391 | return err; | 405 | return err; |
392 | 406 | ||
393 | subs->cur_audiofmt = fmt; | 407 | subs->cur_audiofmt = fmt; |
@@ -450,7 +464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
450 | struct usb_interface *iface; | 464 | struct usb_interface *iface; |
451 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); | 465 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); |
452 | alts = &iface->altsetting[fmt->altset_idx]; | 466 | alts = &iface->altsetting[fmt->altset_idx]; |
453 | ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); | 467 | ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); |
454 | if (ret < 0) | 468 | if (ret < 0) |
455 | return ret; | 469 | return ret; |
456 | subs->cur_rate = rate; | 470 | subs->cur_rate = rate; |
@@ -460,12 +474,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
460 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 474 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
461 | /* format changed */ | 475 | /* format changed */ |
462 | stop_endpoints(subs, 0, 0, 0); | 476 | stop_endpoints(subs, 0, 0, 0); |
463 | deactivate_endpoints(subs); | ||
464 | |||
465 | ret = activate_endpoints(subs); | ||
466 | if (ret < 0) | ||
467 | goto unlock; | ||
468 | |||
469 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, | 477 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, |
470 | subs->sync_endpoint); | 478 | subs->sync_endpoint); |
471 | if (ret < 0) | 479 | if (ret < 0) |
@@ -500,6 +508,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
500 | subs->period_bytes = 0; | 508 | subs->period_bytes = 0; |
501 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 509 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
502 | stop_endpoints(subs, 0, 1, 1); | 510 | stop_endpoints(subs, 0, 1, 1); |
511 | deactivate_endpoints(subs); | ||
503 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | 512 | mutex_unlock(&subs->stream->chip->shutdown_mutex); |
504 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 513 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
505 | } | 514 | } |
@@ -938,16 +947,20 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | |||
938 | 947 | ||
939 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | 948 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) |
940 | { | 949 | { |
941 | int ret; | ||
942 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 950 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
943 | struct snd_usb_substream *subs = &as->substream[direction]; | 951 | struct snd_usb_substream *subs = &as->substream[direction]; |
944 | 952 | ||
945 | stop_endpoints(subs, 0, 0, 0); | 953 | stop_endpoints(subs, 0, 0, 0); |
946 | ret = deactivate_endpoints(subs); | 954 | |
955 | if (!as->chip->shutdown && subs->interface >= 0) { | ||
956 | usb_set_interface(subs->dev, subs->interface, 0); | ||
957 | subs->interface = -1; | ||
958 | } | ||
959 | |||
947 | subs->pcm_substream = NULL; | 960 | subs->pcm_substream = NULL; |
948 | snd_usb_autosuspend(subs->stream->chip); | 961 | snd_usb_autosuspend(subs->stream->chip); |
949 | 962 | ||
950 | return ret; | 963 | return 0; |
951 | } | 964 | } |
952 | 965 | ||
953 | /* Since a URB can handle only a single linear buffer, we must use double | 966 | /* Since a URB can handle only a single linear buffer, we must use double |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d89ab4c7d44..79780fa57a4 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -1831,6 +1831,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1831 | } | 1831 | } |
1832 | } | 1832 | } |
1833 | }, | 1833 | }, |
1834 | { | ||
1835 | USB_DEVICE(0x0582, 0x014d), | ||
1836 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1837 | /* .vendor_name = "BOSS", */ | ||
1838 | /* .product_name = "GT-100", */ | ||
1839 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1840 | .type = QUIRK_COMPOSITE, | ||
1841 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1842 | { | ||
1843 | .ifnum = 1, | ||
1844 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1845 | }, | ||
1846 | { | ||
1847 | .ifnum = 2, | ||
1848 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1849 | }, | ||
1850 | { | ||
1851 | .ifnum = 3, | ||
1852 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1853 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1854 | .out_cables = 0x0001, | ||
1855 | .in_cables = 0x0001 | ||
1856 | } | ||
1857 | }, | ||
1858 | { | ||
1859 | .ifnum = -1 | ||
1860 | } | ||
1861 | } | ||
1862 | } | ||
1863 | }, | ||
1834 | 1864 | ||
1835 | /* Guillemot devices */ | 1865 | /* Guillemot devices */ |
1836 | { | 1866 | { |