aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/mixer.c
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2011-03-11 08:51:12 -0500
committerTakashi Iwai <tiwai@suse.de>2011-03-11 08:59:29 -0500
commit88a8516a2128a6d078a106ead48092240e8a138f (patch)
treedc839c85a9b2fc2e17759c5a42368cb8300e42bc /sound/usb/mixer.c
parentedf7de31c25ce72f163bf7d1fc0d2711869d073c (diff)
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.c23
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 @@
61#include "mixer.h" 61#include "mixer.h"
62#include "helper.h" 62#include "helper.h"
63#include "mixer_quirks.h" 63#include "mixer_quirks.h"
64#include "power.h"
64 65
65#define MAX_ID_ELEMS 256 66#define MAX_ID_ELEMS 256
66 67
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
295 unsigned char buf[2]; 296 unsigned char buf[2];
296 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 297 int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
297 int timeout = 10; 298 int timeout = 10;
299 int err;
298 300
301 err = snd_usb_autoresume(cval->mixer->chip);
302 if (err < 0)
303 return -EIO;
299 while (timeout-- > 0) { 304 while (timeout-- > 0) {
300 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, 305 if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
301 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 306 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
302 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 307 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
303 buf, val_len, 100) >= val_len) { 308 buf, val_len, 100) >= val_len) {
304 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); 309 *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
310 snd_usb_autosuspend(cval->mixer->chip);
305 return 0; 311 return 0;
306 } 312 }
307 } 313 }
314 snd_usb_autosuspend(cval->mixer->chip);
308 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 315 snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
309 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); 316 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
310 return -EINVAL; 317 return -EINVAL;
@@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
328 335
329 memset(buf, 0, sizeof(buf)); 336 memset(buf, 0, sizeof(buf));
330 337
338 ret = snd_usb_autoresume(chip) ? -EIO : 0;
339 if (ret)
340 goto error;
341
331 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, 342 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
332 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 343 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
333 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 344 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
334 buf, size, 1000); 345 buf, size, 1000);
346 snd_usb_autosuspend(chip);
335 347
336 if (ret < 0) { 348 if (ret < 0) {
349error:
337 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", 350 snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
338 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); 351 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
339 return ret; 352 return ret;
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
413{ 426{
414 struct snd_usb_audio *chip = cval->mixer->chip; 427 struct snd_usb_audio *chip = cval->mixer->chip;
415 unsigned char buf[2]; 428 unsigned char buf[2];
416 int val_len, timeout = 10; 429 int val_len, err, timeout = 10;
417 430
418 if (cval->mixer->protocol == UAC_VERSION_1) { 431 if (cval->mixer->protocol == UAC_VERSION_1) {
419 val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; 432 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,
433 value_set = convert_bytes_value(cval, value_set); 446 value_set = convert_bytes_value(cval, value_set);
434 buf[0] = value_set & 0xff; 447 buf[0] = value_set & 0xff;
435 buf[1] = (value_set >> 8) & 0xff; 448 buf[1] = (value_set >> 8) & 0xff;
449 err = snd_usb_autoresume(chip);
450 if (err < 0)
451 return -EIO;
436 while (timeout-- > 0) 452 while (timeout-- > 0)
437 if (snd_usb_ctl_msg(chip->dev, 453 if (snd_usb_ctl_msg(chip->dev,
438 usb_sndctrlpipe(chip->dev, 0), request, 454 usb_sndctrlpipe(chip->dev, 0), request,
439 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 455 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
440 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), 456 validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
441 buf, val_len, 100) >= 0) 457 buf, val_len, 100) >= 0) {
458 snd_usb_autosuspend(chip);
442 return 0; 459 return 0;
460 }
461 snd_usb_autosuspend(chip);
443 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", 462 snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
444 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); 463 request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
445 return -EINVAL; 464 return -EINVAL;