diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-11-18 10:18:15 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-11-21 05:58:01 -0500 |
commit | 2bfb14c3b8fbc787ff4478f9d77ecee78cb922fe (patch) | |
tree | 1b181fa8f501abf62ee527da7c455bc0e3af50bd /sound/usb | |
parent | 5f503ee9e270f8251ba9024bafa8d698050066cb (diff) |
ALSA: usb-audio: Add Xonar U1 resume support
This time it's about Xonar U1: add the proper resume support for
"Digital Playback Switch" element.
Also, the status is moved into kcontrol private_value from
usb_mixer_interface struct field. One more cut.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/mixer.h | 2 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 66 |
2 files changed, 38 insertions, 30 deletions
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 0b3740ea6614..d3268f0ee2b3 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h | |||
@@ -22,8 +22,6 @@ struct usb_mixer_interface { | |||
22 | struct urb *rc_urb; | 22 | struct urb *rc_urb; |
23 | struct usb_ctrlrequest *rc_setup_packet; | 23 | struct usb_ctrlrequest *rc_setup_packet; |
24 | u8 rc_buffer[6]; | 24 | u8 rc_buffer[6]; |
25 | |||
26 | u8 xonar_u1_status; | ||
27 | }; | 25 | }; |
28 | 26 | ||
29 | #define MAX_CHANNELS 16 /* max logical channels */ | 27 | #define MAX_CHANNELS 16 /* max logical channels */ |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f2b1c0d8ccd1..4afcf096ebb2 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -543,38 +543,52 @@ static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer) | |||
543 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, | 543 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, |
544 | struct snd_ctl_elem_value *ucontrol) | 544 | struct snd_ctl_elem_value *ucontrol) |
545 | { | 545 | { |
546 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 546 | ucontrol->value.integer.value[0] = !!(kcontrol->private_value & 0x02); |
547 | |||
548 | ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02); | ||
549 | return 0; | 547 | return 0; |
550 | } | 548 | } |
551 | 549 | ||
550 | static int snd_xonar_u1_switch_update(struct usb_mixer_interface *mixer, | ||
551 | unsigned char status) | ||
552 | { | ||
553 | struct snd_usb_audio *chip = mixer->chip; | ||
554 | int err; | ||
555 | |||
556 | down_read(&chip->shutdown_rwsem); | ||
557 | if (chip->shutdown) | ||
558 | err = -ENODEV; | ||
559 | else | ||
560 | err = snd_usb_ctl_msg(chip->dev, | ||
561 | usb_sndctrlpipe(chip->dev, 0), 0x08, | ||
562 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
563 | 50, 0, &status, 1); | ||
564 | up_read(&chip->shutdown_rwsem); | ||
565 | return err; | ||
566 | } | ||
567 | |||
552 | static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, | 568 | static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, |
553 | struct snd_ctl_elem_value *ucontrol) | 569 | struct snd_ctl_elem_value *ucontrol) |
554 | { | 570 | { |
555 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | 571 | struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); |
556 | u8 old_status, new_status; | 572 | u8 old_status, new_status; |
557 | int err, changed; | 573 | int err; |
558 | 574 | ||
559 | old_status = mixer->xonar_u1_status; | 575 | old_status = kcontrol->private_value; |
560 | if (ucontrol->value.integer.value[0]) | 576 | if (ucontrol->value.integer.value[0]) |
561 | new_status = old_status | 0x02; | 577 | new_status = old_status | 0x02; |
562 | else | 578 | else |
563 | new_status = old_status & ~0x02; | 579 | new_status = old_status & ~0x02; |
564 | changed = new_status != old_status; | 580 | if (new_status == old_status) |
565 | down_read(&mixer->chip->shutdown_rwsem); | 581 | return 0; |
566 | if (mixer->chip->shutdown) | 582 | |
567 | err = -ENODEV; | 583 | kcontrol->private_value = new_status; |
568 | else | 584 | err = snd_xonar_u1_switch_update(list->mixer, new_status); |
569 | err = snd_usb_ctl_msg(mixer->chip->dev, | 585 | return err < 0 ? err : 1; |
570 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, | 586 | } |
571 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 587 | |
572 | 50, 0, &new_status, 1); | 588 | static int snd_xonar_u1_switch_resume(struct usb_mixer_elem_list *list) |
573 | up_read(&mixer->chip->shutdown_rwsem); | 589 | { |
574 | if (err < 0) | 590 | return snd_xonar_u1_switch_update(list->mixer, |
575 | return err; | 591 | list->kctl->private_value); |
576 | mixer->xonar_u1_status = new_status; | ||
577 | return changed; | ||
578 | } | 592 | } |
579 | 593 | ||
580 | static struct snd_kcontrol_new snd_xonar_u1_output_switch = { | 594 | static struct snd_kcontrol_new snd_xonar_u1_output_switch = { |
@@ -583,18 +597,14 @@ static struct snd_kcontrol_new snd_xonar_u1_output_switch = { | |||
583 | .info = snd_ctl_boolean_mono_info, | 597 | .info = snd_ctl_boolean_mono_info, |
584 | .get = snd_xonar_u1_switch_get, | 598 | .get = snd_xonar_u1_switch_get, |
585 | .put = snd_xonar_u1_switch_put, | 599 | .put = snd_xonar_u1_switch_put, |
600 | .private_value = 0x05, | ||
586 | }; | 601 | }; |
587 | 602 | ||
588 | static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | 603 | static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) |
589 | { | 604 | { |
590 | int err; | 605 | return add_single_ctl_with_resume(mixer, 0, |
591 | 606 | snd_xonar_u1_switch_resume, | |
592 | err = snd_ctl_add(mixer->chip->card, | 607 | &snd_xonar_u1_output_switch, NULL); |
593 | snd_ctl_new1(&snd_xonar_u1_output_switch, mixer)); | ||
594 | if (err < 0) | ||
595 | return err; | ||
596 | mixer->xonar_u1_status = 0x05; | ||
597 | return 0; | ||
598 | } | 608 | } |
599 | 609 | ||
600 | /* Digidesign Mbox 1 clock source switch (internal/spdif) */ | 610 | /* Digidesign Mbox 1 clock source switch (internal/spdif) */ |