ALSA: hda - Fix coding style issues in last two patches
[pandora-kernel.git] / sound / pci / hda / patch_sigmatel.c
index a7df81e..72c87aa 100644 (file)
@@ -43,6 +43,7 @@ enum {
 };
 
 enum {
+       STAC_AUTO,
        STAC_REF,
        STAC_9200_OQO,
        STAC_9200_DELL_D21,
@@ -62,6 +63,7 @@ enum {
 };
 
 enum {
+       STAC_9205_AUTO,
        STAC_9205_REF,
        STAC_9205_DELL_M42,
        STAC_9205_DELL_M43,
@@ -71,6 +73,7 @@ enum {
 };
 
 enum {
+       STAC_92HD73XX_AUTO,
        STAC_92HD73XX_NO_JD, /* no jack-detection */
        STAC_92HD73XX_REF,
        STAC_DELL_M6_AMIC,
@@ -81,22 +84,27 @@ enum {
 };
 
 enum {
+       STAC_92HD83XXX_AUTO,
        STAC_92HD83XXX_REF,
        STAC_92HD83XXX_PWR_REF,
+       STAC_DELL_S14,
        STAC_92HD83XXX_MODELS
 };
 
 enum {
+       STAC_92HD71BXX_AUTO,
        STAC_92HD71BXX_REF,
        STAC_DELL_M4_1,
        STAC_DELL_M4_2,
        STAC_DELL_M4_3,
        STAC_HP_M4,
        STAC_HP_DV5,
+       STAC_HP_HDX,
        STAC_92HD71BXX_MODELS
 };
 
 enum {
+       STAC_925x_AUTO,
        STAC_925x_REF,
        STAC_M1,
        STAC_M1_2,
@@ -109,6 +117,7 @@ enum {
 };
 
 enum {
+       STAC_922X_AUTO,
        STAC_D945_REF,
        STAC_D945GTP3,
        STAC_D945GTP5,
@@ -136,6 +145,7 @@ enum {
 };
 
 enum {
+       STAC_927X_AUTO,
        STAC_D965_REF_NO_JD, /* no jack-detection */
        STAC_D965_REF,
        STAC_D965_3ST,
@@ -181,6 +191,7 @@ struct sigmatel_spec {
        unsigned int stream_delay;
 
        /* analog loopback */
+       struct snd_kcontrol_new *aloopback_ctl;
        unsigned char aloopback_mask;
        unsigned char aloopback_shift;
 
@@ -228,7 +239,6 @@ struct sigmatel_spec {
        /* pin widgets */
        hda_nid_t *pin_nids;
        unsigned int num_pins;
-       unsigned int *pin_configs;
 
        /* codec specific stuff */
        struct hda_verb *init;
@@ -404,6 +414,10 @@ static hda_nid_t stac922x_mux_nids[2] = {
         0x12, 0x13,
 };
 
+static hda_nid_t stac927x_slave_dig_outs[2] = {
+       0x1f, 0,
+};
+
 static hda_nid_t stac927x_adc_nids[3] = {
         0x07, 0x08, 0x09
 };
@@ -476,15 +490,21 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = {
        0x14, 0x22, 0x23
 };
 
-static hda_nid_t stac92hd83xxx_pin_nids[14] = {
+static hda_nid_t stac92hd83xxx_pin_nids[10] = {
        0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
-       0x0f, 0x10, 0x11, 0x12, 0x13,
-       0x1d, 0x1e, 0x1f, 0x20
+       0x0f, 0x10, 0x11, 0x1f, 0x20,
 };
-static hda_nid_t stac92hd71bxx_pin_nids[11] = {
+
+#define STAC92HD71BXX_NUM_PINS 13
+static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
+       0x0a, 0x0b, 0x0c, 0x0d, 0x00,
+       0x00, 0x14, 0x18, 0x19, 0x1e,
+       0x1f, 0x20, 0x27
+};
+static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = {
        0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
        0x0f, 0x14, 0x18, 0x19, 0x1e,
-       0x1f,
+       0x1f, 0x20, 0x27
 };
 
 static hda_nid_t stac927x_pin_nids[14] = {
@@ -846,9 +866,9 @@ static struct hda_verb stac92hd73xx_10ch_core_init[] = {
 };
 
 static struct hda_verb stac92hd83xxx_core_init[] = {
-       { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0},
-       { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0},
-       { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1},
+       { 0xa, AC_VERB_SET_CONNECT_SEL, 0x1},
+       { 0xb, AC_VERB_SET_CONNECT_SEL, 0x1},
+       { 0xd, AC_VERB_SET_CONNECT_SEL, 0x0},
 
        /* power state controls amps */
        { 0x01, AC_VERB_SET_EAPD, 1 << 2},
@@ -995,8 +1015,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
        HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT),
        HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT),
 
-       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3),
-
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 
@@ -1006,9 +1024,22 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
        { } /* end */
 };
 
-static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
+static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = {
+       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3),
+       {}
+};
+
+static struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = {
        STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4),
+       {}
+};
 
+static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = {
+       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5),
+       {}
+};
+
+static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 
@@ -1033,8 +1064,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
 };
 
 static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {
-       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5),
-
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
 
@@ -1086,8 +1115,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
 };
 
 static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
-       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
-
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 
@@ -1113,9 +1140,11 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
        { } /* end */
 };
 
-static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
-       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
+static struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
+       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2)
+};
 
+static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
 
@@ -1133,8 +1162,6 @@ static struct snd_kcontrol_new stac925x_mixer[] = {
 };
 
 static struct snd_kcontrol_new stac9205_mixer[] = {
-       STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1),
-
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
 
@@ -1143,6 +1170,11 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new stac9205_loopback[] = {
+       STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1),
+       {}
+};
+
 /* This needs to be generated dynamically based on sequence */
 static struct snd_kcontrol_new stac922x_mixer[] = {
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
@@ -1155,8 +1187,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
 
 
 static struct snd_kcontrol_new stac927x_mixer[] = {
-       STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
-
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT),
 
@@ -1168,6 +1198,11 @@ static struct snd_kcontrol_new stac927x_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new stac927x_loopback[] = {
+       STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
+       {}
+};
+
 static struct snd_kcontrol_new stac_dmux_mixer = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Digital Input Source",
@@ -1193,10 +1228,7 @@ static const char *slave_vols[] = {
        "LFE Playback Volume",
        "Side Playback Volume",
        "Headphone Playback Volume",
-       "Headphone Playback Volume",
        "Speaker Playback Volume",
-       "External Speaker Playback Volume",
-       "Speaker2 Playback Volume",
        NULL
 };
 
@@ -1207,10 +1239,7 @@ static const char *slave_sws[] = {
        "LFE Playback Switch",
        "Side Playback Switch",
        "Headphone Playback Switch",
-       "Headphone Playback Switch",
        "Speaker Playback Switch",
-       "External Speaker Playback Switch",
-       "Speaker2 Playback Switch",
        "IEC958 Playback Switch",
        NULL
 };
@@ -1294,6 +1323,13 @@ static int stac92xx_build_controls(struct hda_codec *codec)
                        return err;
        }
 
