aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-11-18 10:59:47 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-21 05:58:14 -0500
commitda6d276957ea56b9514aa5c8d885edf22f0b3e65 (patch)
tree2c0528ae77eb36953a84830078d23b710a0cd854
parent25a9a4f91b909822fa07cbc9939c99a8c67d8960 (diff)
ALSA: usb-audio: Add resume support for Native Instruments controls
The changes at this time are a bit more wider than previous ones. Firstly, the NI controls didn't cache the values, so I had to implement the caching. It's stored in bit 24 of private_value. In addition to that, the initial values have to be read from registers. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/mixer_quirks.c99
1 files changed, 52 insertions, 47 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index f7ad2078c0cf..e11b4f3e1215 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -742,64 +742,68 @@ static int snd_mbox1_create_sync_switch(struct usb_mixer_interface *mixer)
742 742
743#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) 743#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
744 744
745static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, 745static int snd_ni_control_init_val(struct usb_mixer_interface *mixer,
746 struct snd_ctl_elem_value *ucontrol) 746 struct snd_kcontrol *kctl)
747{ 747{
748 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
749 struct usb_device *dev = mixer->chip->dev; 748 struct usb_device *dev = mixer->chip->dev;
750 u8 bRequest = (kcontrol->private_value >> 16) & 0xff; 749 unsigned int pval = kctl->private_value;
751 u16 wIndex = kcontrol->private_value & 0xffff; 750 u8 value;
752 u8 tmp; 751 int err;
753 int ret;
754
755 down_read(&mixer->chip->shutdown_rwsem);
756 if (mixer->chip->shutdown)
757 ret = -ENODEV;
758 else
759 ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
760 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
761 0, wIndex,
762 &tmp, sizeof(tmp));
763 up_read(&mixer->chip->shutdown_rwsem);
764 752
765 if (ret < 0) { 753 err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
754 (pval >> 16) & 0xff,
755 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
756 0, pval & 0xffff, &value, 1);
757 if (err < 0) {
766 dev_err(&dev->dev, 758 dev_err(&dev->dev,
767 "unable to issue vendor read request (ret = %d)", ret); 759 "unable to issue vendor read request (ret = %d)", err);
768 return ret; 760 return err;
769 } 761 }
770 762
771 ucontrol->value.integer.value[0] = tmp; 763 kctl->private_value |= (value << 24);
772
773 return 0; 764 return 0;
774} 765}
775 766
776static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, 767static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
777 struct snd_ctl_elem_value *ucontrol) 768 struct snd_ctl_elem_value *ucontrol)
778{ 769{
779 struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); 770 ucontrol->value.integer.value[0] = kcontrol->private_value >> 24;
780 struct usb_device *dev = mixer->chip->dev; 771 return 0;
781 u8 bRequest = (kcontrol->private_value >> 16) & 0xff; 772}
782 u16 wIndex = kcontrol->private_value & 0xffff;
783 u16 wValue = ucontrol->value.integer.value[0];
784 int ret;
785 773
786 down_read(&mixer->chip->shutdown_rwsem); 774static int snd_ni_update_cur_val(struct usb_mixer_elem_list *list)
787 if (mixer->chip->shutdown) 775{
788 ret = -ENODEV; 776 struct snd_usb_audio *chip = list->mixer->chip;
777 unsigned int pval = list->kctl->private_value;
778 int err;
779
780 down_read(&chip->shutdown_rwsem);
781 if (chip->shutdown)
782 err = -ENODEV;
789 else 783 else
790 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, 784 err = usb_control_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
791 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 785 (pval >> 16) & 0xff,
792 wValue, wIndex, 786 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
793 NULL, 0, 1000); 787 pval >> 24, pval & 0xffff, NULL, 0, 1000);
794 up_read(&mixer->chip->shutdown_rwsem); 788 up_read(&chip->shutdown_rwsem);
789 return err;
790}
795 791
796 if (ret < 0) { 792static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
797 dev_err(&dev->dev, 793 struct snd_ctl_elem_value *ucontrol)
798 "unable to issue vendor write request (ret = %d)", ret); 794{
799 return ret; 795 struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
800 } 796 u8 oldval = (kcontrol->private_value >> 24) & 0xff;
797 u8 newval = ucontrol->value.integer.value[0];
798 int err;
801 799
802 return 0; 800 if (oldval == newval)
801 return 0;
802
803 kcontrol->private_value &= ~(0xff << 24);
804 kcontrol->private_value |= newval;
805 err = snd_ni_update_cur_val(list);
806 return err < 0 ? err : 1;
803} 807}
804 808
805static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { 809static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
@@ -870,16 +874,17 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
870 }; 874 };
871 875
872 for (i = 0; i < count; i++) { 876 for (i = 0; i < count; i++) {
873 struct snd_kcontrol *c; 877 struct usb_mixer_elem_list *list;
874 878
875 template.name = kc[i].name; 879 template.name = kc[i].name;
876 template.private_value = kc[i].private_value; 880 template.private_value = kc[i].private_value;
877 881
878 c = snd_ctl_new1(&template, mixer); 882 err = add_single_ctl_with_resume(mixer, 0,
879 err = snd_ctl_add(mixer->chip->card, c); 883 snd_ni_update_cur_val,
880 884 &template, &list);
881 if (err < 0) 885 if (err < 0)
882 break; 886 break;
887 snd_ni_control_init_val(mixer, list->kctl);
883 } 888 }
884 889
885 return err; 890 return err;