From 20f7d928fa6e51ca81648946ead6244c58a0b4c0 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Thu, 16 Feb 2012 12:35:16 +0100
Subject: [PATCH] ALSA: hda/realtek - Replace ALC260 model=replacer with the auto-parser
Git-commit: 20f7d928fa6e51ca81648946ead6244c58a0b4c0
Patch-mainline: 3.4-rc3

The support for Replacer 627V in the auto-parser needs the unique unsol
event handling: although the machine has a single output pin 0x0f, it's
used for both the headphone and the speaker, and the driver needs to
toggle the output route via GPIO 1.

In addition, it needs a special COEF setup with 0x3050.

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

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

--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -30,7 +30,6 @@ ALC880
 ALC260
 ======
   fujitsu	Fujitsu S7020
-  replacer	Replacer 672V
   favorit100	Maxdata Favorit 100XS
   basic		fixed pin assignment (old default model)
   test		for testing/debugging purpose, almost all controls can
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4219,8 +4219,35 @@ enum {
 	ALC260_FIXUP_HP_PIN_0F,
 	ALC260_FIXUP_COEF,
 	ALC260_FIXUP_GPIO1,
+	ALC260_FIXUP_GPIO1_TOGGLE,
+	ALC260_FIXUP_REPLACER,
 };
 
+static void alc260_gpio1_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+			    spec->hp_jack_present);
+}
+
+static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
+				      const struct alc_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	if (action == ALC_FIXUP_ACT_PROBE) {
+		/* although the machine has only one output pin, we need to
+		 * toggle GPIO1 according to the jack state
+		 */
+		spec->automute_hook = alc260_gpio1_automute;
+		spec->detect_hp = 1;
+		spec->automute_speaker = 1;
+		spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
+		snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
+		spec->unsol_event = alc_sku_unsol_event;
+		add_verb(codec->spec, alc_gpio1_init_verbs);
+	}
+}
+
 static const struct alc_fixup alc260_fixups[] = {
 	[ALC260_FIXUP_HP_DC5750] = {
 		.type = ALC_FIXUP_PINS,
@@ -4254,6 +4281,22 @@ static const struct alc_fixup alc260_fix
 		.type = ALC_FIXUP_VERBS,
 		.v.verbs = alc_gpio1_init_verbs,
 	},
+	[ALC260_FIXUP_GPIO1_TOGGLE] = {
+		.type = ALC_FIXUP_FUNC,
+		.v.func = alc260_fixup_gpio1_toggle,
+		.chained = true,
+		.chain_id = ALC260_FIXUP_HP_PIN_0F,
+	},
+	[ALC260_FIXUP_REPLACER] = {
+		.type = ALC_FIXUP_VERBS,
+		.v.verbs = (const struct hda_verb[]) {
+			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+			{ 0x20, AC_VERB_SET_PROC_COEF,  0x3050 },
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
+	},
 };
 
 static const struct snd_pci_quirk alc260_fixup_tbl[] = {
@@ -4261,6 +4304,7 @@ static const struct snd_pci_quirk alc260
 	SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
 	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
 	SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
+	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
 	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
 	{}
 };