+       if (spec->aloopback_ctl &&
+           snd_hda_get_bool_hint(codec, "loopback") == 1) {
+               err = snd_hda_add_new_ctls(codec, spec->aloopback_ctl);
+               if (err < 0)
+                       return err;
+       }
+
        stac92xx_free_kctls(codec); /* no longer needed */
 
        /* create jack input elements */
@@ -1478,6 +1514,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
 };
 
 static const char *stac9200_models[STAC_9200_MODELS] = {
+       [STAC_AUTO] = "auto",
        [STAC_REF] = "ref",
        [STAC_9200_OQO] = "oqo",
        [STAC_9200_DELL_D21] = "dell-d21",
@@ -1623,6 +1660,7 @@ static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
 };
 
 static const char *stac925x_models[STAC_925x_MODELS] = {
+       [STAC_925x_AUTO] = "auto",
        [STAC_REF] = "ref",
        [STAC_M1] = "m1",
        [STAC_M1_2] = "m1-2",
@@ -1682,6 +1720,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
+       [STAC_92HD73XX_AUTO] = "auto",
        [STAC_92HD73XX_NO_JD] = "no-jd",
        [STAC_92HD73XX_REF] = "ref",
        [STAC_DELL_M6_AMIC] = "dell-m6-amic",
@@ -1719,21 +1758,29 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
        {} /* terminator */
 };
 
-static unsigned int ref92hd83xxx_pin_configs[14] = {
+static unsigned int ref92hd83xxx_pin_configs[10] = {
        0x02214030, 0x02211010, 0x02a19020, 0x02170130,
        0x01014050, 0x01819040, 0x01014020, 0x90a3014e,
-       0x40f000f0, 0x40f000f0, 0x40f000f0, 0x40f000f0,
        0x01451160, 0x98560170,
 };
 
+static unsigned int dell_s14_pin_configs[10] = {
+       0x02214030, 0x02211010, 0x02a19020, 0x01014050,
+       0x40f000f0, 0x01819040, 0x40f000f0, 0x90a60160,
+       0x40f000f0, 0x40f000f0,
+};
+
 static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
        [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
        [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
+       [STAC_DELL_S14] = dell_s14_pin_configs,
 };
 
 static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
+       [STAC_92HD83XXX_AUTO] = "auto",
        [STAC_92HD83XXX_REF] = "ref",
        [STAC_92HD83XXX_PWR_REF] = "mic-ref",
+       [STAC_DELL_S14] = "dell-s14",
 };
 
 static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1742,31 +1789,37 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                      "DFI LanParty", STAC_92HD83XXX_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
                      "DFI LanParty", STAC_92HD83XXX_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
+                     "unknown Dell", STAC_DELL_S14),
        {} /* terminator */
 };
 
-static unsigned int ref92hd71bxx_pin_configs[11] = {
+static unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = {
        0x02214030, 0x02a19040, 0x01a19020, 0x01014010,
        0x0181302e, 0x01014010, 0x01019020, 0x90a000f0,
-       0x90a000f0, 0x01452050, 0x01452050,
+       0x90a000f0, 0x01452050, 0x01452050, 0x00000000,
+       0x00000000
 };
 
-static unsigned int dell_m4_1_pin_configs[11] = {
+static unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = {
        0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
        0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
-       0x40f000f0, 0x4f0000f0, 0x4f0000f0,
+       0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000,
+       0x00000000
 };
 
-static unsigned int dell_m4_2_pin_configs[11] = {
+static unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = {
        0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
        0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
-       0x40f000f0, 0x044413b0, 0x044413b0,
+       0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000,
+       0x00000000
 };
 
-static unsigned int dell_m4_3_pin_configs[11] = {
+static unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = {
        0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
        0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0,
-       0x40f000f0, 0x044413b0, 0x044413b0,
+       0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000,
+       0x00000000
 };
 
 static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
@@ -1776,15 +1829,18 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
        [STAC_DELL_M4_3]        = dell_m4_3_pin_configs,
        [STAC_HP_M4]            = NULL,
        [STAC_HP_DV5]           = NULL,
+       [STAC_HP_HDX]           = NULL,
 };
 
 static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
+       [STAC_92HD71BXX_AUTO] = "auto",
        [STAC_92HD71BXX_REF] = "ref",
        [STAC_DELL_M4_1] = "dell-m4-1",
        [STAC_DELL_M4_2] = "dell-m4-2",
        [STAC_DELL_M4_3] = "dell-m4-3",
        [STAC_HP_M4] = "hp-m4",
        [STAC_HP_DV5] = "hp-dv5",
+       [STAC_HP_HDX] = "hp-hdx",
 };
 
 static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
@@ -1793,20 +1849,16 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
                      "DFI LanParty", STAC_92HD71BXX_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
                      "DFI LanParty", STAC_92HD71BXX_REF),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2,
-                     "HP dv5", STAC_HP_M4),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4,
-                     "HP dv7", STAC_HP_M4),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f7,
-                     "HP dv4", STAC_HP_DV5),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc,
-                     "HP dv7", STAC_HP_M4),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600,
-                     "HP dv5", STAC_HP_DV5),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603,
-                     "HP dv5", STAC_HP_DV5),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0,
+                     "HP dv4-7", STAC_HP_DV5),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600,
+                     "HP dv4-7", STAC_HP_DV5),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610,
+                     "HP HDX", STAC_HP_HDX),  /* HDX18 */
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a,
-                               "unknown HP", STAC_HP_M4),
+                     "HP mini 1000", STAC_HP_M4),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b,
+                     "HP HDX", STAC_HP_HDX),  /* HDX16 */
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
                                "unknown Dell", STAC_DELL_M4_1),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
@@ -1958,6 +2010,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
 };
 
 static const char *stac922x_models[STAC_922X_MODELS] = {
+       [STAC_922X_AUTO] = "auto",
        [STAC_D945_REF] = "ref",
        [STAC_D945GTP5] = "5stack",
        [STAC_D945GTP3] = "3stack",
@@ -2067,31 +2120,7 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7,
                      "Dell XPS M1210", STAC_922X_DELL_M82),
        /* ECS/PC Chips boards */
