diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 10:46:37 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 10:46:37 -0700 |
| commit | d3e458d78167102cc961237cfceef6fffc80c0b3 (patch) | |
| tree | e9195c1294daf053614e63ac52b0b44a28479017 /sound/usb/card.c | |
| parent | f2e1fbb5f2177227f71c4fc0491e531dd7acd385 (diff) | |
| parent | d351cf4603edb2a5bfa9a48d06c425511c63f2a3 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (308 commits)
ALSA: sound/pci/asihpi: check adapter index in hpi_ioctl
ALSA: aloop - Fix possible IRQ lock inversion
ALSA: sound/core: merge list_del()/list_add_tail() to list_move_tail()
ALSA: ctxfi - use list_move() instead of list_del()/list_add() combination
ALSA: firewire - msleep needs delay.h
ALSA: firewire-lib, firewire-speakers: handle packet queueing errors
ALSA: firewire-lib: allocate DMA buffer separately
ALSA: firewire-lib: use no-info SYT for packets without SYT sample
ALSA: add LaCie FireWire Speakers/Griffin FireWave Surround driver
ALSA: hda - Remove an unused variable in patch_realtek.c
ALSA: hda - pin-adc-mux-dmic auto-configuration of 92HD8X codecs
ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs
ALSA: hda - Move default input-src selection to init part
ALSA: hda - Initialize special cases for input src in init phase
ALSA: ctxfi - Clear input settings before initialization
ALSA: ctxfi - Fix SPDIF status retrieval
ALSA: ctxfi - Fix incorrect SPDIF status bit mask
ALSA: ctxfi - Fix microphone boost codes/comments
ALSA: atiixp - Fix wrong time-out checks during ac-link reset
ALSA: intel8x0m: append 'm' to "r_intel8x0"
...
Diffstat (limited to 'sound/usb/card.c')
| -rw-r--r-- | sound/usb/card.c | 64 |
1 files changed, 55 insertions, 9 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index c0f8270bc19..40722f8711a 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -65,6 +65,7 @@ #include "pcm.h" #include "urb.h" #include "format.h" +#include "power.h" MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); MODULE_DESCRIPTION("USB Audio"); @@ -330,6 +331,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, chip->setup = device_setup[idx]; chip->nrpacks = nrpacks; chip->async_unlink = async_unlink; + chip->probing = 1; chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); @@ -451,6 +453,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, goto __error; } chip = usb_chip[i]; + chip->probing = 1; break; } } @@ -466,6 +469,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, goto __error; } snd_card_set_dev(chip->card, &intf->dev); + chip->pm_intf = intf; break; } if (!chip) { @@ -505,6 +509,7 @@ 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; @@ -581,29 +586,61 @@ static void usb_audio_disconnect(struct usb_interface *intf) } #ifdef CONFIG_PM + +int snd_usb_autoresume(struct snd_usb_audio *chip) +{ + int err = -ENODEV; + + if (!chip->shutdown && !chip->probing) + err = usb_autopm_get_interface(chip->pm_intf); + + return err; +} + +void snd_usb_autosuspend(struct snd_usb_audio *chip) +{ + if (!chip->shutdown && !chip->probing) + usb_autopm_put_interface(chip->pm_intf); +} + 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 (!(message.event & PM_EVENT_AUTO)) { + 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); + } + } + } else { + /* + * otherwise we keep the rest of the system in the dark + * to keep this transparent + */ + if (!chip->num_suspended_intf++) + chip->autosuspended = 1; } + list_for_each_entry(mixer, &chip->mixer_list, list) + snd_usb_mixer_inactivate(mixer); + return 0; } static int usb_audio_resume(struct usb_interface *intf) { struct snd_usb_audio *chip = usb_get_intfdata(intf); + struct usb_mixer_interface *mixer; + int err = 0; if (chip == (void *)-1L) return 0; @@ -611,12 +648,20 @@ static int usb_audio_resume(struct usb_interface *intf) return 0; /* * 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_activate(mixer); + 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: + return err; } #else #define usb_audio_suspend NULL @@ -644,6 +689,7 @@ static struct usb_driver usb_audio_driver = { .suspend = usb_audio_suspend, .resume = usb_audio_resume, .id_table = usb_audio_ids, + .supports_autosuspend = 1, }; static int __init snd_usb_audio_init(void) |
