From e86db10a6c3efe1d38a0bee7ff2c3949b69d5d82 Mon Sep 17 00:00:00 2001
From: Michel Pollet <buserror@gmail.com>
Date: Wed, 2 Jun 2010 13:23:59 +0100
Subject: [PATCH 2/2] [joggler] sound fix v3, forward ported

joggler-sound-fix-v2.6.33-v3.patch forward ported to .34

Signed-off-by: Michel Pollet <buserror@gmail.com>
---
 sound/pci/hda/patch_sigmatel.c |  197 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 194 insertions(+), 3 deletions(-)

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a0e06d8..3839294 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -66,6 +66,12 @@ enum {
 };
 
 enum {
+	STAC_9202_REF,
+	STAC_9202_OPENPEAK,
+	STAC_9202_MODELS
+};
+
+enum {
 	STAC_9205_AUTO,
 	STAC_9205_REF,
 	STAC_9205_DELL_M42,
@@ -319,6 +325,22 @@ static hda_nid_t stac9200_dac_nids[1] = {
         0x02,
 };
 
+static hda_nid_t stac9202_adc_nids[1] = {
+	0x03,
+};
+
+static hda_nid_t stac9202_mux_nids[1] = {
+	0x0f,
+};
+
+static hda_nid_t stac9202_dac_nids[1] = {
+	0x02,
+};
+
+static hda_nid_t stac9202_dmic_nids[2] = {
+	0x15, 0
+};
+
 static hda_nid_t stac92hd73xx_pwr_nids[8] = {
 	0x0a, 0x0b, 0x0c, 0xd, 0x0e,
 	0x0f, 0x10, 0x11
@@ -548,6 +570,11 @@ static hda_nid_t stac9200_pin_nids[8] = {
 	0x0f, 0x10, 0x11, 0x12,
 };
 
+static hda_nid_t stac9202_pin_nids[9] = {
+	0x07, 0x08, 0x0a, 0x0d,
+	0x0c, 0x0b, 0x10, 0x11, 0x15,
+};
+
 static hda_nid_t stac925x_pin_nids[8] = {
 	0x07, 0x08, 0x0a, 0x0b, 
 	0x0c, 0x0d, 0x10, 0x11,
@@ -860,6 +887,23 @@ static struct hda_verb stac9200_eapd_init[] = {
 	{}
 };
 
+static struct hda_verb stac9202_ref_init[] = {
+	/* set dac0mux for dac converter */
+	{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{}
+};
+
+static struct hda_verb stac9202_openpeak_init[] = {
+	/* set dac0mux for dac converter */
+	{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{ 0x07, AC_VERB_SET_EAPD_BTLENABLE , 0x02},
+	/* Unmute the Input MUX */
+	{ 0x14, 0x390, 0x00},
+	{ 0x14, 0x3a0, 0x00},
+	{ 0x0F, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00},
+	{}
+};
+
 static struct hda_verb dell_eq_core_init[] = {
 	/* set master volume to max value without distortion
 	 * and direct control */
@@ -991,6 +1035,28 @@ static struct snd_kcontrol_new stac9200_mixer[] = {
 	{ } /* end */
 };
 
+
+static struct snd_kcontrol_new stac9202_ref_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new stac9202_openpeak_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new stac9202_openpeak_mixer_loopback[] = {
+	STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1),
+	{}
+};
+
 static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = {
 	STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3),
 	{}
@@ -1435,6 +1501,35 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
 	{} /* terminator */
 };
 
+static unsigned int openpeak9202_pin_configs[9] = {
+        0x01110014, 0x01410013, 0x02111011, 0x02214012,
+        0x01810022, 0x01a10021, 0x01010031, 0x01310023, 0x01d10024,
+};
+
+static unsigned int ref9202_pin_configs[9] = {
+        0x01c10014, 0x01410013, 0x01210011, 0x01010012,
+        0x01810022, 0x01a10021, 0x01010031, 0x01310023, 0x01d10024,
+};
+
+static unsigned int *stac9202_brd_tbl[STAC_9202_MODELS] = {
+	[STAC_9202_REF] = ref9202_pin_configs,
+	[STAC_9202_OPENPEAK] = openpeak9202_pin_configs,
+};
+
+static const char *stac9202_models[STAC_9202_MODELS] = {
+	[STAC_9202_REF] = "ref",
+	[STAC_9202_OPENPEAK] = "openpeak",
+};
+
+static struct snd_pci_quirk stac9202_cfg_tbl[] = {
+        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
+                      "Stac 9202 Ref Config", STAC_9202_REF),
+        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8119,
+                      "OpenPeak ATOM Frame", STAC_9202_OPENPEAK),
+        {}
+};
+
+
 static unsigned int ref925x_pin_configs[8] = {
 	0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
 	0x90a70320, 0x02214210, 0x01019020, 0x9033032e,
@@ -1516,7 +1611,6 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = {
 	/* SigmaTel reference board */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF),
-	SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),
 
 	/* Default table for unknown ID */
 	SND_PCI_QUIRK(0x1002, 0x437b, "Gateway mobile", STAC_M2_2),
@@ -4579,10 +4673,24 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
 		if (spec->hp_switch)
 			stac92xx_reset_pinctl(codec, spec->hp_switch,
 					      AC_PINCTL_OUT_EN);
+
+		if (spec->board_config == STAC_9202_OPENPEAK)
+		{
+			snd_hda_codec_write(codec, 0x07, 0,AC_VERB_SET_EAPD_BTLENABLE,0x0);
+			spec->gpio_data=1;
+			snd_hda_codec_write_cache(codec, codec->afg, 0,AC_VERB_SET_GPIO_DATA, spec->gpio_data);
+		}
 		for (i = 0; i < cfg->line_outs; i++)
 			stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
 						AC_PINCTL_OUT_EN);
 	} else {
+		if (spec->board_config == STAC_9202_OPENPEAK)
+		{
+			snd_hda_codec_write(codec, 0x07, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x2);
+			spec->gpio_data=0;
+			snd_hda_codec_write_cache(codec, codec->afg, 0,AC_VERB_SET_GPIO_DATA, spec->gpio_data);
+		}
+
 		/* enable lineouts */
 		if (spec->hp_switch)
 			stac92xx_set_pinctl(codec, spec->hp_switch,
@@ -5057,6 +5165,89 @@ static int patch_stac9200(struct hda_codec *codec)
 	return 0;
 }
 
+static int patch_stac9202(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec;
+	int err;
+
+	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->num_pins = ARRAY_SIZE(stac9202_pin_nids);
+	spec->pin_nids = stac9202_pin_nids;
+	spec->board_config = snd_hda_check_board_config(codec, STAC_9202_MODELS,
+							stac9202_models,
+							stac9202_cfg_tbl);
+	if (spec->board_config < 0) {
+		snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+			    codec->chip_name);
+	} else {
+		if (spec->board_config == STAC_9202_OPENPEAK) {
+			unsigned char * baseptr;
+			unsigned char boardrev;
+			baseptr = ioremap(0xFFBC0100, 1);
+			if (baseptr != NULL){
+				boardrev = readb(baseptr);
+				iounmap(baseptr);
+			} else {
+				boardrev = 0x1F;
+			}
+
+			switch (boardrev){
+				/* First revision */
+			case 0x1F:
+				stac9202_brd_tbl[spec->board_config][2]  = 0x01210011;
+				stac9202_brd_tbl[spec->board_config][3]  = 0x01010012;
+				break;
+			default:
+				break;
+			}
+		}
+		stac92xx_set_config_regs(codec,
+					 stac9202_brd_tbl[spec->board_config]);
+	}
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = 1;
+	spec->multiout.dac_nids = stac9202_dac_nids;
+	spec->adc_nids = stac9202_adc_nids;
+	spec->mux_nids = stac9202_mux_nids;
+	spec->num_muxes = 1;
+	spec->num_adcs = 1;
+	switch(spec->board_config) {
+	case STAC_9202_OPENPEAK:
+		spec->num_dmics = 1;
+		spec->dmic_nids = stac9202_dmic_nids;
+		spec->init = stac9202_openpeak_init;
+		spec->mixer = stac9202_openpeak_mixer;
+		spec->aloopback_mask = 0x40;
+		spec->aloopback_shift = 0;
+		spec->aloopback_ctl = stac9202_openpeak_mixer_loopback;
+		spec->eapd_switch = 1;
+		spec->gpio_dir = 0x00000001;
+		spec->gpio_mask = 0x00000001;
+		spec->gpio_data = 0x00000000;
+		break;
+	default:
+		spec->num_dmics = 0;
+		spec->init = stac9202_ref_init;
+		spec->mixer = stac9202_ref_mixer;
+		break;
+	}
+
+	err = stac9200_parse_auto_config(codec);
+	if (err < 0) {
+		stac92xx_free(codec);
+		return err;
+	}
+
+	codec->patch_ops = stac92xx_patch_ops;
+
+	return 0;
+}
+
 static int patch_stac925x(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec;
@@ -6235,8 +6426,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
  	{ .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x },
  	{ .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x },
  	{ .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x },
-	{ .id = 0x83847632, .name = "STAC9202",  .patch = patch_stac925x },
-	{ .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x },
+	{ .id = 0x83847632, .name = "STAC9202",  .patch = patch_stac9202 },
+	{ .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac9202 },
 	{ .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x },
 	{ .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x },
 	{ .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x },
-- 
1.7.1

