[alsa-devel] [PATCH] hda_codec: restore control element values during resume

Daniel Drake dsd at gentoo.org
Sun Apr 29 18:14:21 CEST 2007


After resume from suspend-to-RAM, there is no sound output from my Intel HDA
hardware:

00:1b.0 Audio device: Intel Corporation 82801G (ICH7 Family) High Definition
Audio Controller (rev 01)
Found in a Dell Inspiron 640m, SigmaTel STAC9200 chip.

After resuming, sound immediately returns when you adjust the volume one notch
in either direction. I reported this on the ALSA bug tracker (#0002989).

Further investigation shows that the AC_VERB_SET_AMP_GAIN_MUTE verb is not
being executed during resume, which seems strange. Does other hardware really
store this value during a suspend/resume cycle? Or maybe the volume is
generally controlled through other means on other setups? I'm not entirely
sure what the difference is between kcontrol and kcontrol_new structures, but
I note that there is already some code to restore the values for kcontrol_new
elements.

I solved the issue with the following patch. Is it correct?

Signed-off-by: Daniel Drake <dsd at gentoo.org>

Index: linux-2.6/sound/pci/hda/hda_codec.c
===================================================================
--- linux-2.6.orig/sound/pci/hda/hda_codec.c
+++ linux-2.6/sound/pci/hda/hda_codec.c
@@ -2248,15 +2248,39 @@ EXPORT_SYMBOL(snd_hda_suspend);
 int snd_hda_resume(struct hda_bus *bus)
 {
 	struct list_head *p;
+	struct snd_ctl_elem_value *val = kmalloc(sizeof(*val), GFP_KERNEL);
+
+	if (!val)
+		return -ENOMEM;
 
 	list_for_each(p, &bus->codec_list) {
 		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		struct snd_kcontrol *kctl;
+
+		codec->in_resume = 1;
+
 		hda_set_power_state(codec,
 				    codec->afg ? codec->afg : codec->mfg,
 				    AC_PWRST_D0);
+
+
+		list_for_each_entry(kctl, &bus->card->controls, list) {
+			memset(val, 0, sizeof(*val));
+			val->id = kctl->id;
+			/* Assume that get callback reads only from cache,
+			 * not accessing the real hardware
+			 */
+			if (snd_ctl_elem_read(bus->card, val) < 0)
+				continue;
+			snd_ctl_elem_write(bus->card, NULL, val);
+		}
+
 		if (codec->patch_ops.resume)
 			codec->patch_ops.resume(codec);
+
+		codec->in_resume = 0;
 	}
+	kfree(val);
 	return 0;
 }
 


More information about the Alsa-devel mailing list