-       SND_PCI_QUIRK(0x1019, 0x2144,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2608,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2633,
-                     "ECS/PC chips P17G/1333", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2811,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2812,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2813,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2814,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2815,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2816,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2817,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2818,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2819,
-                     "ECS/PC chips", STAC_ECS_202),
-       SND_PCI_QUIRK(0x1019, 0x2820,
+       SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000,
                      "ECS/PC chips", STAC_ECS_202),
        {} /* terminator */
 };
@@ -2134,6 +2163,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
 };
 
 static const char *stac927x_models[STAC_927X_MODELS] = {
+       [STAC_927X_AUTO]        = "auto",
        [STAC_D965_REF_NO_JD]   = "ref-no-jd",
        [STAC_D965_REF]         = "ref",
        [STAC_D965_3ST]         = "3stack",
@@ -2152,22 +2182,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST),
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST),
        /* 965 based 3 stack systems */
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100,
+                          "Intel D965", STAC_D965_3ST),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000,
+                          "Intel D965", STAC_D965_3ST),
        /* Dell 3 stack systems */
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_3ST),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
@@ -2183,15 +2201,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x02ff, "Dell     ", STAC_DELL_BIOS),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0209, "Dell XPS 1330", STAC_DELL_BIOS),
        /* 965 based 5 stack systems */
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300,
+                          "Intel D965", STAC_D965_5ST),
+       SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500,
+                          "Intel D965", STAC_D965_5ST),
        {} /* terminator */
 };
 
@@ -2248,6 +2261,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
 };
 
 static const char *stac9205_models[STAC_9205_MODELS] = {
+       [STAC_9205_AUTO] = "auto",
        [STAC_9205_REF] = "ref",
        [STAC_9205_DELL_M42] = "dell-m42",
        [STAC_9205_DELL_M43] = "dell-m43",
@@ -2297,98 +2311,19 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
        {} /* terminator */
 };
 
-static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
-{
-       int i;
-       struct sigmatel_spec *spec = codec->spec;
-       
-       kfree(spec->pin_configs);
-       spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs),
-                                   GFP_KERNEL);
-       if (!spec->pin_configs)
-               return -ENOMEM;
-       
-       for (i = 0; i < spec->num_pins; i++) {
-               hda_nid_t nid = spec->pin_nids[i];
-               unsigned int pin_cfg;
-               
-               pin_cfg = snd_hda_codec_read(codec, nid, 0, 
-                       AC_VERB_GET_CONFIG_DEFAULT, 0x00);      
-               snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",
-                                       nid, pin_cfg);
-               spec->pin_configs[i] = pin_cfg;
-       }
-       
-       return 0;
-}
-
-static void stac92xx_set_config_reg(struct hda_codec *codec,
-                                   hda_nid_t pin_nid, unsigned int pin_config)
-{
-       int i;
-       snd_hda_codec_write(codec, pin_nid, 0,
-                           AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
-                           pin_config & 0x000000ff);
-       snd_hda_codec_write(codec, pin_nid, 0,
-                           AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
-                           (pin_config & 0x0000ff00) >> 8);
-       snd_hda_codec_write(codec, pin_nid, 0,
-                           AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
-                           (pin_config & 0x00ff0000) >> 16);
-       snd_hda_codec_write(codec, pin_nid, 0,
-                           AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
-                           pin_config >> 24);
-       i = snd_hda_codec_read(codec, pin_nid, 0,
-                              AC_VERB_GET_CONFIG_DEFAULT,
-                              0x00);   
-       snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n",
-                   pin_nid, i);
-}
-
-static void stac92xx_set_config_regs(struct hda_codec *codec)
+static void stac92xx_set_config_regs(struct hda_codec *codec,
+                                    unsigned int *pincfgs)
 {
        int i;
        struct sigmatel_spec *spec = codec->spec;
 
-       if (!spec->pin_configs)
-               return;
+       if (!pincfgs)
+               return;
 
        for (i = 0; i < spec->num_pins; i++)
-               stac92xx_set_config_reg(codec, spec->pin_nids[i],
-                                       spec->pin_configs[i]);
-}
-
-static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins)
-{
-       struct sigmatel_spec *spec = codec->spec;
-
-       if (!pins)
-               return stac92xx_save_bios_config_regs(codec);
-
-       kfree(spec->pin_configs);
-       spec->pin_configs = kmemdup(pins,
-                                   spec->num_pins * sizeof(*pins),
-                                   GFP_KERNEL);
-       if (!spec->pin_configs)
-               return -ENOMEM;
-
-       stac92xx_set_config_regs(codec);
-       return 0;
-}
-
-static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid,
-                                  unsigned int cfg)
-{
-       struct sigmatel_spec *spec = codec->spec;
-       int i;
-
-       for (i = 0; i < spec->num_pins; i++) {
-               if (spec->pin_nids[i] == nid) {
-                       spec->pin_configs[i] = cfg;
-                       stac92xx_set_config_reg(codec, nid, cfg);
-                       break;
-               }
-       }
+               if (spec->pin_nids[i] && pincfgs[i])
+                       snd_hda_codec_set_pincfg(codec, spec->pin_nids[i],
+                                                pincfgs[i]);
 }
 
 /*
@@ -2453,6 +2388,14 @@ static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
                                             stream_tag, format, substream);
 }
 
+static int stac92xx_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       struct snd_pcm_substream *substream)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
+}
+
 
 /*
  * Analog capture callbacks
@@ -2497,7 +2440,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
        .ops = {
                .open = stac92xx_dig_playback_pcm_open,
                .close = stac92xx_dig_playback_pcm_close,
-               .prepare = stac92xx_dig_playback_pcm_prepare
+               .prepare = stac92xx_dig_playback_pcm_prepare,
+               .cleanup = stac92xx_dig_playback_pcm_cleanup
        },
 };
 
@@ -2569,7 +2513,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
                codec->num_pcms++;
                info++;
                info->name = "STAC92xx Digital";
-               info->pcm_type = spec->autocfg.dig_out_type;
+               info->pcm_type = spec->autocfg.dig_out_type[0];
                if (spec->multiout.dig_out_nid) {
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
                        info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
@@ -2866,8 +2810,7 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
        mic_pin = AUTO_PIN_MIC;
        for (;;) {
                hda_nid_t nid = cfg->input_pins[mic_pin];
-               def_conf = snd_hda_codec_read(codec, nid, 0,
-                                             AC_VERB_GET_CONFIG_DEFAULT, 0);
+               def_conf = snd_hda_codec_get_pincfg(codec, nid);
                /* some laptops have an internal analog microphone
                 * which can't be used as a output */
                if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
@@ -2935,6 +2878,16 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
                        return conn[j];
                }
        }
+       /* if all DACs are already assigned, connect to the primary DAC */
+       if (conn_len > 1) {
+               for (j = 0; j < conn_len; j++) {
+                       if (conn[j] == spec->multiout.dac_nids[0]) {
+                               snd_hda_codec_write_cache(codec, nid, 0,
+                                                 AC_VERB_SET_CONNECT_SEL, j);
+                               break;
+                       }
+               }
+       }
        return 0;
 }
 
@@ -2975,6 +2928,26 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
                add_spec_dacs(spec, dac);
        }
 
+       for (i = 0; i < cfg->hp_outs; i++) {
+               nid = cfg->hp_pins[i];
+               dac = get_unassigned_dac(codec, nid);
+               if (dac) {
+                       if (!spec->multiout.hp_nid)
+                               spec->multiout.hp_nid = dac;
+                       else
+                               add_spec_extra_dacs(spec, dac);
+               }
+               spec->hp_dacs[i] = dac;
+       }
+
+       for (i = 0; i < cfg->speaker_outs; i++) {
+               nid = cfg->speaker_pins[i];
+               dac = get_unassigned_dac(codec, nid);
+               if (dac)
+                       add_spec_extra_dacs(spec, dac);
+               spec->speaker_dacs[i] = dac;
+       }
+
        /* add line-in as output */
        nid = check_line_out_switch(codec);
        if (nid) {
@@ -3002,26 +2975,6 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
                }
        }
 
-       for (i = 0; i < cfg->hp_outs; i++) {
-               nid = cfg->hp_pins[i];
-               dac = get_unassigned_dac(codec, nid);
-               if (dac) {
-                       if (!spec->multiout.hp_nid)
-                               spec->multiout.hp_nid = dac;
-                       else
-                               add_spec_extra_dacs(spec, dac);
-               }
-               spec->hp_dacs[i] = dac;
-       }
-
-       for (i = 0; i < cfg->speaker_outs; i++) {
-               nid = cfg->speaker_pins[i];
-               dac = get_unassigned_dac(codec, nid);
-               if (dac)
-                       add_spec_extra_dacs(spec, dac);
-               spec->speaker_dacs[i] = dac;
-       }
-
        snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
                   spec->multiout.num_dacs,
                   spec->multiout.dac_nids[0],
@@ -3034,8 +2987,8 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
 }
 
 /* create volume control/switch for the given prefx type */
-static int create_controls(struct hda_codec *codec, const char *pfx,
-                          hda_nid_t nid, int chs)
+static int create_controls_idx(struct hda_codec *codec, const char *pfx,
+                              int idx, hda_nid_t nid, int chs)
 {
        struct sigmatel_spec *spec = codec->spec;
        char name[32];
@@ -3059,19 +3012,22 @@ static int create_controls(struct hda_codec *codec, const char *pfx,
        }
 
        sprintf(name, "%s Playback Volume", pfx);
-       err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
+       err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, idx, name,
                HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT,
                                        spec->volume_offset));
        if (err < 0)
                return err;
        sprintf(name, "%s Playback Switch", pfx);
-       err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name,
+       err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_MUTE, idx, name,
                                   HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
        if (err < 0)
                return err;
        return 0;
 }
 
+#define create_controls(codec, pfx, nid, chs) \
+       create_controls_idx(codec, pfx, 0, nid, chs)
+
 static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
 {
        if (spec->multiout.num_dacs > 4) {
@@ -3097,35 +3053,27 @@ static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
        return 1;
 }
 
-static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid)
-{
-       int i;
-
-       if (spec->autocfg.line_outs != 1)
-               return 0;
-       if (spec->multiout.hp_nid == nid)
-               return 0;
-       for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
-               if (spec->multiout.extra_out_nid[i] == nid)
-                       return 0;
-       return 1;
-}
-
-/* add playback controls from the parsed DAC table */
-static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
-                                              const struct auto_pin_cfg *cfg)
+/* Create output controls
+ * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT)
+ */
+static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
+                                const hda_nid_t *pins,
+                                const hda_nid_t *dac_nids,
+                                int type)
 {
        struct sigmatel_spec *spec = codec->spec;
        static const char *chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
-       hda_nid_t nid = 0;
+       hda_nid_t nid;
        int i, err;
        unsigned int wid_caps;
 
-       for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) {
-               nid = spec->multiout.dac_nids[i];
-               if (i == 2) {
+       for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
+               nid = dac_nids[i];
+               if (!nid)
+                       continue;
+               if (type != AUTO_PIN_HP_OUT && i == 2) {
                        /* Center/LFE */
                        err = create_controls(codec, "Center", nid, 1);
                        if (err < 0)
@@ -3146,23 +3094,47 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
                        }
 
                } else {
-                       const char *name = chname[i];
-                       /* if it's a single DAC, assign a better name */
-                       if (!i && is_unique_dac(spec, nid)) {
-                               switch (cfg->line_out_type) {
-                               case AUTO_PIN_HP_OUT:
-                                       name = "Headphone";
-                                       break;
-                               case AUTO_PIN_SPEAKER_OUT:
-                                       name = "Speaker";
-                                       break;
-                               }
+                       const char *name;
+                       int idx;
+                       switch (type) {
+                       case AUTO_PIN_HP_OUT:
+                               name = "Headphone";
+                               idx = i;
+                               break;
+                       case AUTO_PIN_SPEAKER_OUT:
+                               name = "Speaker";
+                               idx = i;
+                               break;
+                       default:
+                               name = chname[i];
+                               idx = 0;
+                               break;
                        }
-                       err = create_controls(codec, name, nid, 3);
+                       err = create_controls_idx(codec, name, idx, nid, 3);
                        if (err < 0)
                                return err;
+                       if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
+                               wid_caps = get_wcaps(codec, pins[i]);
+                               if (wid_caps & AC_WCAP_UNSOL_CAP)
+                                       spec->hp_detect = 1;
+                       }
                }
        }
