[ALSA] hda-codec - Fix Gateway laptops with STAC9200
authorTakashi Iwai <tiwai@suse.de>
Wed, 10 Oct 2007 08:04:26 +0000 (10:04 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 16 Oct 2007 14:51:08 +0000 (16:51 +0200)
Fix the output of Gateway laptops with STAC9200 codec chip.
They require the EAPD control for some pins.  These pins shouldn't be
powered down.
To enable EAPD control, a new model 'gateway' was added to STAC9200.
The known PCI SSIDs are included in the quirk list.
The fix was originally suggested by Brian Hinz, in ALSA bug#2948.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Documentation/sound/alsa/ALSA-Configuration.txt
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_sigmatel.c

index 9268925..a035eb6 100644 (file)
@@ -972,6 +972,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          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
index 239cdd8..187533e 100644 (file)
@@ -1630,10 +1630,24 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
 
        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) {
index 27360d2..fe91b9b 100644 (file)
@@ -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_init[] = {
        {}
 };
 
+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_9200_MODELS] = {
        [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_tbl[] = {
                      "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_codec *codec)
        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);