diff options
author | Oliver Neukum <oneukum@suse.de> | 2011-03-11 16:51:12 +0300 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-03-11 16:59:29 +0300 |
commit | 88a8516a2128a6d078a106ead48092240e8a138f (patch) | |
tree | dc839c85a9b2fc2e17759c5a42368cb8300e42bc /sound/usb/mixer.c | |
parent | edf7de31c25ce72f163bf7d1fc0d2711869d073c (diff) | |
download | linux-88a8516a2128a6d078a106ead48092240e8a138f.tar.xz |
ALSA: usbaudio: implement USB autosuspend
Devices are autosuspended if no pcm nor midi channel is open
Mixer devices may be opened. This way they are active when
in use to play or record sound, but can be suspended while
users have a mixer application running.
[Small clean-ups using static inline by tiwai]
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r-- | sound/usb/mixer.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 09e59345bb6d..5e4775716607 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -61,6 +61,7 @@ #include "mixer.h" #include "helper.h" #include "mixer_quirks.h" +#include "power.h" #define MAX_ID_ELEMS 256 @@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v unsigned char buf[2]; int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; int timeout = 10; + int err; + err = snd_usb_autoresume(cval->mixer->chip); + if (err < 0) + return -EIO; while (timeout-- > 0) { if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), buf, val_len, 100) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); + snd_usb_autosuspend(cval->mixer->chip); return 0; } } + snd_usb_autosuspend(cval->mixer->chip); snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); return -EINVAL; @@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v memset(buf, 0, sizeof(buf)); + ret = snd_usb_autoresume(chip) ? -EIO : 0; + if (ret) + goto error; + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), buf, size, 1000); + snd_usb_autosuspend(chip); if (ret < 0) { +error: snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); return ret; @@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, { struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2]; - int val_len, timeout = 10; + int val_len, err, timeout = 10; if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, value_set = convert_bytes_value(cval, value_set); buf[0] = value_set & 0xff; buf[1] = (value_set >> 8) & 0xff; + err = snd_usb_autoresume(chip); + if (err < 0) + return -EIO; while (timeout-- > 0) if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len, 100) >= 0) + buf, val_len, 100) >= 0) { + snd_usb_autosuspend(chip); return 0; + } + snd_usb_autosuspend(chip); snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); return -EINVAL; |