[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <bca6607d26ef205356b619dbfbc7a8ef81080275.1438699154.git.jslaby@suse.cz>
Date: Tue, 4 Aug 2015 16:39:22 +0200
From: Jiri Slaby <jslaby@...e.cz>
To: stable@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, Takashi Iwai <tiwai@...e.de>,
Jiri Slaby <jslaby@...e.cz>
Subject: [PATCH 3.12 018/123] ALSA: usb-audio: Resume mixer values properly
From: Takashi Iwai <tiwai@...e.de>
3.12-stable review patch. If anyone has any objections, please let me know.
===============
commit 400362f1d8dcfda3562e80e88cfc2a92cffaf9bf upstream.
Implement reset_resume callback so that the mixer values are properly
restored. Still no boot quirks are called, so it might not work well
on some devices.
Signed-off-by: Takashi Iwai <tiwai@...e.de>
Signed-off-by: Jiri Slaby <jslaby@...e.cz>
---
sound/usb/card.c | 18 ++++++++--
sound/usb/mixer.c | 99 ++++++++++++++++++++++++++++++++++++++++++++-----------
sound/usb/mixer.h | 7 ++--
3 files changed, 99 insertions(+), 25 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 4476b9047adc..3ab9fc47da09 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -706,12 +706,12 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
}
list_for_each_entry(mixer, &chip->mixer_list, list)
- snd_usb_mixer_inactivate(mixer);
+ snd_usb_mixer_suspend(mixer);
return 0;
}
-static int usb_audio_resume(struct usb_interface *intf)
+static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
{
struct snd_usb_audio *chip = usb_get_intfdata(intf);
struct usb_mixer_interface *mixer;
@@ -726,7 +726,7 @@ static int usb_audio_resume(struct usb_interface *intf)
* we just notify and restart the mixers
*/
list_for_each_entry(mixer, &chip->mixer_list, list) {
- err = snd_usb_mixer_activate(mixer);
+ err = snd_usb_mixer_resume(mixer, reset_resume);
if (err < 0)
goto err_out;
}
@@ -738,9 +738,20 @@ static int usb_audio_resume(struct usb_interface *intf)
err_out:
return err;
}
+
+static int usb_audio_resume(struct usb_interface *intf)
+{
+ return __usb_audio_resume(intf, false);
+}
+
+static int usb_audio_reset_resume(struct usb_interface *intf)
+{
+ return __usb_audio_resume(intf, true);
+}
#else
#define usb_audio_suspend NULL
#define usb_audio_resume NULL
+#define usb_audio_reset_resume NULL
#endif /* CONFIG_PM */
static struct usb_device_id usb_audio_ids [] = {
@@ -762,6 +773,7 @@ static struct usb_driver usb_audio_driver = {
.disconnect = usb_audio_disconnect,
.suspend = usb_audio_suspend,
.resume = usb_audio_resume,
+ .reset_resume = usb_audio_reset_resume,
.id_table = usb_audio_ids,
.supports_autosuspend = 1,
};
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 5ea5a18f3f58..86f46b46f214 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2302,26 +2302,6 @@ requeue:
}
}
-/* stop any bus activity of a mixer */
-void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
-{
- usb_kill_urb(mixer->urb);
- usb_kill_urb(mixer->rc_urb);
-}
-
-int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
-{
- int err;
-
- if (mixer->urb) {
- err = usb_submit_urb(mixer->urb, GFP_NOIO);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
/* create the handler for the optional status interrupt endpoint */
static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
{
@@ -2420,3 +2400,82 @@ void snd_usb_mixer_disconnect(struct list_head *p)
usb_kill_urb(mixer->urb);
usb_kill_urb(mixer->rc_urb);
}
+
+#ifdef CONFIG_PM
+/* stop any bus activity of a mixer */
+static void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
+{
+ usb_kill_urb(mixer->urb);
+ usb_kill_urb(mixer->rc_urb);
+}
+
+static int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
+{
+ int err;
+
+ if (mixer->urb) {
+ err = usb_submit_urb(mixer->urb, GFP_NOIO);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
+{
+ snd_usb_mixer_inactivate(mixer);
+ return 0;
+}
+
+static int restore_mixer_value(struct usb_mixer_elem_info *cval)
+{
+ int c, err, idx;
+
+ if (cval->cmask) {
+ idx = 0;
+ for (c = 0; c < MAX_CHANNELS; c++) {
+ if (!(cval->cmask & (1 << c)))
+ continue;
+ if (cval->cached & (1 << c)) {
+ err = set_cur_mix_value(cval, c + 1, idx,
+ cval->cache_val[idx]);
+ if (err < 0)
+ return err;
+ }
+ idx++;
+ }
+ } else {
+ /* master */
+ if (cval->cached) {
+ err = set_cur_mix_value(cval, 0, 0, *cval->cache_val);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
+{
+ struct usb_mixer_elem_info *cval;
+ int id, err;
+
+ /* FIXME: any mixer quirks? */
+
+ if (reset_resume) {
+ /* restore cached mixer values */
+ for (id = 0; id < MAX_ID_ELEMS; id++) {
+ for (cval = mixer->id_elems[id]; cval;
+ cval = cval->next_id_elem) {
+ err = restore_mixer_value(cval);
+ if (err < 0)
+ return err;
+ }
+ }
+ }
+
+ return snd_usb_mixer_activate(mixer);
+}
+#endif
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index aab80df201bd..73b1f649447b 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -63,8 +63,6 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
int request, int validx, int value_set);
-void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
-int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
struct snd_kcontrol *kctl);
@@ -72,4 +70,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv);
+#ifdef CONFIG_PM
+int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer);
+int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume);
+#endif
+
#endif /* __USBMIXER_H */
--
2.5.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists