diff options
Diffstat (limited to 'sound/usb/card.c')
| -rw-r--r-- | sound/usb/card.c | 306 |
1 files changed, 214 insertions, 92 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 800f7cb4f25..a09e5f3519e 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -25,9 +25,6 @@ * * NOTES: * - * - async unlink should be used for avoiding the sleep inside lock. - * 2.4.22 usb-uhci seems buggy for async unlinking and results in - * oops. in such a cse, pass async_unlink=0 option. * - the linked URBs would be preferred but not used so far because of * the instability of unlinking. * - type II is not supported properly. there is no device which supports @@ -41,12 +38,15 @@ #include <linux/list.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/ctype.h> #include <linux/usb.h> #include <linux/moduleparam.h> #include <linux/mutex.h> #include <linux/usb/audio.h> #include <linux/usb/audio-v2.h> +#include <linux/module.h> +#include <sound/control.h> #include <sound/core.h> #include <sound/info.h> #include <sound/pcm.h> @@ -63,8 +63,9 @@ #include "helper.h" #include "debug.h" #include "pcm.h" -#include "urb.h" #include "format.h" +#include "power.h" +#include "stream.h" MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("USB Audio"); @@ -74,14 +75,13 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ /* Vendor/product IDs for this card */ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; -static int nrpacks = 8; /* max. number of packets per urb */ -static int async_unlink = 1; static int device_setup[SNDRV_CARDS]; /* device parameter for this card */ -static int ignore_ctl_error; +static bool ignore_ctl_error; +static bool autoclock = true; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); @@ -93,15 +93,13 @@ module_param_array(vid, int, NULL, 0444); MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device."); module_param_array(pid, int, NULL, 0444); MODULE_PARM_DESC(pid, "Product ID for the USB audio device."); -module_param(nrpacks, int, 0644); -MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB."); -module_param(async_unlink, bool, 0444); -MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); module_param_array(device_setup, int, NULL, 0444); MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); module_param(ignore_ctl_error, bool, 0444); MODULE_PARM_DESC(ignore_ctl_error, "Ignore errors from USB controller for mixer interfaces."); +module_param(autoclock, bool, 0444); +MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes)."); /* * we keep the snd_usb_audio_t instances by ourselves for merging @@ -127,8 +125,9 @@ static void snd_usb_stream_disconnect(struct list_head *head) subs = &as->substream[idx]; if (!subs->num_formats) continue; - snd_usb_release_substream_urbs(subs, 1); subs->interface = -1; + subs->data_endpoint = NULL; + subs->sync_endpoint = NULL; } } @@ -140,27 +139,46 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int struct usb_interface *iface = usb_ifnum_to_if(dev, interface); if (!iface) { - snd_printk(KERN_ERR "%d:%u:%d : does not exist\n", - dev->devnum, ctrlif, interface); + dev_err(&dev->dev, "%u:%d : does not exist\n", + ctrlif, interface); return -EINVAL; } + alts = &iface->altsetting[0]; + altsd = get_iface_desc(alts); + + /* + * Android with both accessory and audio interfaces enabled gets the + * interface numbers wrong. + */ + if ((chip->usb_id == USB_ID(0x18d1, 0x2d04) || + chip->usb_id == USB_ID(0x18d1, 0x2d05)) && + interface == 0 && + altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && + altsd->bInterfaceSubClass == USB_SUBCLASS_VENDOR_SPEC) { + interface = 2; + iface = usb_ifnum_to_if(dev, interface); + if (!iface) + return -EINVAL; + alts = &iface->altsetting[0]; + altsd = get_iface_desc(alts); + } + if (usb_interface_claimed(iface)) { - snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", - dev->devnum, ctrlif, interface); + dev_dbg(&dev->dev, "%d:%d: skipping, already claimed\n", + ctrlif, interface); return -EINVAL; } - alts = &iface->altsetting[0]; - altsd = get_iface_desc(alts); if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) { int err = snd_usbmidi_create(chip->card, iface, &chip->midi_list, NULL); if (err < 0) { - snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", - dev->devnum, ctrlif, interface); + dev_err(&dev->dev, + "%u:%d: cannot create sequencer device\n", + ctrlif, interface); return -EINVAL; } usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); @@ -171,18 +189,19 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING) { - snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", - dev->devnum, ctrlif, interface, altsd->bInterfaceClass); + dev_dbg(&dev->dev, + "%u:%d: skipping non-supported interface %d\n", + ctrlif, interface, altsd->bInterfaceClass); /* skip non-supported classes */ return -EINVAL; } if (snd_usb_get_speed(dev) == USB_SPEED_LOW) { - snd_printk(KERN_ERR "low speed audio streaming not supported\n"); + dev_err(&dev->dev, "low speed audio streaming not supported\n"); return -EINVAL; } - if (! snd_usb_parse_audio_endpoints(chip, interface)) { + if (! snd_usb_parse_audio_interface(chip, interface)) { usb_set_interface(dev, interface, 0); /* reset the current interface */ usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); return -EINVAL; @@ -211,26 +230,27 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) protocol = altsd->bInterfaceProtocol; if (!control_header) { - snd_printk(KERN_ERR "cannot find UAC_HEADER\n"); + dev_err(&dev->dev, "cannot find UAC_HEADER\n"); return -EINVAL; } switch (protocol) { default: - snd_printdd(KERN_WARNING "unknown interface protocol %#02x, assuming v1\n", - protocol); + dev_warn(&dev->dev, + "unknown interface protocol %#02x, assuming v1\n", + protocol); /* fall through */ case UAC_VERSION_1: { struct uac1_ac_header_descriptor *h1 = control_header; if (!h1->bInCollection) { - snd_printk(KERN_INFO "skipping empty audio interface (v1)\n"); + dev_info(&dev->dev, "skipping empty audio interface (v1)\n"); return -EINVAL; } if (h1->bLength < sizeof(*h1) + h1->bInCollection) { - snd_printk(KERN_ERR "invalid UAC_HEADER (v1)\n"); + dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n"); return -EINVAL; } @@ -245,7 +265,22 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) usb_ifnum_to_if(dev, ctrlif)->intf_assoc; if (!assoc) { - snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n"); + /* + * Firmware writers cannot count to three. So to find + * the IAD on the NuForce UDH-100, also check the next + * interface. + */ + struct usb_interface *iface = + usb_ifnum_to_if(dev, ctrlif + 1); + if (iface && + iface->intf_assoc && + iface->intf_assoc->bFunctionClass == USB_CLASS_AUDIO && + iface->intf_assoc->bFunctionProtocol == UAC_VERSION_2) + assoc = iface->intf_assoc; + } + + if (!assoc) { + dev_err(&dev->dev, "Audio class v2 interfaces need an interface association\n"); return -EINVAL; } @@ -272,6 +307,12 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) static int snd_usb_audio_free(struct snd_usb_audio *chip) { + struct list_head *p, *n; + + list_for_each_safe(p, n, &chip->ep_list) + snd_usb_endpoint_free(p); + + mutex_destroy(&chip->mutex); kfree(chip); return 0; } @@ -282,11 +323,21 @@ static int snd_usb_audio_dev_free(struct snd_device *device) return snd_usb_audio_free(chip); } +static void remove_trailing_spaces(char *str) +{ + char *p; + + if (!*str) + return; + for (p = str + strlen(str) - 1; p >= str && isspace(*p); p--) + *p = 0; +} /* * create a chip instance and set its names. */ -static int snd_usb_audio_create(struct usb_device *dev, int idx, +static int snd_usb_audio_create(struct usb_interface *intf, + struct usb_device *dev, int idx, const struct snd_usb_audio_quirk *quirk, struct snd_usb_audio **rchip) { @@ -304,16 +355,18 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, case USB_SPEED_LOW: case USB_SPEED_FULL: case USB_SPEED_HIGH: + case USB_SPEED_WIRELESS: case USB_SPEED_SUPER: break; default: - snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); + dev_err(&dev->dev, "unknown device speed %d\n", snd_usb_get_speed(dev)); return -ENXIO; } - err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card); + err = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE, + 0, &card); if (err < 0) { - snd_printk(KERN_ERR "cannot create card instance %d\n", idx); + dev_err(&dev->dev, "cannot create card instance %d\n", idx); return err; } @@ -323,16 +376,19 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, return -ENOMEM; } + mutex_init(&chip->mutex); + init_rwsem(&chip->shutdown_rwsem); chip->index = idx; chip->dev = dev; chip->card = card; chip->setup = device_setup[idx]; - chip->nrpacks = nrpacks; - chip->async_unlink = async_unlink; + chip->autoclock = autoclock; + chip->probing = 1; chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); INIT_LIST_HEAD(&chip->pcm_list); + INIT_LIST_HEAD(&chip->ep_list); INIT_LIST_HEAD(&chip->midi_list); INIT_LIST_HEAD(&chip->mixer_list); @@ -348,7 +404,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, snd_component_add(card, component); /* retrieve the device string as shortname */ - if (quirk && quirk->product_name) { + if (quirk && quirk->product_name && *quirk->product_name) { strlcpy(card->shortname, quirk->product_name, sizeof(card->shortname)); } else { if (!dev->descriptor.iProduct || @@ -360,9 +416,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, USB_ID_PRODUCT(chip->usb_id)); } } + remove_trailing_spaces(card->shortname); /* retrieve the vendor and device strings as longname */ - if (quirk && quirk->vendor_name) { + if (quirk && quirk->vendor_name && *quirk->vendor_name) { len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname)); } else { if (dev->descriptor.iManufacturer) @@ -372,8 +429,11 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, len = 0; /* we don't really care if there isn't any vendor string */ } - if (len > 0) - strlcat(card->longname, " ", sizeof(card->longname)); + if (len > 0) { + remove_trailing_spaces(card->longname); + if (*card->longname) + strlcat(card->longname, " ", sizeof(card->longname)); + } strlcat(card->longname, card->shortname, sizeof(card->longname)); @@ -415,9 +475,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, * only at the first time. the successive calls of this function will * append the pcm interface to the corresponding card. */ -static void *snd_usb_audio_probe(struct usb_device *dev, - struct usb_interface *intf, - const struct usb_device_id *usb_id) +static struct snd_usb_audio * +snd_usb_audio_probe(struct usb_device *dev, + struct usb_interface *intf, + const struct usb_device_id *usb_id) { const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info; int i, err; @@ -446,10 +507,11 @@ static void *snd_usb_audio_probe(struct usb_device *dev, for (i = 0; i < SNDRV_CARDS; i++) { if (usb_chip[i] && usb_chip[i]->dev == dev) { if (usb_chip[i]->shutdown) { - snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n"); + dev_err(&dev->dev, "USB device is in the shutdown state, cannot create a card instance\n"); goto __error; } chip = usb_chip[i]; + chip->probing = 1; break; } } @@ -461,26 +523,19 @@ static void *snd_usb_audio_probe(struct usb_device *dev, if (enable[i] && ! usb_chip[i] && (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { - if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { + if (snd_usb_audio_create(intf, dev, i, quirk, + &chip) < 0) { goto __error; } - snd_card_set_dev(chip->card, &intf->dev); + chip->pm_intf = intf; break; } if (!chip) { - printk(KERN_ERR "no available usb audio device\n"); + dev_err(&dev->dev, "no available usb audio device\n"); goto __error; } } - chip->txfr_quirk = 0; - err = 1; /* continue */ - if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { - /* need some special handlings */ - if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) - goto __error; - } - /* * For devices with more than one control interface, we assume the * first contains the audio controls. We might need a more specific @@ -489,6 +544,14 @@ static void *snd_usb_audio_probe(struct usb_device *dev, if (!chip->ctrl_intf) chip->ctrl_intf = alts; + chip->txfr_quirk = 0; + err = 1; /* continue */ + if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { + /* need some special handlings */ + if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) + goto __error; + } + if (err > 0) { /* create normal USB audio interfaces */ if (snd_usb_create_streams(chip, ifnum) < 0 || @@ -504,12 +567,16 @@ static void *snd_usb_audio_probe(struct usb_device *dev, usb_chip[chip->index] = chip; chip->num_interfaces++; + chip->probing = 0; mutex_unlock(®ister_mutex); return chip; __error: - if (chip && !chip->num_interfaces) - snd_card_free(chip->card); + if (chip) { + if (!chip->num_interfaces) + snd_card_free(chip->card); + chip->probing = 0; + } mutex_unlock(®ister_mutex); __err_val: return NULL; @@ -519,26 +586,34 @@ static void *snd_usb_audio_probe(struct usb_device *dev, * we need to take care of counter, since disconnection can be called also * many times as well as usb_audio_probe(). */ -static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) +static void snd_usb_audio_disconnect(struct usb_device *dev, + struct snd_usb_audio *chip) { - struct snd_usb_audio *chip; struct snd_card *card; struct list_head *p; - if (ptr == (void *)-1L) + if (chip == (void *)-1L) return; - chip = ptr; card = chip->card; - mutex_lock(®ister_mutex); + down_write(&chip->shutdown_rwsem); chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); chip->num_interfaces--; if (chip->num_interfaces <= 0) { + struct snd_usb_endpoint *ep; + snd_card_disconnect(card); /* release the pcm resources */ list_for_each(p, &chip->pcm_list) { snd_usb_stream_disconnect(p); } + /* release the endpoint resources */ + list_for_each_entry(ep, &chip->ep_list, list) { + snd_usb_endpoint_release(ep); + } /* release the midi resources */ list_for_each(p, &chip->midi_list) { snd_usbmidi_disconnect(p); @@ -561,7 +636,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) static int usb_audio_probe(struct usb_interface *intf, const struct usb_device_id *id) { - void *chip; + struct snd_usb_audio *chip; chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id); if (chip) { usb_set_intfdata(intf, chip); @@ -577,46 +652,107 @@ static void usb_audio_disconnect(struct usb_interface *intf) } #ifdef CONFIG_PM + +int snd_usb_autoresume(struct snd_usb_audio *chip) +{ + int err = -ENODEV; + + down_read(&chip->shutdown_rwsem); + if (chip->probing && chip->in_pm) + err = 0; + else if (!chip->shutdown) + err = usb_autopm_get_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); + + return err; +} + +void snd_usb_autosuspend(struct snd_usb_audio *chip) +{ + down_read(&chip->shutdown_rwsem); + if (!chip->shutdown && !chip->probing && !chip->in_pm) + usb_autopm_put_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); +} + static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) { struct snd_usb_audio *chip = usb_get_intfdata(intf); - struct list_head *p; struct snd_usb_stream *as; + struct usb_mixer_interface *mixer; if (chip == (void *)-1L) return 0; - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - if (!chip->num_suspended_intf++) { - list_for_each(p, &chip->pcm_list) { - as = list_entry(p, struct snd_usb_stream, list); - snd_pcm_suspend_all(as->pcm); + if (!PMSG_IS_AUTO(message)) { + snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); + if (!chip->num_suspended_intf++) { + list_for_each_entry(as, &chip->pcm_list, list) { + snd_pcm_suspend_all(as->pcm); + as->substream[0].need_setup_ep = + as->substream[1].need_setup_ep = true; + } } + } else { + /* + * otherwise we keep the rest of the system in the dark + * to keep this transparent + */ + if (!chip->num_suspended_intf++) + chip->autosuspended = 1; } + if (chip->num_suspended_intf == 1) + list_for_each_entry(mixer, &chip->mixer_list, list) + snd_usb_mixer_suspend(mixer); + return 0; } -static int usb_audio_resume(struct usb_interface *intf) +static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) { struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct usb_mixer_interface *mixer; + int err = 0; if (chip == (void *)-1L) return 0; if (--chip->num_suspended_intf) return 0; + + chip->in_pm = 1; /* * ALSA leaves material resumption to user space - * we just notify + * we just notify and restart the mixers */ + list_for_each_entry(mixer, &chip->mixer_list, list) { + err = snd_usb_mixer_resume(mixer, reset_resume); + if (err < 0) + goto err_out; + } - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); + if (!chip->autosuspended) + snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); + chip->autosuspended = 0; - return 0; +err_out: + chip->in_pm = 0; + return err; +} + +static int usb_audio_resume(struct usb_interface *intf) +{ + return __usb_audio_resume(intf, false); +} + +static int usb_audio_reset_resume(struct usb_interface *intf) +{ + return __usb_audio_resume(intf, true); } #else #define usb_audio_suspend NULL #define usb_audio_resume NULL +#define usb_audio_reset_resume NULL #endif /* CONFIG_PM */ static struct usb_device_id usb_audio_ids [] = { @@ -626,8 +762,7 @@ static struct usb_device_id usb_audio_ids [] = { .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL }, { } /* Terminating entry */ }; - -MODULE_DEVICE_TABLE (usb, usb_audio_ids); +MODULE_DEVICE_TABLE(usb, usb_audio_ids); /* * entry point for linux usb interface @@ -639,22 +774,9 @@ static struct usb_driver usb_audio_driver = { .disconnect = usb_audio_disconnect, .suspend = usb_audio_suspend, .resume = usb_audio_resume, + .reset_resume = usb_audio_reset_resume, .id_table = usb_audio_ids, + .supports_autosuspend = 1, }; -static int __init snd_usb_audio_init(void) -{ - if (nrpacks < 1 || nrpacks > MAX_PACKS) { - printk(KERN_WARNING "invalid nrpacks value.\n"); - return -EINVAL; - } - return usb_register(&usb_audio_driver); -} - -static void __exit snd_usb_audio_cleanup(void) -{ - usb_deregister(&usb_audio_driver); -} - -module_init(snd_usb_audio_init); -module_exit(snd_usb_audio_cleanup); +module_usb_driver(usb_audio_driver); |
