[alsa-devel] [PATCH] stac9200 eapd fixes

Takashi Iwai tiwai at suse.de
Tue Oct 9 11:03:07 CEST 2007


At Wed, 26 Sep 2007 21:39:47 -0400,
Brian Hinz wrote:
> 
> Hi,
> 
> The following patch addresses alsa bug #0002948 and it's (many) duplicates.  
> Please consider it for inclusion in the next release.

Thanks for the patch!  It's been a real PITA.

> 
> Thanks,
> -brian
> 
> --- alsa-kernel/pci/hda/hda_codec.c	2007-09-24 21:46:11.000000000 -0400
> +++ alsa-kernel/pci/hda/hda_codec.c	2007-09-24 22:00:15.000000000 -0400
> @@ -1629,11 +1629,30 @@
> 			    power_state);
> 
> 	nid = codec->start_nid;
> +	unsigned int pincap;
> 	for (i = 0; i < codec->num_nodes; i++, nid++) {
> -		if (get_wcaps(codec, nid) & AC_WCAP_POWER)
> -			snd_hda_codec_write(codec, nid, 0,
> +		if (get_wcaps(codec, nid) & AC_WCAP_POWER) {
> +			pincap = snd_hda_param_read(codec, nid,
> +				AC_PAR_PIN_CAP);
> +			/*
> + 			 * don't power down the widget if it controls eapd
> + 			 * and EAPD_BTLENABLE is set.
> + 			 */
> +			if (pincap & AC_PINCAP_EAPD) {
> +				int eapd = snd_hda_codec_read(codec, nid,
> +					0, AC_VERB_GET_EAPD_BTLENABLE, 0);
> +				eapd &= 0x02;
> +				if (power_state != AC_PWRST_D3 || !eapd) {
> +					snd_hda_codec_write(codec, nid, 0,
> +						AC_VERB_SET_POWER_STATE,
> +					    	power_state);
> +				}
> +			} else {
> +				snd_hda_codec_write(codec, nid, 0,
> 					    AC_VERB_SET_POWER_STATE,
> 					    power_state);
> +			}
> +		}
> 	}
> 
> 	if (power_state == AC_PWRST_D0) {

Hm, I'm not 100% sure whether this check is always needed for every
pin with EAPD capability.  But, surely, stopping the power-down
doesn't hurt much but a slight power-loss.  Let's add it.


> --- alsa-kernel/pci/hda/patch_sigmatel.c	2007-09-24 21:46:12.000000000 -0400
> +++ alsa-kernel/pci/hda/patch_sigmatel.c	2007-09-26 20:57:55.000000000 -0400
> @@ -378,6 +378,13 @@
> 	{}
> };
> 
> +static struct hda_verb stac9200_eapd_init[] = {
> +	/* set dac0mux for dac converter */
> +	{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
> +	{ 0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
> +	{}
> +};
> +
> static struct hda_verb stac925x_core_init[] = {
> 	/* set dac0mux for dac converter */
> 	{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
> @@ -2492,7 +2499,23 @@
> 	spec->num_dmics = 0;
> 	spec->num_adcs = 1;
> 
> -	spec->init = stac9200_core_init;
> +	/*
> + 	 * EAPD needs to be set on resume
> + 	 */
> +	switch (codec->subsystem_id) {
> +	case 0x107b0205: /* Gateway S-7110M */
> +		spec->init = stac9200_eapd_init;
> +		break;
> +	case 0x107b0317: /* Gateway MT3423, MX3412, MX3410, MX3414 */
> +		spec->init = stac9200_eapd_init;
> +		break;
> +	case 0x107b0318: /* Gateway ML3109, MT3707 */
> +		spec->init = stac9200_eapd_init;
> +		break;
> +	default:
> +		spec->init = stac9200_core_init;
> +		break;
> +	}
> 	spec->mixer = stac9200_mixer;
> 
> 	err = stac9200_parse_auto_config(codec);

I prefer a new model, e.g. STAC9200_GATEWAY, instead of checking each
SSID there.  Then you'll be able to add a quirk dynamically via model
module option if any model is missing in the table.


Could you check whether the patch below works?  I rewrote
hda_set_power_state() changes slightly, too.  After confirming it
works, I'd love to push it before 1.0.15 release.


thanks,

Takashi

diff -r a4cf3aa3dc5b Documentation/ALSA-Configuration.txt
--- a/Documentation/ALSA-Configuration.txt	Tue Oct 09 10:34:06 2007 +0200
+++ b/Documentation/ALSA-Configuration.txt	Tue Oct 09 11:01:51 2007 +0200
@@ -972,6 +972,7 @@ Prior to version 0.9.0rc4 options had a 
 	  dell-m25	Dell Inspiron E1505n
 	  dell-m26	Dell Inspiron 1501
 	  dell-m27	Dell Inspiron E1705/9400
+	  gateway	Gateway laptops with EAPD control
 
 	STAC9205/9254
 	  ref		Reference board
diff -r a4cf3aa3dc5b pci/hda/hda_codec.c
--- a/pci/hda/hda_codec.c	Tue Oct 09 10:34:06 2007 +0200
+++ b/pci/hda/hda_codec.c	Tue Oct 09 11:01:51 2007 +0200
@@ -1630,10 +1630,24 @@ static void hda_set_power_state(struct h
 
 	nid = codec->start_nid;
 	for (i = 0; i < codec->num_nodes; i++, nid++) {
-		if (get_wcaps(codec, nid) & AC_WCAP_POWER)
+		if (get_wcaps(codec, nid) & AC_WCAP_POWER) {
+			unsigned int pincap;
+			/*
+			 * don't power down the widget if it controls eapd
+ 			 * and EAPD_BTLENABLE is set.
+ 			 */
+			pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (pincap & AC_PINCAP_EAPD) {
+				int eapd = snd_hda_codec_read(codec, nid,
+					0, AC_VERB_GET_EAPD_BTLENABLE, 0);
+				eapd &= 0x02;
+				if (power_state == AC_PWRST_D3 && eapd)
+					continue;
+			}
 			snd_hda_codec_write(codec, nid, 0,
 					    AC_VERB_SET_POWER_STATE,
 					    power_state);
+		}
 	}
 
 	if (power_state == AC_PWRST_D0) {
diff -r a4cf3aa3dc5b pci/hda/patch_sigmatel.c
--- a/pci/hda/patch_sigmatel.c	Tue Oct 09 10:34:06 2007 +0200
+++ b/pci/hda/patch_sigmatel.c	Tue Oct 09 11:01:51 2007 +0200
@@ -49,6 +49,7 @@ enum {
 	STAC_9200_DELL_M25,
 	STAC_9200_DELL_M26,
 	STAC_9200_DELL_M27,
+	STAC_9200_GATEWAY,
 	STAC_9200_MODELS
 };
 
@@ -378,6 +379,13 @@ static struct hda_verb stac9200_core_ini
 	{}
 };
 
+static struct hda_verb stac9200_eapd_init[] = {
+	/* set dac0mux for dac converter */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	{}
+};
+
 static struct hda_verb stac925x_core_init[] = {
 	/* set dac0mux for dac converter */
 	{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -693,6 +701,7 @@ static const char *stac9200_models[STAC_
 	[STAC_9200_DELL_M25] = "dell-m25",
 	[STAC_9200_DELL_M26] = "dell-m26",
 	[STAC_9200_DELL_M27] = "dell-m27",
+	[STAC_9200_GATEWAY] = "gateway",
 };
 
 static struct snd_pci_quirk stac9200_cfg_tbl[] = {
@@ -760,7 +769,12 @@ static struct snd_pci_quirk stac9200_cfg
 		      "unknown Dell", STAC_9200_DELL_M26),
 	/* Panasonic */
 	SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
-
+	/* Gateway machines needs EAPD to be set on resume */
+	SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY),
+	SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*",
+		      STAC_9200_GATEWAY),
+	SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707",
+		      STAC_9200_GATEWAY),
 	{} /* terminator */
 };
 
@@ -2492,7 +2506,10 @@ static int patch_stac9200(struct hda_cod
 	spec->num_dmics = 0;
 	spec->num_adcs = 1;
 
-	spec->init = stac9200_core_init;
+	if (spec->board_config == STAC_9200_GATEWAY)
+		spec->init = stac9200_eapd_init;
+	else
+		spec->init = stac9200_core_init;
 	spec->mixer = stac9200_mixer;
 
 	err = stac9200_parse_auto_config(codec);


More information about the Alsa-devel mailing list