+       return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
+                                              const struct auto_pin_cfg *cfg)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int err;
+
+       err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
+                                   spec->multiout.dac_nids,
+                                   cfg->line_out_type);
+       if (err < 0)
+               return err;
 
        if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
                err = stac92xx_add_control(spec,
@@ -3197,40 +3169,18 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
                                        struct auto_pin_cfg *cfg)
 {
        struct sigmatel_spec *spec = codec->spec;
-       hda_nid_t nid;
-       int i, err, nums;
+       int err;
+
+       err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins,
+                                   spec->hp_dacs, AUTO_PIN_HP_OUT);
+       if (err < 0)
+               return err;
+
+       err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins,
+                                   spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT);
+       if (err < 0)
+               return err;
 
-       nums = 0;
-       for (i = 0; i < cfg->hp_outs; i++) {
-               static const char *pfxs[] = {
-                       "Headphone", "Headphone2", "Headphone3",
-               };
-               unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
-               if (wid_caps & AC_WCAP_UNSOL_CAP)
-                       spec->hp_detect = 1;
-               if (nums >= ARRAY_SIZE(pfxs))
-                       continue;
-               nid = spec->hp_dacs[i];
-               if (!nid)
-                       continue;
-               err = create_controls(codec, pfxs[nums++], nid, 3);
-               if (err < 0)
-                       return err;
-       }
-       nums = 0;
-       for (i = 0; i < cfg->speaker_outs; i++) {
-               static const char *pfxs[] = {
-                       "Speaker", "External Speaker", "Speaker2",
-               };
-               if (nums >= ARRAY_SIZE(pfxs))
-                       continue;
-               nid = spec->speaker_dacs[i];
-               if (!nid)
-                       continue;
-               err = create_controls(codec, pfxs[nums++], nid, 3);
-               if (err < 0)
-                       return err;
-       }
        return 0;
 }
 
@@ -3439,11 +3389,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                unsigned int wcaps;
                unsigned int def_conf;
 
-               def_conf = snd_hda_codec_read(codec,
-                                             spec->dmic_nids[i],
-                                             0,
-                                             AC_VERB_GET_CONFIG_DEFAULT,
-                                             0);
+               def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]);
                if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
                        continue;
 
@@ -3567,6 +3513,7 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec)
 static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
 {
        struct sigmatel_spec *spec = codec->spec;
+       int hp_swap = 0;
        int err;
 
        if ((err = snd_hda_parse_pin_def_config(codec,
@@ -3594,6 +3541,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
                spec->autocfg.line_outs = spec->autocfg.hp_outs;
                spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
                spec->autocfg.hp_outs = 0;
+               hp_swap = 1;
        }
        if (spec->autocfg.mono_out_pin) {
                int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
@@ -3687,12 +3635,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
 #endif
 
        err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
-
        if (err < 0)
                return err;
 
-       err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
+       /* All output parsing done, now restore the swapped hp pins */
+       if (hp_swap) {
+               memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
+                      sizeof(spec->autocfg.hp_pins));
+               spec->autocfg.hp_outs = spec->autocfg.line_outs;
+               spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
+               spec->autocfg.line_outs = 0;
+       }
 
+       err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -3729,7 +3684,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
        if (spec->multiout.max_channels > 2)
                spec->surr_switch = 1;
 
-       if (spec->autocfg.dig_out_pin)
+       if (spec->autocfg.dig_outs)
                spec->multiout.dig_out_nid = dig_out;
        if (dig_in && spec->autocfg.dig_in_pin)
                spec->dig_in_nid = dig_in;
@@ -3792,9 +3747,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
                for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
                        hda_nid_t pin = spec->autocfg.line_out_pins[i];
                        unsigned int defcfg;
-                       defcfg = snd_hda_codec_read(codec, pin, 0,
-                                                AC_VERB_GET_CONFIG_DEFAULT,
-                                                0x00);
+                       defcfg = snd_hda_codec_get_pincfg(codec, pin);
                        if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
                                unsigned int wcaps = get_wcaps(codec, pin);
                                wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
@@ -3842,7 +3795,7 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
        if (err < 0)
                return err;
 
-       if (spec->autocfg.dig_out_pin)
+       if (spec->autocfg.dig_outs)
                spec->multiout.dig_out_nid = 0x05;
        if (spec->autocfg.dig_in_pin)
                spec->dig_in_nid = 0x04;
@@ -3898,8 +3851,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
 #ifdef CONFIG_SND_JACK
        struct sigmatel_spec *spec = codec->spec;
        struct sigmatel_jack *jack;
-       int def_conf = snd_hda_codec_read(codec, nid,
-                       0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+       int def_conf = snd_hda_codec_get_pincfg(codec, nid);
        int connectivity = get_defcfg_connect(def_conf);
        char name[32];
 
@@ -4014,6 +3966,36 @@ static void stac92xx_power_down(struct hda_codec *codec)
 static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
                                  int enable);
 
+/* override some hints from the hwdep entry */
+static void stac_store_hints(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       const char *p;
+       int val;
+
+       val = snd_hda_get_bool_hint(codec, "hp_detect");
+       if (val >= 0)
+               spec->hp_detect = val;
+       p = snd_hda_get_hint(codec, "gpio_mask");
+       if (p) {
+               spec->gpio_mask = simple_strtoul(p, NULL, 0);
+               spec->eapd_mask = spec->gpio_dir = spec->gpio_data =
+                       spec->gpio_mask;
+       }
+       p = snd_hda_get_hint(codec, "gpio_dir");
+       if (p)
+               spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
+       p = snd_hda_get_hint(codec, "gpio_data");
+       if (p)
+               spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
+       p = snd_hda_get_hint(codec, "eapd_mask");
+       if (p)
+               spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask;
+       val = snd_hda_get_bool_hint(codec, "eapd_switch");
+       if (val >= 0)
+               spec->eapd_switch = val;
+}
+
 static int stac92xx_init(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -4030,6 +4012,9 @@ static int stac92xx_init(struct hda_codec *codec)
                                spec->adc_nids[i], 0,
                                AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
 
+       /* override some hints */
+       stac_store_hints(codec);
+
        /* set up GPIO */
        gpio = spec->gpio_data;
        /* turn on EAPD statically when spec->eapd_switch isn't set.
@@ -4079,8 +4064,7 @@ static int stac92xx_init(struct hda_codec *codec)
                                                                 pinctl);
                                }
                        }
-                       conf = snd_hda_codec_read(codec, nid, 0,
-                                             AC_VERB_GET_CONFIG_DEFAULT, 0);
+                       conf = snd_hda_codec_get_pincfg(codec, nid);
                        if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
                                enable_pin_detect(codec, nid,
                                                  STAC_INSERT_EVENT);
@@ -4092,8 +4076,8 @@ static int stac92xx_init(struct hda_codec *codec)
        for (i = 0; i < spec->num_dmics; i++)
                stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
                                        AC_PINCTL_IN_EN);
-       if (cfg->dig_out_pin)
-               stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
+       if (cfg->dig_out_pins[0])
+               stac92xx_auto_set_pinctl(codec, cfg->dig_out_pins[0],
                                         AC_PINCTL_OUT_EN);
        if (cfg->dig_in_pin)
                stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
@@ -4121,8 +4105,7 @@ static int stac92xx_init(struct hda_codec *codec)
                        stac_toggle_power_map(codec, nid, 1);
                        continue;
                }
-               def_conf = snd_hda_codec_read(codec, nid, 0,
-                                             AC_VERB_GET_CONFIG_DEFAULT, 0);
+               def_conf = snd_hda_codec_get_pincfg(codec, nid);
                def_conf = get_defcfg_connect(def_conf);
                /* skip any ports that don't have jacks since presence
                 * detection is useless */
@@ -4176,7 +4159,6 @@ static void stac92xx_free(struct hda_codec *codec)
        if (! spec)
                return;
 
-       kfree(spec->pin_configs);
        stac92xx_free_jacks(codec);
        snd_array_free(&spec->events);
 
@@ -4487,7 +4469,6 @@ static int stac92xx_resume(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
 
-       stac92xx_set_config_regs(codec);
        stac92xx_init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
@@ -4498,6 +4479,37 @@ static int stac92xx_resume(struct hda_codec *codec)
        return 0;
 }
 
+
+/*
+ * using power check for controlling mute led of HP HDX notebooks
+ * check for mute state only on Speakers (nid = 0x10)
+ *
+ * For this feature CONFIG_SND_HDA_POWER_SAVE is needed, otherwise
+ * the LED is NOT working properly !
+ */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int stac92xx_hp_hdx_check_power_status(struct hda_codec *codec,
+                                             hda_nid_t nid)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       if (nid == 0x10) {
+               if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
+                   HDA_AMP_MUTE)
+                       spec->gpio_data &= ~0x08;  /* orange */
+               else
+                       spec->gpio_data |= 0x08;   /* white */
+
+               stac_gpio_set(codec, spec->gpio_mask,
+                             spec->gpio_dir,
+                             spec->gpio_data);
+       }
+
+       return 0;
+}
+#endif
+
 static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -4536,16 +4548,11 @@ static int patch_stac9200(struct hda_codec *codec)
        spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
                                                        stac9200_models,
                                                        stac9200_cfg_tbl);
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                         stac9200_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        spec->multiout.max_channels = 2;
        spec->multiout.num_dacs = 1;
@@ -4613,17 +4620,12 @@ static int patch_stac925x(struct hda_codec *codec)
                                                        stac925x_models,
                                                        stac925x_cfg_tbl);
  again:
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
                                      "using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                         stac925x_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        spec->multiout.max_channels = 2;
        spec->multiout.num_dacs = 1;
