ALSA: usb-audio: Add Emu0204 channel switch resume support
authorTakashi Iwai <tiwai@suse.de>
Tue, 18 Nov 2014 15:11:37 +0000 (16:11 +0100)
committerTakashi Iwai <tiwai@suse.de>
Fri, 21 Nov 2014 10:57:55 +0000 (11:57 +0100)
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>
sound/usb/mixer_quirks.c

index 41cacf8..f2b1c0d 100644 (file)
@@ -473,63 +473,71 @@ static int snd_emu0204_ch_switch_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol,
-                                    struct snd_ctl_elem_value *ucontrol)
+static int snd_emu0204_ch_switch_update(struct usb_mixer_interface *mixer,
+                                       int value)
 {
-       struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
-       unsigned int value = ucontrol->value.enumerated.item[0];
-       int err, changed;
+       struct snd_usb_audio *chip = mixer->chip;
+       int err;
        unsigned char buf[2];
 
-       if (value > 1)
-               return -EINVAL;
-
-       buf[0] = 0x01;
-       buf[1] = value ? 0x02 : 0x01;
-
-       changed = value != kcontrol->private_value;
-       down_read(&mixer->chip->shutdown_rwsem);
+       down_read(&chip->shutdown_rwsem);
        if (mixer->chip->shutdown) {
                err = -ENODEV;
                goto out;
        }
-       err = snd_usb_ctl_msg(mixer->chip->dev,
-                     usb_sndctrlpipe(mixer->chip->dev, 0), UAC_SET_CUR,
+
+       buf[0] = 0x01;
+       buf[1] = value ? 0x02 : 0x01;
+       err = snd_usb_ctl_msg(chip->dev,
+                     usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
                      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
                      0x0400, 0x0e00, buf, 2);
  out:
-       up_read(&mixer->chip->shutdown_rwsem);
-       if (err < 0)
-               return err;
+       up_read(&chip->shutdown_rwsem);
+       return err;
+}
+
+static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
+       struct usb_mixer_interface *mixer = list->mixer;
+       unsigned int value = ucontrol->value.enumerated.item[0];
+       int err;
+
+       if (value > 1)
+               return -EINVAL;
+
+       if (value == kcontrol->private_value)
+               return 0;
+
        kcontrol->private_value = value;
-       return changed;
+       err = snd_emu0204_ch_switch_update(mixer, value);
+       return err < 0 ? err : 1;
 }
 
+static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list)
+{
+       return snd_emu0204_ch_switch_update(list->mixer,
+                                           list->kctl->private_value);
+}
 
-static struct snd_kcontrol_new snd_emu0204_controls[] = {
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               .name = "Front Jack Channels",
-               .info = snd_emu0204_ch_switch_info,
-               .get = snd_emu0204_ch_switch_get,
-               .put = snd_emu0204_ch_switch_put,
-               .private_value = 0,
-       },
+static struct snd_kcontrol_new snd_emu0204_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Front Jack Channels",
+       .info = snd_emu0204_ch_switch_info,
+       .get = snd_emu0204_ch_switch_get,
+       .put = snd_emu0204_ch_switch_put,
+       .private_value = 0,
 };
 
 static int snd_emu0204_controls_create(struct usb_mixer_interface *mixer)
 {
-       int i, err;
-
-       for (i = 0; i < ARRAY_SIZE(snd_emu0204_controls); ++i) {
-               err = snd_ctl_add(mixer->chip->card,
-                       snd_ctl_new1(&snd_emu0204_controls[i], mixer));
-               if (err < 0)
-                       return err;
-       }
-
-       return 0;
+       return add_single_ctl_with_resume(mixer, 0,
+                                         snd_emu0204_ch_switch_resume,
+                                         &snd_emu0204_control, NULL);
 }
+
 /* ASUS Xonar U1 / U3 controls */
 
 static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,