From 1c86845268dc91fa6a53de9a4479b407cd4ee903 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 13 Aug 2012 11:09:35 +0200
Subject: [PATCH] ALSA: hda - Add 3stack-automute model to AD1882 codec
Git-commit: 1c86845268dc91fa6a53de9a4479b407cd4ee903
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
Patch-mainline: 3.7-rc1
References: bnc#775373

Added a simple support of automute for the front HP jack to AD1882
stack model.  Such an addition is basically an exception -- we really
want to avoid the static quirk codes, but AD1882 parser isn't still
ready for moving to the BIOS auto-parser yet.  So, as a quick fix, I
merged it for now.

In near future, we really need the big clean up of patch_analog.c to
move on to the auto-parser...

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 Documentation/sound/alsa/HD-Audio-Models.txt |    3 +-
 sound/pci/hda/patch_analog.c                 |   40 +++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -209,7 +209,8 @@ CMI9880
 
 AD1882 / AD1882A
 ================
-  3stack	3-stack mode (default)
+  3stack	3-stack mode
+  3stack-automute 3-stack with automute front HP (default)
   6stack	6-stack mode
 
 AD1884A / AD1883 / AD1984A / AD1984B
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -4735,6 +4735,32 @@ static const struct snd_kcontrol_new ad1
 	{ } /* end */
 };
 
+/* simple auto-mute control for AD1882 3-stack board */
+#define AD1882_HP_EVENT	0x01
+
+static void ad1882_3stack_automute(struct hda_codec *codec)
+{
+	bool mute = snd_hda_jack_detect(codec, 0x11);
+	snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    mute ? 0 : PIN_OUT);
+}
+
+static int ad1882_3stack_automute_init(struct hda_codec *codec)
+{
+	ad198x_init(codec);
+	ad1882_3stack_automute(codec);
+	return 0;
+}
+
+static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	switch (res >> 26) {
+	case AD1882_HP_EVENT:
+		ad1882_3stack_automute(codec);
+		break;
+	}
+}
+
 static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
 	HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
@@ -4849,6 +4875,11 @@ static const struct hda_verb ad1882_init
 	{ } /* end */
 };
 
+static const struct hda_verb ad1882_3stack_automute_verbs[] = {
+	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT},
+	{ } /* end */
+};
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static const struct hda_amp_list ad1882_loopbacks[] = {
 	{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
@@ -4863,12 +4894,14 @@ static const struct hda_amp_list ad1882_
 enum {
 	AD1882_3STACK,
 	AD1882_6STACK,
+	AD1882_3STACK_AUTOMUTE,
 	AD1882_MODELS
 };
 
 static const char * const ad1882_models[AD1986A_MODELS] = {
 	[AD1882_3STACK]		= "3stack",
 	[AD1882_6STACK]		= "6stack",
+	[AD1882_3STACK_AUTOMUTE] = "3stack-automute",
 };
 
 
@@ -4923,6 +4956,7 @@ static int patch_ad1882(struct hda_codec
 	switch (board_config) {
 	default:
 	case AD1882_3STACK:
+	case AD1882_3STACK_AUTOMUTE:
 		spec->num_mixers = 3;
 		spec->mixers[2] = ad1882_3stack_mixers;
 		spec->channel_mode = ad1882_modes;
@@ -4930,6 +4964,12 @@ static int patch_ad1882(struct hda_codec
 		spec->need_dac_fix = 1;
 		spec->multiout.max_channels = 2;
 		spec->multiout.num_dacs = 1;
+		if (board_config != AD1882_3STACK) {
+			spec->init_verbs[spec->num_init_verbs++] =
+				ad1882_3stack_automute_verbs;
+			codec->patch_ops.unsol_event = ad1882_3stack_unsol_event;
+			codec->patch_ops.init = ad1882_3stack_automute_init;
+		}
 		break;
 	case AD1882_6STACK:
 		spec->num_mixers = 3;