@@ -4701,17 +4703,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
                                                        stac92hd73xx_models,
                                                        stac92hd73xx_cfg_tbl);
 again:
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for"
                        " STAC92HD73XX, using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                stac92hd73xx_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        num_dacs = snd_hda_get_connections(codec, 0x0a,
                        conn, STAC92HD73_DAC_COUNT + 2) - 1;
@@ -4725,14 +4722,18 @@ again:
        case 0x3: /* 6 Channel */
                spec->mixer = stac92hd73xx_6ch_mixer;
                spec->init = stac92hd73xx_6ch_core_init;
+               spec->aloopback_ctl = stac92hd73xx_6ch_loopback;
                break;
        case 0x4: /* 8 Channel */
                spec->mixer = stac92hd73xx_8ch_mixer;
                spec->init = stac92hd73xx_8ch_core_init;
+               spec->aloopback_ctl = stac92hd73xx_8ch_loopback;
                break;
        case 0x5: /* 10 Channel */
                spec->mixer = stac92hd73xx_10ch_mixer;
                spec->init = stac92hd73xx_10ch_core_init;
+               spec->aloopback_ctl = stac92hd73xx_10ch_loopback;
+               break;
        }
        spec->multiout.dac_nids = spec->dac_nids;
 
@@ -4771,18 +4772,18 @@ again:
                        spec->init = dell_m6_core_init;
                switch (spec->board_config) {
                case STAC_DELL_M6_AMIC: /* Analog Mics */
-                       stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
+                       snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
                        spec->num_dmics = 0;
                        spec->private_dimux.num_items = 1;
                        break;
                case STAC_DELL_M6_DMIC: /* Digital Mics */
-                       stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+                       snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
                        spec->num_dmics = 1;
                        spec->private_dimux.num_items = 2;
                        break;
                case STAC_DELL_M6_BOTH: /* Both */
-                       stac92xx_set_config_reg(codec, 0x0b, 0x90A70170);
-                       stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
+                       snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170);
+                       snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160);
                        spec->num_dmics = 1;
                        spec->private_dimux.num_items = 2;
                        break;
@@ -4845,6 +4846,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
        int err;
        int num_dacs;
+       hda_nid_t nid;
 
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -4863,15 +4865,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
        spec->multiout.dac_nids = spec->dac_nids;
 
-
-       /* set port 0xe to select the last DAC
-        */
-       num_dacs = snd_hda_get_connections(codec, 0x0e,
-               conn, STAC92HD83_DAC_COUNT + 1) - 1;
-
-       snd_hda_codec_write_cache(codec, 0xe, 0,
-               AC_VERB_SET_CONNECT_SEL, num_dacs);
-
        spec->init = stac92hd83xxx_core_init;
        spec->mixer = stac92hd83xxx_mixer;
        spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids);
@@ -4886,17 +4879,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
                                                        stac92hd83xxx_models,
                                                        stac92hd83xxx_cfg_tbl);
 again:
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for"
                        " STAC92HD83XXX, using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                stac92hd83xxx_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        switch (codec->vendor_id) {
        case 0x111d7604:
@@ -4923,6 +4911,23 @@ again:
                return err;
        }
 
+       switch (spec->board_config) {
+       case STAC_DELL_S14:
+               nid = 0xf;
+               break;
+       default:
+               nid = 0xe;
+               break;
+       }
+
+       num_dacs = snd_hda_get_connections(codec, nid,
+                               conn, STAC92HD83_DAC_COUNT + 1) - 1;
+
+       /* set port X to select the last DAC
+        */
+       snd_hda_codec_write_cache(codec, nid, 0,
+                       AC_VERB_SET_CONNECT_SEL, num_dacs);
+
        codec->patch_ops = stac92xx_patch_ops;
 
        codec->proc_widget_hook = stac92hd_proc_hook;
