[alsa-devel] [PATCH] stac9200 eapd fixes
Hi,
The following patch addresses alsa bug #0002948 and it's (many) duplicates. Please consider it for inclusion in the next release.
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) { --- 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);
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);
Hi Takashi,
Your updated version works fine with hg clone from tonight.
Thanks, -brian
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
At Tue, 9 Oct 2007 22:18:00 -0400, Brian Hinz wrote:
Hi Takashi,
Your updated version works fine with hg clone from tonight.
Thanks, -brian
Great. I committed the patch right now to HG tree. Thanks for quick reaction!
Takashi
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
participants (2)
-
Brian Hinz
-
Takashi Iwai