diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-11-18 10:11:37 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-11-21 05:57:55 -0500 |
commit | 5f503ee9e270f8251ba9024bafa8d698050066cb (patch) | |
tree | d78f2ddf1a969f505396bcaac66ef64e80cb6ce4 | |
parent | 9cf3689bfe0784b6f6afb301bece95d3fc3eeb64 (diff) |
ALSA: usb-audio: Add Emu0204 channel switch resume support
Similar as the previous fix, this adds the proper resume support to
Emu0202 "Front Jack Channels" enum mixer element.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/usb/mixer_quirks.c | 84 |
1 files changed, 46 insertions, 38 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41cacf889c98..f2b1c0d8ccd1 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -473,63 +473,71 @@ static int snd_emu0204_ch_switch_get(struct snd_kcontrol *kcontrol, | |||
473 | return 0; | 473 | return 0; |
474 | } | 474 | } |
475 | 475 | ||
476 | static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, | 476 | static int snd_emu0204_ch_switch_update(struct usb_mixer_interface *mixer, |
477 | struct snd_ctl_elem_value *ucontrol) | 477 | int value) |
478 | { | 478 | { |
479 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 479 | struct snd_usb_audio *chip = mixer->chip; |
480 | unsigned int value = ucontrol->value.enumerated.item[0]; | 480 | int err; |
481 | int err, changed; | ||
482 | unsigned char buf[2]; | 481 | unsigned char buf[2]; |
483 | 482 | ||
484 | if (value > 1) | 483 | down_read(&chip->shutdown_rwsem); |
485 | return -EINVAL; | ||
486 | |||
487 | buf[0] = 0x01; | ||
488 | buf[1] = value ? 0x02 : 0x01; | ||
489 | |||
490 | changed = value != kcontrol->private_value; | ||
491 | down_read(&mixer->chip->shutdown_rwsem); | ||
492 | if (mixer->chip->shutdown) { | 484 | if (mixer->chip->shutdown) { |
493 | err = -ENODEV; | 485 | err = -ENODEV; |
494 | goto out; | 486 | goto out; |
495 | } | 487 | } |
496 | err = snd_usb_ctl_msg(mixer->chip->dev, | 488 | |
497 | usb_sndctrlpipe(mixer->chip->dev, 0), UAC_SET_CUR, | 489 | buf[0] = 0x01; |
490 | buf[1] = value ? 0x02 : 0x01; | ||
491 | err = snd_usb_ctl_msg(chip->dev, | ||
492 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, | ||
498 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 493 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
499 | 0x0400, 0x0e00, buf, 2); | 494 | 0x0400, 0x0e00, buf, 2); |
500 | out: | 495 | out: |
501 | up_read(&mixer->chip->shutdown_rwsem); | 496 | up_read(&chip->shutdown_rwsem); |
502 | if (err < 0) | 497 | return err; |
503 | return err; | 498 | } |
499 | |||
500 | static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, | ||
501 | struct snd_ctl_elem_value *ucontrol) | ||
502 | { | ||
503 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); | ||
504 | struct usb_mixer_interface *mixer = list->mixer; | ||
505 | unsigned int value = ucontrol->value.enumerated.item[0]; | ||
506 | int err; | ||
507 | |||
508 | if (value > 1) | ||
509 | return -EINVAL; | ||
510 | |||
511 | if (value == kcontrol->private_value) | ||
512 | return 0; | ||
513 | |||
504 | kcontrol->private_value = value; | 514 | kcontrol->private_value = value; |
505 | return changed; | 515 | err = snd_emu0204_ch_switch_update(mixer, value); |
516 | return err < 0 ? err : 1; | ||
506 | } | 517 | } |
507 | 518 | ||
519 | static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list) | ||
520 | { | ||
521 | return snd_emu0204_ch_switch_update(list->mixer, | ||
522 | list->kctl->private_value); | ||
523 | } | ||
508 | 524 | ||
509 | static struct snd_kcontrol_new snd_emu0204_controls[] = { | 525 | static struct snd_kcontrol_new snd_emu0204_control = { |
510 | { | 526 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
511 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 527 | .name = "Front Jack Channels", |
512 | .name = "Front Jack Channels", | 528 | .info = snd_emu0204_ch_switch_info, |
513 | .info = snd_emu0204_ch_switch_info, | 529 | .get = snd_emu0204_ch_switch_get, |
514 | .get = snd_emu0204_ch_switch_get, | 530 | .put = snd_emu0204_ch_switch_put, |
515 | .put = snd_emu0204_ch_switch_put, | 531 | .private_value = 0, |
516 | .private_value = 0, | ||
517 | }, | ||
518 | }; | 532 | }; |
519 | 533 | ||
520 | static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer) | 534 | static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer) |
521 | { | 535 | { |
522 | int i, err; | 536 | return add_single_ctl_with_resume(mixer, 0, |
523 | 537 | snd_emu0204_ch_switch_resume, | |
524 | for (i = 0; i < ARRAY_SIZE(snd_emu0204_controls); ++i) { | 538 | &snd_emu0204_control, NULL); |
525 | err = snd_ctl_add(mixer->chip->card, | ||
526 | snd_ctl_new1(&snd_emu0204_controls[i], mixer)); | ||
527 | if (err < 0) | ||
528 | return err; | ||
529 | } | ||
530 | |||
531 | return 0; | ||
532 | } | 539 | } |
540 | |||
533 | /* ASUS Xonar U1 / U3 controls */ | 541 | /* ASUS Xonar U1 / U3 controls */ |
534 | 542 | ||
535 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, | 543 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, |