@@ -4930,7 +4935,16 @@ again:
        return 0;
 }
 
-static struct hda_input_mux stac92hd71bxx_dmux = {
+static struct hda_input_mux stac92hd71bxx_dmux_nomixer = {
+       .num_items = 3,
+       .items = {
+               { "Analog Inputs", 0x00 },
+               { "Digital Mic 1", 0x02 },
+               { "Digital Mic 2", 0x03 },
+       }
+};
+
+static struct hda_input_mux stac92hd71bxx_dmux_amixer = {
        .num_items = 4,
        .items = {
                { "Analog Inputs", 0x00 },
@@ -4940,11 +4954,67 @@ static struct hda_input_mux stac92hd71bxx_dmux = {
        }
 };
 
+/* get the pin connection (fixed, none, etc) */
+static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       unsigned int cfg;
+
+       cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
+       return get_defcfg_connect(cfg);
+}
+
+static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
+                                        hda_nid_t *nids, int num_nids)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int idx, num;
+       unsigned int def_conf;
+
+       for (num = 0; num < num_nids; num++) {
+               for (idx = 0; idx < spec->num_pins; idx++)
+                       if (spec->pin_nids[idx] == nids[num])
+                               break;
+               if (idx >= spec->num_pins)
+                       break;
+               def_conf = stac_get_defcfg_connect(codec, idx);
+               if (def_conf == AC_JACK_PORT_NONE)
+                       break;
+       }
+       return num;
+}
+
+static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
+                                         hda_nid_t dig0pin)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int idx;
+
+       for (idx = 0; idx < spec->num_pins; idx++)
+               if (spec->pin_nids[idx] == dig0pin)
+                       break;
+       if ((idx + 2) >= spec->num_pins)
+               return 0;
+
+       /* dig1pin case */
+       if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE)
+               return 2;
+
+       /* dig0pin + dig2pin case */
+       if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE)
+               return 2;
+       if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE)
+               return 1;
+       else
+               return 0;
+}
+
 static int patch_stac92hd71bxx(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec;
        struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
        int err = 0;
+       unsigned int ndmic_nids = 0;
 
        spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -4952,27 +5022,32 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
 
        codec->spec = spec;
        codec->patch_ops = stac92xx_patch_ops;
-       spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids);
+       spec->num_pins = STAC92HD71BXX_NUM_PINS;
+       switch (codec->vendor_id) {
+       case 0x111d76b6:
+       case 0x111d76b7:
+               spec->pin_nids = stac92hd71bxx_pin_nids_4port;
+               break;
+       case 0x111d7603:
+       case 0x111d7608:
+               /* On 92HD75Bx 0x27 isn't a pin nid */
+               spec->num_pins--;
+               /* fallthrough */
+       default:
+               spec->pin_nids = stac92hd71bxx_pin_nids_6port;
+       }
        spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
-       spec->pin_nids = stac92hd71bxx_pin_nids;
-       memcpy(&spec->private_dimux, &stac92hd71bxx_dmux,
-                       sizeof(stac92hd71bxx_dmux));
        spec->board_config = snd_hda_check_board_config(codec,
                                                        STAC_92HD71BXX_MODELS,
                                                        stac92hd71bxx_models,
                                                        stac92hd71bxx_cfg_tbl);
 again:
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for"
                        " STAC92HD71BXX, using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                stac92hd71bxx_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        if (spec->board_config > STAC_92HD71BXX_REF) {
                /* GPIO0 = EAPD */
@@ -4981,16 +5056,34 @@ again:
                spec->gpio_data = 0x01;
        }
 
+       spec->dmic_nids = stac92hd71bxx_dmic_nids;
+       spec->dmux_nids = stac92hd71bxx_dmux_nids;
+
        switch (codec->vendor_id) {
        case 0x111d76b6: /* 4 Port without Analog Mixer */
        case 0x111d76b7:
+               unmute_init++;
+               /* fallthru */
        case 0x111d76b4: /* 6 Port without Analog Mixer */
        case 0x111d76b5:
+               memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer,
+                      sizeof(stac92hd71bxx_dmux_nomixer));
                spec->mixer = stac92hd71bxx_mixer;
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
+               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+                                       stac92hd71bxx_dmic_nids,
+                                       STAC92HD71BXX_NUM_DMICS);
+               if (spec->num_dmics) {
+                       spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+                       spec->dinput_mux = &spec->private_dimux;
+                       ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
+               }
                break;
        case 0x111d7608: /* 5 Port with Analog Mixer */
+               memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
+                      sizeof(stac92hd71bxx_dmux_amixer));
+               spec->private_dimux.num_items--;
                switch (spec->board_config) {
                case STAC_HP_M4:
                        /* Enable VREF power saving on GPIO1 detect */
@@ -5018,7 +5111,14 @@ again:
                /* disable VSW */
                spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
                unmute_init++;
-               stac_change_pin_config(codec, 0xf, 0x40f000f0);
+               snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
+               snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
+               stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
+               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+                                       stac92hd71bxx_dmic_nids,
+                                       STAC92HD71BXX_NUM_DMICS - 1);
+               spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+               ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
                break;
        case 0x111d7603: /* 6 Port with Analog Mixer */
                if ((codec->revision_id & 0xf) == 1)
@@ -5028,15 +5128,23 @@ again:
                spec->num_pwrs = 0;
                /* fallthru */
        default:
+               memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
+                      sizeof(stac92hd71bxx_dmux_amixer));
                spec->dinput_mux = &spec->private_dimux;
                spec->mixer = stac92hd71bxx_analog_mixer;
                spec->init = stac92hd71bxx_analog_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
+               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+                                       stac92hd71bxx_dmic_nids,
+                                       STAC92HD71BXX_NUM_DMICS);
+               spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+               ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
        }
 
        if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
                snd_hda_sequence_write_cache(codec, unmute_init);
 
+       spec->aloopback_ctl = stac92hd71bxx_loopback;
        spec->aloopback_mask = 0x50;
        spec->aloopback_shift = 0;
 
@@ -5044,18 +5152,17 @@ again:
        spec->digbeep_nid = 0x26;
        spec->mux_nids = stac92hd71bxx_mux_nids;
        spec->adc_nids = stac92hd71bxx_adc_nids;
