From d02667e6206fb3be0990c38af8447a4ed2b74c11 Mon Sep 17 00:00:00 2001
From: Vitaliy Kulikov <Vitaliy.Kulikov@idt.com>
Date: Fri, 22 Jul 2011 18:18:15 -0500
Subject: [PATCH] ALSA: hda - Fix invalid mute led state on resume of IDT codecs
Git-commit: d02667e6206fb3be0990c38af8447a4ed2b74c11
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
Patch-mainline: 3.1-rc2
References: bnc#708376

Codec state is not restored immediately on resume but on the first
access when power-save is enabled.  That leads to an invalid mute led
state after resume until either sound is played or some control is
changed.  This patch adds a possibility for a vendor specific patch to
restore codec state immediately after resume if required.  And it adds
code to restore IDT codecs state immediately on resume on HP systems
with mute led support.

Signed-off-by: Vitaliy Kulikov <Vitaliy.Kulikov@idt.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 sound/pci/hda/hda_codec.c      |    2 ++
 sound/pci/hda/hda_codec.h      |    3 +++
 sound/pci/hda/patch_sigmatel.c |   12 ++++++++++++
 3 files changed, 17 insertions(+)

--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -4007,6 +4007,8 @@
 	struct hda_codec *codec;
 
 	list_for_each_entry(codec, &bus->codec_list, list) {
+		if (codec->patch_ops.pre_resume)
+			codec->patch_ops.pre_resume(codec);
 		if (snd_hda_codec_needs_resume(codec))
 			hda_call_codec_resume(codec);
 	}
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -684,6 +684,9 @@
 	int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
 #endif
 	void (*reboot_notify)(struct hda_codec *codec);
+#ifdef SND_HDA_NEEDS_RESUME
+	int (*pre_resume)(struct hda_codec *codec);
+#endif
 };
 
 /* record for amp information cache */
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4997,6 +4997,17 @@
 #endif
 
 #ifdef SND_HDA_NEEDS_RESUME
+static int stac92xx_pre_resume(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	/* sync mute LED */
+	if (spec->gpio_led)
+		stac_gpio_set(codec, spec->gpio_mask,
+				spec->gpio_dir, spec->gpio_data);
+	return 0;
+}
+
 static int stac92xx_resume(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -5077,6 +5088,7 @@
 #ifdef SND_HDA_NEEDS_RESUME
 	.suspend = stac92xx_suspend,
 	.resume = stac92xx_resume,
+	.pre_resume = stac92xx_pre_resume,
 #endif
 	.reboot_notify = stac92xx_shutup,
 };
