diff options
Diffstat (limited to 'sound/usb/card.c')
| -rw-r--r-- | sound/usb/card.c | 114 |
1 files changed, 62 insertions, 52 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 64952e2d3ed..a09e5f3519e 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -79,7 +79,6 @@ 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 device_setup[SNDRV_CARDS]; /* device parameter for this card */ static bool ignore_ctl_error; static bool autoclock = true; @@ -94,8 +93,6 @@ 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_array(device_setup, int, NULL, 0444); MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); module_param(ignore_ctl_error, bool, 0444); @@ -142,8 +139,8 @@ 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; } @@ -168,8 +165,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int } 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; } @@ -179,8 +176,9 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int 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); @@ -191,14 +189,15 @@ 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; } @@ -231,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; } @@ -280,7 +280,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) } if (!assoc) { - snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n"); + dev_err(&dev->dev, "Audio class v2 interfaces need an interface association\n"); return -EINVAL; } @@ -307,6 +307,11 @@ 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; @@ -331,7 +336,8 @@ static void remove_trailing_spaces(char *str) /* * 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) { @@ -349,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; } @@ -374,7 +382,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, chip->dev = dev; chip->card = card; chip->setup = device_setup[idx]; - chip->nrpacks = nrpacks; chip->autoclock = autoclock; chip->probing = 1; @@ -500,7 +507,7 @@ 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]; @@ -516,15 +523,15 @@ 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; } } @@ -583,7 +590,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, struct snd_usb_audio *chip) { struct snd_card *card; - struct list_head *p, *n; + struct list_head *p; if (chip == (void *)-1L) return; @@ -596,14 +603,16 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, 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_safe(p, n, &chip->ep_list) { - snd_usb_endpoint_free(p); + 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) { @@ -649,7 +658,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) int err = -ENODEV; down_read(&chip->shutdown_rwsem); - if (chip->probing) + if (chip->probing && chip->in_pm) err = 0; else if (!chip->shutdown) err = usb_autopm_get_interface(chip->pm_intf); @@ -661,7 +670,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) void snd_usb_autosuspend(struct snd_usb_audio *chip) { down_read(&chip->shutdown_rwsem); - if (!chip->shutdown && !chip->probing) + if (!chip->shutdown && !chip->probing && !chip->in_pm) usb_autopm_put_interface(chip->pm_intf); up_read(&chip->shutdown_rwsem); } @@ -693,13 +702,14 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) chip->autosuspended = 1; } - list_for_each_entry(mixer, &chip->mixer_list, list) - snd_usb_mixer_inactivate(mixer); + 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; @@ -709,12 +719,14 @@ static int usb_audio_resume(struct usb_interface *intf) return 0; if (--chip->num_suspended_intf) return 0; + + chip->in_pm = 1; /* * ALSA leaves material resumption to user space * we just notify and restart the mixers */ list_for_each_entry(mixer, &chip->mixer_list, list) { - err = snd_usb_mixer_activate(mixer); + err = snd_usb_mixer_resume(mixer, reset_resume); if (err < 0) goto err_out; } @@ -724,11 +736,23 @@ static int usb_audio_resume(struct usb_interface *intf) chip->autosuspended = 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 [] = { @@ -750,23 +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); |