-       spec->dmic_nids = stac92hd71bxx_dmic_nids;
-       spec->dmux_nids = stac92hd71bxx_dmux_nids;
        spec->smux_nids = stac92hd71bxx_smux_nids;
        spec->pwr_nids = stac92hd71bxx_pwr_nids;
 
        spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids);
        spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids);
+       spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e);
 
        switch (spec->board_config) {
        case STAC_HP_M4:
                /* enable internal microphone */
-               stac_change_pin_config(codec, 0x0e, 0x01813040);
+               snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040);
                stac92xx_auto_set_pinctl(codec, 0x0e,
                        AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
                /* fallthru */
@@ -5068,21 +5175,38 @@ again:
        case STAC_DELL_M4_3:
                spec->num_dmics = 1;
                spec->num_smuxes = 0;
-               spec->num_dmuxes = 0;
+               spec->num_dmuxes = 1;
+               break;
+       case STAC_HP_DV5:
+               snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
+               stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN);
+               break;
+       case STAC_HP_HDX:
+               spec->num_dmics = 1;
+               spec->num_dmuxes = 1;
+               spec->num_smuxes = 1;
+               /*
+                * For controlling MUTE LED on HP HDX16/HDX18 notebooks,
+                * the CONFIG_SND_HDA_POWER_SAVE is needed to be set.
+                */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+               /* orange/white mute led on GPIO3, orange=0, white=1 */
+               spec->gpio_mask |= 0x08;
+               spec->gpio_dir  |= 0x08;
+               spec->gpio_data |= 0x08;  /* set to white */
+
+               /* register check_power_status callback. */
+               codec->patch_ops.check_power_status =
+                   stac92xx_hp_hdx_check_power_status;
+#endif 
                break;
-       default:
-               spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
-               spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids);
-               spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
        };
 
        spec->multiout.dac_nids = spec->dac_nids;
        if (spec->dinput_mux)
-               spec->private_dimux.num_items +=
-                       spec->num_dmics -
-                               (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1);
+               spec->private_dimux.num_items += spec->num_dmics - ndmic_nids;
 
-       err = stac92xx_parse_auto_config(codec, 0x21, 0x23);
+       err = stac92xx_parse_auto_config(codec, 0x21, 0);
        if (!err) {
                if (spec->board_config < 0) {
                        printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -5157,17 +5281,12 @@ static int patch_stac922x(struct hda_codec *codec)
        }
 
  again:
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
                        "using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                stac922x_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        spec->adc_nids = stac922x_adc_nids;
        spec->mux_nids = stac922x_mux_nids;
@@ -5218,24 +5337,19 @@ static int patch_stac927x(struct hda_codec *codec)
                return -ENOMEM;
 
        codec->spec = spec;
+       codec->slave_dig_outs = stac927x_slave_dig_outs;
        spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
        spec->pin_nids = stac927x_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
                                                        stac927x_models,
                                                        stac927x_cfg_tbl);
  again:
-       if (spec->board_config < 0 || !stac927x_brd_tbl[spec->board_config]) {
-               if (spec->board_config < 0)
-                       snd_printdd(KERN_INFO "hda_codec: Unknown model for"
-                                   "STAC927x, using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       if (spec->board_config < 0)
+               snd_printdd(KERN_INFO "hda_codec: Unknown model for"
+                           "STAC927x, using BIOS defaults\n");
+       else
+               stac92xx_set_config_regs(codec,
                                stac927x_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        spec->digbeep_nid = 0x23;
        spec->adc_nids = stac927x_adc_nids;
@@ -5264,15 +5378,15 @@ static int patch_stac927x(struct hda_codec *codec)
                case 0x10280209:
                case 0x1028022e:
                        /* correct the device field to SPDIF out */
-                       stac_change_pin_config(codec, 0x21, 0x01442070);
+                       snd_hda_codec_set_pincfg(codec, 0x21, 0x01442070);
                        break;
                };
                /* configure the analog microphone on some laptops */
-               stac_change_pin_config(codec, 0x0c, 0x90a79130);
+               snd_hda_codec_set_pincfg(codec, 0x0c, 0x90a79130);
                /* correct the front output jack as a hp out */
-               stac_change_pin_config(codec, 0x0f, 0x0227011f);
+               snd_hda_codec_set_pincfg(codec, 0x0f, 0x0227011f);
                /* correct the front input jack as a mic */
-               stac_change_pin_config(codec, 0x0e, 0x02a79130);
+               snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130);
                /* fallthru */
        case STAC_DELL_3ST:
                /* GPIO2 High = Enable EAPD */
@@ -5299,6 +5413,7 @@ static int patch_stac927x(struct hda_codec *codec)
        }
 
        spec->num_pwrs = 0;
+       spec->aloopback_ctl = stac927x_loopback;
        spec->aloopback_mask = 0x40;
        spec->aloopback_shift = 0;
        spec->eapd_switch = 1;
@@ -5357,16 +5472,11 @@ static int patch_stac9205(struct hda_codec *codec)
                                                        stac9205_models,
                                                        stac9205_cfg_tbl);
  again:
-       if (spec->board_config < 0) {
+       if (spec->board_config < 0)
                snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
-               err = stac92xx_save_bios_config_regs(codec);
-       } else
-               err = stac_save_pin_cfgs(codec,
+       else
+               stac92xx_set_config_regs(codec,
                                         stac9205_brd_tbl[spec->board_config]);
-       if (err < 0) {
-               stac92xx_free(codec);
-               return err;
-       }
 
        spec->digbeep_nid = 0x23;
        spec->adc_nids = stac9205_adc_nids;
@@ -5383,6 +5493,7 @@ static int patch_stac9205(struct hda_codec *codec)
 
        spec->init = stac9205_core_init;
        spec->mixer = stac9205_mixer;
+       spec->aloopback_ctl = stac9205_loopback;
 
        spec->aloopback_mask = 0x40;
        spec->aloopback_shift = 0;
@@ -5394,8 +5505,8 @@ static int patch_stac9205(struct hda_codec *codec)
        switch (spec->board_config){
        case STAC_9205_DELL_M43:
                /* Enable SPDIF in/out */
-               stac_change_pin_config(codec, 0x1f, 0x01441030);
-               stac_change_pin_config(codec, 0x20, 0x1c410030);
+               snd_hda_codec_set_pincfg(codec, 0x1f, 0x01441030);
+               snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
 
                /* Enable unsol response for GPIO4/Dock HP connection */
                err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);