]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - sound/pci/hda/patch_realtek.c
ALSA: hda - Consolidate default automute functions for Realtek
[mirror_ubuntu-bionic-kernel.git] / sound / pci / hda / patch_realtek.c
index f1a03f223495f70043914326c4a563798f10ef34..5715b6f3e2a966e0cebe540771cd682c8c21c675 100644 (file)
@@ -299,6 +299,17 @@ struct alc_customize_define {
 
 struct alc_fixup;
 
+struct alc_multi_io {
+       hda_nid_t pin;          /* multi-io widget pin NID */
+       hda_nid_t dac;          /* DAC to be connected */
+       unsigned int ctl_in;    /* cached input-pin control value */
+};
+
+enum {
+       ALC_AUTOMUTE_PIN,
+       ALC_AUTOMUTE_AMP,
+};
+
 struct alc_spec {
        /* codec parameterization */
        struct snd_kcontrol_new *mixers[5];     /* mixer arrays */
@@ -375,17 +386,23 @@ struct alc_spec {
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        void (*power_hook)(struct hda_codec *codec);
 #endif
+       void (*shutup)(struct hda_codec *codec);
 
        /* for pin sensing */
        unsigned int sense_updated: 1;
        unsigned int jack_present: 1;
        unsigned int master_sw: 1;
        unsigned int auto_mic:1;
+       unsigned int automute:1;        /* HP automute enabled */
 
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
        unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
        unsigned int single_input_src:1;
+
+       /* auto-mute control */
+       int automute_mode;
+
        int init_amp;
        int codec_variant;      /* flag for other variants */
 
@@ -403,6 +420,10 @@ struct alc_spec {
        int fixup_id;
        const struct alc_fixup *fixup_list;
        const char *fixup_name;
+
+       /* multi-io */
+       int multi_ios;
+       struct alc_multi_io multi_io[4];
 };
 
 /*
@@ -1051,13 +1072,16 @@ static int alc_init_jacks(struct hda_codec *codec)
        return 0;
 }
 
-static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
+static void alc_hp_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        unsigned int mute;
        hda_nid_t nid;
        int i;
 
+       if (!spec->automute)
+               return;
+
        spec->jack_present = 0;
        for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
                nid = spec->autocfg.hp_pins[i];
@@ -1073,7 +1097,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
                nid = spec->autocfg.speaker_pins[i];
                if (!nid)
                        break;
-               if (pinctl) {
+               if (spec->automute_mode == ALC_AUTOMUTE_PIN) {
                        snd_hda_codec_write(codec, nid, 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    spec->jack_present ? 0 : PIN_OUT);
@@ -1084,11 +1108,6 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
        }
 }
 
-static void alc_automute_pin(struct hda_codec *codec)
-{
-       alc_automute_speaker(codec, 1);
-}
-
 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
                                hda_nid_t nid)
 {
@@ -1184,7 +1203,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
                res >>= 26;
        switch (res) {
        case ALC880_HP_EVENT:
-               alc_automute_pin(codec);
+               alc_hp_automute(codec);
                break;
        case ALC880_MIC_EVENT:
                alc_mic_automute(codec);
@@ -1194,7 +1213,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 
 static void alc_inithook(struct hda_codec *codec)
 {
-       alc_automute_pin(codec);
+       alc_hp_automute(codec);
        alc_mic_automute(codec);
 }
 
@@ -1236,6 +1255,43 @@ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
                                    on ? 2 : 0);
 }
 
+/* turn on/off EAPD controls of the codec */
+static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
+{
+       /* We currently only handle front, HP */
+       switch (codec->vendor_id) {
+       case 0x10ec0260:
+               set_eapd(codec, 0x0f, on);
+               set_eapd(codec, 0x10, on);
+               break;
+       case 0x10ec0262:
+       case 0x10ec0267:
+       case 0x10ec0268:
+       case 0x10ec0269:
+       case 0x10ec0270:
+       case 0x10ec0272:
+       case 0x10ec0660:
+       case 0x10ec0662:
+       case 0x10ec0663:
+       case 0x10ec0665:
+       case 0x10ec0862:
+       case 0x10ec0889:
+       case 0x10ec0892:
+               set_eapd(codec, 0x14, on);
+               set_eapd(codec, 0x15, on);
+               break;
+       }
+}
+
+/* generic shutup callback;
+ * just turning off EPAD and a little pause for avoiding pop-noise
+ */
+static void alc_eapd_shutup(struct hda_codec *codec)
+{
+       alc_auto_setup_eapd(codec, false);
+       msleep(200);
+}
+
 static void alc_auto_init_amp(struct hda_codec *codec, int type)
 {
        unsigned int tmp;
@@ -1251,26 +1307,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
                snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
                break;
        case ALC_INIT_DEFAULT:
-               switch (codec->vendor_id) {
-               case 0x10ec0260:
-                       set_eapd(codec, 0x0f, 1);
-                       set_eapd(codec, 0x10, 1);
-                       break;
-               case 0x10ec0262:
-               case 0x10ec0267:
-               case 0x10ec0268:
-               case 0x10ec0269:
-               case 0x10ec0270:
-               case 0x10ec0272:
-               case 0x10ec0660:
-               case 0x10ec0662:
-               case 0x10ec0663:
-               case 0x10ec0862:
-               case 0x10ec0889:
-                       set_eapd(codec, 0x14, 1);
-                       set_eapd(codec, 0x15, 1);
-                       break;
-               }
+               alc_auto_setup_eapd(codec, true);
                switch (codec->vendor_id) {
                case 0x10ec0260:
                        snd_hda_codec_write(codec, 0x1a, 0,
@@ -1289,7 +1326,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
                case 0x10ec0883:
                case 0x10ec0885:
                case 0x10ec0887:
-               case 0x10ec0889:
+               /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
                        alc889_coef_init(codec);
                        break;
                case 0x10ec0888:
@@ -1345,6 +1382,8 @@ static void alc_init_auto_hp(struct hda_codec *codec)
                snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
                                  AC_VERB_SET_UNSOLICITED_ENABLE,
                                  AC_USRSP_EN | ALC880_HP_EVENT);
+               spec->automute = 1;
+               spec->automute_mode = ALC_AUTOMUTE_PIN;
        }
        spec->unsol_event = alc_sku_unsol_event;
 }
@@ -1942,22 +1981,6 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
        {}
 };
 
-static void alc_automute_amp(struct hda_codec *codec)
-{
-       alc_automute_speaker(codec, 0);
-}
-
-static void alc_automute_amp_unsol_event(struct hda_codec *codec,
-                                        unsigned int res)
-{
-       if (codec->vendor_id == 0x10ec0880)
-               res >>= 28;
-       else
-               res >>= 26;
-       if (res == ALC880_HP_EVENT)
-               alc_automute_amp(codec);
-}
-
 static void alc889_automute_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -1968,12 +1991,14 @@ static void alc889_automute_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x17;
        spec->autocfg.speaker_pins[3] = 0x19;
        spec->autocfg.speaker_pins[4] = 0x1a;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc889_intel_init_hook(struct hda_codec *codec)
 {
        alc889_coef_init(codec);
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
 }
 
 static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
@@ -1984,6 +2009,8 @@ static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[1] = 0x1b; /* hp */
        spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
        spec->autocfg.speaker_pins[1] = 0x15; /* bass */
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /*
@@ -2266,6 +2293,8 @@ static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
@@ -2276,6 +2305,8 @@ static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
@@ -2286,6 +2317,8 @@ static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
@@ -2296,6 +2329,8 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x1b;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /*
@@ -3371,11 +3406,13 @@ static void alc880_uniwill_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x16;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc880_uniwill_init_hook(struct hda_codec *codec)
 {
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
        alc88x_simple_mic_automute(codec);
 }
 
@@ -3390,7 +3427,7 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
                alc88x_simple_mic_automute(codec);
                break;
        default:
-               alc_automute_amp_unsol_event(codec, res);
+               alc_sku_unsol_event(codec, res);
                break;
        }
 }
@@ -3401,6 +3438,8 @@ static void alc880_uniwill_p53_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -3425,7 +3464,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
        if ((res >> 28) == ALC880_DCVOL_EVENT)
                alc880_uniwill_p53_dcvol_automute(codec);
        else
-               alc_automute_amp_unsol_event(codec, res);
+               alc_sku_unsol_event(codec, res);
 }
 
 /*
@@ -3669,6 +3708,8 @@ static void alc880_lg_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /*
@@ -3753,6 +3794,8 @@ static void alc880_lg_lw_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
@@ -3800,7 +3843,7 @@ static struct hda_verb alc880_medion_rim_init_verbs[] = {
 static void alc880_medion_rim_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
        /* toggle EAPD */
        if (spec->jack_present)
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
@@ -3824,6 +3867,8 @@ static void alc880_medion_rim_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -4192,6 +4237,10 @@ static int alc_build_pcms(struct hda_codec *codec)
 
 static inline void alc_shutup(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
+
+       if (spec && spec->shutup)
+               spec->shutup(codec);
        snd_hda_shutup_pins(codec);
 }
 
@@ -4225,27 +4274,7 @@ static void alc_free(struct hda_codec *codec)
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static void alc_power_eapd(struct hda_codec *codec)
 {
-       /* We currently only handle front, HP */
-       switch (codec->vendor_id) {
-       case 0x10ec0260:
-               set_eapd(codec, 0x0f, 0);
-               set_eapd(codec, 0x10, 0);
-               break;
-       case 0x10ec0262:
-       case 0x10ec0267:
-       case 0x10ec0268:
-       case 0x10ec0269:
-       case 0x10ec0270:
-       case 0x10ec0272:
-       case 0x10ec0660:
-       case 0x10ec0662:
-       case 0x10ec0663:
-       case 0x10ec0862:
-       case 0x10ec0889:
-               set_eapd(codec, 0x14, 0);
-               set_eapd(codec, 0x15, 0);
-               break;
-       }
+       alc_auto_setup_eapd(codec, false);
 }
 
 static int alc_suspend(struct hda_codec *codec, pm_message_t state)
@@ -4261,6 +4290,7 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state)
 #ifdef SND_HDA_NEEDS_RESUME
 static int alc_resume(struct hda_codec *codec)
 {
+       msleep(150); /* to avoid pop noise */
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
@@ -4792,7 +4822,7 @@ static struct alc_config_preset alc880_presets[] = {
                .input_mux = &alc880_f1734_capture_source,
                .unsol_event = alc880_uniwill_p53_unsol_event,
                .setup = alc880_uniwill_p53_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC880_ASUS] = {
                .mixers = { alc880_asus_mixer },
@@ -4883,7 +4913,7 @@ static struct alc_config_preset alc880_presets[] = {
                .input_mux = &alc880_capture_source,
                .unsol_event = alc880_uniwill_p53_unsol_event,
                .setup = alc880_uniwill_p53_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC880_FUJITSU] = {
                .mixers = { alc880_fujitsu_mixer },
@@ -4898,7 +4928,7 @@ static struct alc_config_preset alc880_presets[] = {
                .input_mux = &alc880_capture_source,
                .unsol_event = alc880_uniwill_p53_unsol_event,
                .setup = alc880_uniwill_p53_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC880_CLEVO] = {
                .mixers = { alc880_three_stack_mixer },
@@ -4923,9 +4953,9 @@ static struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_lg_ch_modes,
                .need_dac_fix = 1,
                .input_mux = &alc880_lg_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc880_lg_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
                .loopbacks = alc880_lg_loopbacks,
 #endif
@@ -4940,9 +4970,9 @@ static struct alc_config_preset alc880_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
                .channel_mode = alc880_lg_lw_modes,
                .input_mux = &alc880_lg_lw_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc880_lg_lw_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC880_MEDION_RIM] = {
                .mixers = { alc880_medion_rim_mixer },
@@ -4988,14 +5018,19 @@ static struct snd_kcontrol_new alc880_control_templates[] = {
        HDA_BIND_MUTE(NULL, 0, 0, 0),
 };
 
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+{
+       snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+       return snd_array_new(&spec->kctls);
+}
+
 /* add dynamic controls */
 static int add_control(struct alc_spec *spec, int type, const char *name,
                       int cidx, unsigned long val)
 {
        struct snd_kcontrol_new *knew;
 
-       snd_array_init(&spec->kctls, sizeof(*knew), 32);
-       knew = snd_array_new(&spec->kctls);
+       knew = alc_kcontrol_new(spec);
        if (!knew)
                return -ENOMEM;
        *knew = alc880_control_templates[type];
@@ -5076,10 +5111,13 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
        return 0;
 }
 
-static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
+static const char *alc_get_line_out_pfx(struct alc_spec *spec,
                                        bool can_be_master)
 {
-       if (!cfg->hp_outs && !cfg->speaker_outs && can_be_master)
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+
+       if (cfg->line_outs == 1 && !spec->multi_ios &&
+           !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
                return "Master";
 
        switch (cfg->line_out_type) {
@@ -5090,7 +5128,7 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
        case AUTO_PIN_HP_OUT:
                return "Headphone";
        default:
-               if (cfg->line_outs == 1)
+               if (cfg->line_outs == 1 && !spec->multi_ios)
                        return "PCM";
                break;
        }
@@ -5104,11 +5142,15 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
        static const char * const chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
-       const char *pfx = alc_get_line_out_pfx(cfg, false);
+       const char *pfx = alc_get_line_out_pfx(spec, false);
        hda_nid_t nid;
-       int i, err;
+       int i, err, noutputs;
 
-       for (i = 0; i < cfg->line_outs; i++) {
+       noutputs = cfg->line_outs;
+       if (spec->multi_ios > 0)
+               noutputs += spec->multi_ios;
+
+       for (i = 0; i < noutputs; i++) {
                if (!spec->multiout.dac_nids[i])
                        continue;
                nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
@@ -5374,6 +5416,8 @@ static void alc880_auto_init_input_src(struct hda_codec *codec)
        }
 }
 
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
+
 /* parse the BIOS configuration and set up the alc_spec */
 /* return 1 if successful, 0 if the proper config is not found,
  * or a negative error code
@@ -5392,6 +5436,9 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
                return 0; /* can't find valid BIOS pin config */
 
        err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc_auto_add_multi_channel_mode(codec);
        if (err < 0)
                return err;
        err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
@@ -7381,6 +7428,7 @@ static int patch_alc260(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC260_AUTO)
                spec->init_hook = alc260_auto_init;
+       spec->shutup = alc_eapd_shutup;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc260_loopbacks;
@@ -8597,6 +8645,8 @@ static void alc885_imac24_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
        spec->autocfg.speaker_pins[1] = 0x1a;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 #define alc885_mb5_setup       alc885_imac24_setup
@@ -8609,6 +8659,8 @@ static void alc885_mba21_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 
@@ -8619,6 +8671,8 @@ static void alc885_mbp3_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc885_imac91_setup(struct hda_codec *codec)
@@ -8628,6 +8682,8 @@ static void alc885_imac91_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
        spec->autocfg.speaker_pins[1] = 0x1a;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc882_targa_verbs[] = {
@@ -8649,7 +8705,7 @@ static struct hda_verb alc882_targa_verbs[] = {
 static void alc882_targa_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
        snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
                                  spec->jack_present ? 1 : 3);
 }
@@ -8660,6 +8716,8 @@ static void alc882_targa_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -8747,7 +8805,7 @@ static void alc885_macpro_init_hook(struct hda_codec *codec)
 static void alc885_imac24_init_hook(struct hda_codec *codec)
 {
        alc885_macpro_init_hook(codec);
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
 }
 
 /*
@@ -9105,6 +9163,8 @@ static void alc883_medion_wim2160_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1a;
        spec->autocfg.speaker_pins[0] = 0x15;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
@@ -9257,6 +9317,8 @@ static void alc883_mitac_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc883_mitac_verbs[] = {
@@ -9421,6 +9483,8 @@ static void alc888_3st_hp_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x18;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc888_3st_hp_verbs[] = {
@@ -9509,6 +9573,8 @@ static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -9521,11 +9587,13 @@ static void alc883_clevo_m720_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
 {
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
        alc88x_simple_mic_automute(codec);
 }
 
@@ -9537,7 +9605,7 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
                alc88x_simple_mic_automute(codec);
                break;
        default:
-               alc_automute_amp_unsol_event(codec, res);
+               alc_sku_unsol_event(codec, res);
                break;
        }
 }
@@ -9549,6 +9617,8 @@ static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_haier_w66_setup(struct hda_codec *codec)
@@ -9557,6 +9627,8 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
@@ -9594,6 +9666,8 @@ static void alc883_acer_aspire_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
        spec->autocfg.speaker_pins[1] = 0x16;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc883_acer_eapd_verbs[] = {
@@ -9623,6 +9697,8 @@ static void alc888_6st_dell_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[1] = 0x15;
        spec->autocfg.speaker_pins[2] = 0x16;
        spec->autocfg.speaker_pins[3] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc888_lenovo_sky_setup(struct hda_codec *codec)
@@ -9635,6 +9711,8 @@ static void alc888_lenovo_sky_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x16;
        spec->autocfg.speaker_pins[3] = 0x17;
        spec->autocfg.speaker_pins[4] = 0x1a;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_vaiott_setup(struct hda_codec *codec)
@@ -9644,6 +9722,8 @@ static void alc883_vaiott_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x17;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc888_asus_m90v_verbs[] = {
@@ -9669,6 +9749,8 @@ static void alc883_mode2_setup(struct hda_codec *codec)
        spec->ext_mic.mux_idx = 0;
        spec->int_mic.mux_idx = 1;
        spec->auto_mic = 1;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc888_asus_eee1601_verbs[] = {
@@ -9690,7 +9772,7 @@ static void alc883_eee1601_inithook(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
-       alc_automute_pin(codec);
+       alc_hp_automute(codec);
 }
 
 static struct hda_verb alc889A_mb31_verbs[] = {
@@ -9861,7 +9943,6 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
        SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
 
        SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
@@ -10012,9 +10093,9 @@ static struct alc_config_preset alc882_presets[] = {
                        .channel_mode = alc885_mba21_ch_modes,
                        .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
                        .input_mux = &alc882_capture_source,
-                       .unsol_event = alc_automute_amp_unsol_event,
+                       .unsol_event = alc_sku_unsol_event,
                        .setup = alc885_mba21_setup,
-                       .init_hook = alc_automute_amp,
+                       .init_hook = alc_hp_automute,
        },
        [ALC885_MBP3] = {
                .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
@@ -10028,9 +10109,9 @@ static struct alc_config_preset alc882_presets[] = {
                .input_mux = &alc882_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc885_mbp3_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC885_MB5] = {
                .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
@@ -10043,9 +10124,9 @@ static struct alc_config_preset alc882_presets[] = {
                .input_mux = &mb5_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc885_mb5_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC885_MACMINI3] = {
                .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
@@ -10058,9 +10139,9 @@ static struct alc_config_preset alc882_presets[] = {
                .input_mux = &macmini3_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc885_macmini3_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC885_MACPRO] = {
                .mixers = { alc882_macpro_mixer },
@@ -10084,7 +10165,7 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
                .channel_mode = alc882_ch_modes,
                .input_mux = &alc882_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc885_imac24_setup,
                .init_hook = alc885_imac24_init_hook,
        },
@@ -10099,9 +10180,9 @@ static struct alc_config_preset alc882_presets[] = {
                .input_mux = &alc889A_imac91_capture_source,
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc885_imac91_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC882_TARGA] = {
                .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
@@ -10117,7 +10198,7 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc882_3ST_6ch_modes,
                .need_dac_fix = 1,
                .input_mux = &alc882_capture_source,
-               .unsol_event = alc882_targa_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc882_targa_setup,
                .init_hook = alc882_targa_automute,
        },
@@ -10211,8 +10292,8 @@ static struct alc_config_preset alc882_presets[] = {
                .capsrc_nids = alc889_capsrc_nids,
                .input_mux = &alc889_capture_source,
                .setup = alc889_automute_setup,
-               .init_hook = alc_automute_amp,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .init_hook = alc_hp_automute,
+               .unsol_event = alc_sku_unsol_event,
                .need_dac_fix = 1,
        },
        [ALC889_INTEL] = {
@@ -10232,7 +10313,7 @@ static struct alc_config_preset alc882_presets[] = {
                .input_mux = &alc889_capture_source,
                .setup = alc889_automute_setup,
                .init_hook = alc889_intel_init_hook,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .need_dac_fix = 1,
        },
        [ALC883_6ST_DIG] = {
@@ -10321,9 +10402,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_acer_aspire_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_ACER_ASPIRE_4930G] = {
                .mixers = { alc888_acer_aspire_4930g_mixer,
@@ -10343,9 +10424,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_mux_defs =
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_2_capture_sources,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_acer_aspire_4930g_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_ACER_ASPIRE_6530G] = {
                .mixers = { alc888_acer_aspire_6530_mixer },
@@ -10362,9 +10443,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_mux_defs =
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_acer_aspire_6530_sources,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_acer_aspire_6530g_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_ACER_ASPIRE_8930G] = {
                .mixers = { alc889_acer_aspire_8930g_mixer,
@@ -10385,9 +10466,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_mux_defs =
                        ARRAY_SIZE(alc889_capture_sources),
                .input_mux = alc889_capture_sources,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc889_acer_aspire_8930g_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
                .power_hook = alc_power_eapd,
 #endif
@@ -10408,9 +10489,9 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .const_channel_count = 6,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_acer_aspire_7730g_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC883_MEDION] = {
                .mixers = { alc883_fivestack_mixer,
@@ -10437,9 +10518,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_medion_wim2160_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC883_LAPTOP_EAPD] = {
                .mixers = { alc883_base_mixer },
@@ -10501,9 +10582,9 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .need_dac_fix = 1,
                .input_mux = &alc883_lenovo_nb0763_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_lenovo_nb0763_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_LENOVO_MS7195_DIG] = {
                .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10527,9 +10608,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_haier_w66_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_3ST_HP] = {
                .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10540,9 +10621,9 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc888_3st_hp_modes,
                .need_dac_fix = 1,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_3st_hp_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_6ST_DELL] = {
                .mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -10554,9 +10635,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_6st_dell_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC883_MITAC] = {
                .mixers = { alc883_mitac_mixer },
@@ -10566,9 +10647,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_mitac_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC883_FUJITSU_PI2515] = {
                .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
@@ -10580,9 +10661,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_fujitsu_pi2515_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_2ch_fujitsu_pi2515_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_FUJITSU_XA3530] = {
                .mixers = { alc888_base_mixer, alc883_chmode_mixer },
@@ -10599,9 +10680,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_mux_defs =
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_2_capture_sources,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_fujitsu_xa3530_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_LENOVO_SKY] = {
                .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
@@ -10613,9 +10694,9 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_sixstack_modes,
                .need_dac_fix = 1,
                .input_mux = &alc883_lenovo_sky_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc888_lenovo_sky_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC888_ASUS_M90V] = {
                .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10683,9 +10764,9 @@ static struct alc_config_preset alc882_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc883_vaiott_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
 };
 
@@ -10698,6 +10779,7 @@ enum {
        PINFIX_LENOVO_Y530,
        PINFIX_PB_M5210,
        PINFIX_ACER_ASPIRE_7736,
+       PINFIX_GIGABYTE_880GM,
 };
 
 static const struct alc_fixup alc882_fixups[] = {
@@ -10729,6 +10811,13 @@ static const struct alc_fixup alc882_fixups[] = {
                .type = ALC_FIXUP_SKU,
                .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
+       [PINFIX_GIGABYTE_880GM] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x14, 0x1114410 }, /* set as speaker */
+                       { }
+               }
+       },
 };
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -10736,6 +10825,7 @@ static struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
        SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM),
        {}
 };
 
@@ -10839,6 +10929,11 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
                const struct hda_input_mux *imux;
                int conns, mute, idx, item;
 
+               /* mute ADC */
+               snd_hda_codec_write(codec, spec->adc_nids[c], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_IN_MUTE(0));
+
                conns = snd_hda_get_connections(codec, nid, conn_list,
                                                ARRAY_SIZE(conn_list));
                if (conns < 0)
@@ -10929,6 +11024,9 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
                return 0; /* can't find valid BIOS pin config */
 
        err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc_auto_add_multi_channel_mode(codec);
        if (err < 0)
                return err;
        err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
@@ -11299,6 +11397,8 @@ static void alc262_hp_t5735_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@ -11532,6 +11632,8 @@ static void alc262_tyan_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x15;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 
@@ -11675,6 +11777,8 @@ static void alc262_toshiba_s06_setup(struct hda_codec *codec)
        spec->int_mic.pin = 0x12;
        spec->int_mic.mux_idx = 9;
        spec->auto_mic = 1;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 /*
@@ -12147,7 +12251,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
        spec->multiout.dac_nids = spec->private_dac_nids;
        spec->multiout.dac_nids[0] = 2;
 
-       pfx = alc_get_line_out_pfx(cfg, true);
+       pfx = alc_get_line_out_pfx(spec, true);
        if (!pfx)
                pfx = "Front";
        for (i = 0; i < 2; i++) {
@@ -12885,9 +12989,9 @@ static struct alc_config_preset alc262_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc262_modes),
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc262_tyan_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
 };
 
@@ -13008,6 +13112,7 @@ static int patch_alc262(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC262_AUTO)
                spec->init_hook = alc262_auto_init;
+       spec->shutup = alc_eapd_shutup;
 
        alc_init_jacks(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -13300,6 +13405,8 @@ static void alc268_dell_setup(struct hda_codec *codec)
        spec->int_mic.pin = 0x19;
        spec->int_mic.mux_idx = 1;
        spec->auto_mic = 1;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
@@ -13330,6 +13437,8 @@ static void alc267_quanta_il1_setup(struct hda_codec *codec)
        spec->int_mic.pin = 0x19;
        spec->int_mic.mux_idx = 1;
        spec->auto_mic = 1;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 /*
@@ -14082,6 +14191,7 @@ static int patch_alc268(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC268_AUTO)
                spec->init_hook = alc268_auto_init;
+       spec->shutup = alc_eapd_shutup;
 
        alc_init_jacks(codec);
 
@@ -14114,7 +14224,7 @@ static hda_nid_t alc269vb_capsrc_nids[1] = {
 };
 
 static hda_nid_t alc269_adc_candidates[] = {
-       0x08, 0x09, 0x07,
+       0x08, 0x09, 0x07, 0x11,
 };
 
 #define alc269_modes           alc260_modes
@@ -14793,7 +14903,6 @@ static void alc269_auto_init(struct hda_codec *codec)
                alc_inithook(codec);
 }
 
-#ifdef SND_HDA_NEEDS_RESUME
 static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
 {
        int val = alc_read_coef_idx(codec, 0x04);
@@ -14804,25 +14913,17 @@ static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
        alc_write_coef_idx(codec, 0x04, val);
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_suspend(struct hda_codec *codec, pm_message_t state)
+static void alc269_shutup(struct hda_codec *codec)
 {
-       struct alc_spec *spec = codec->spec;
-
        if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
                alc269_toggle_power_output(codec, 0);
        if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
                alc269_toggle_power_output(codec, 0);
                msleep(150);
        }
-
-       alc_shutup(codec);
-       if (spec && spec->power_hook)
-               spec->power_hook(codec);
-       return 0;
 }
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
 
+#ifdef SND_HDA_NEEDS_RESUME
 static int alc269_resume(struct hda_codec *codec)
 {
        if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
@@ -14858,6 +14959,23 @@ static void alc269_fixup_hweq(struct hda_codec *codec,
        alc_write_coef_idx(codec, 0x1e, coef | 0x80);
 }
 
+static void alc271_fixup_dmic(struct hda_codec *codec,
+                             const struct alc_fixup *fix, int action)
+{
+       static struct hda_verb verbs[] = {
+               {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
+               {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
+               {}
+       };
+       unsigned int cfg;
+
+       if (strcmp(codec->chip_name, "ALC271X"))
+               return;
+       cfg = snd_hda_codec_get_pincfg(codec, 0x12);
+       if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
+               snd_hda_sequence_write(codec, verbs);
+}
+
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -14866,6 +14984,7 @@ enum {
        ALC269_FIXUP_ASUS_G73JW,
        ALC269_FIXUP_LENOVO_EAPD,
        ALC275_FIXUP_SONY_HWEQ,
+       ALC271_FIXUP_DMIC,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14919,7 +15038,11 @@ static const struct alc_fixup alc269_fixups[] = {
                .v.func = alc269_fixup_hweq,
                .chained = true,
                .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
-       }
+       },
+       [ALC271_FIXUP_DMIC] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc271_fixup_dmic,
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -14928,6 +15051,7 @@ static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -15287,14 +15411,12 @@ static int patch_alc269(struct hda_codec *codec)
        spec->vmaster_nid = 0x02;
 
        codec->patch_ops = alc_patch_ops;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-       codec->patch_ops.suspend = alc269_suspend;
-#endif
 #ifdef SND_HDA_NEEDS_RESUME
        codec->patch_ops.resume = alc269_resume;
 #endif
        if (board_config == ALC269_AUTO)
                spec->init_hook = alc269_auto_init;
+       spec->shutup = alc269_shutup;
 
        alc_init_jacks(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -15988,11 +16110,15 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
        static const char * const chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
-       const char *pfx = alc_get_line_out_pfx(cfg, true);
+       const char *pfx = alc_get_line_out_pfx(spec, true);
        hda_nid_t nid;
-       int i, err;
+       int i, err, noutputs;
 
-       for (i = 0; i < cfg->line_outs; i++) {
+       noutputs = cfg->line_outs;
+       if (spec->multi_ios > 0)
+               noutputs += spec->multi_ios;
+
+       for (i = 0; i < noutputs; i++) {
                nid = spec->multiout.dac_nids[i];
                if (!nid)
                        continue;
@@ -16006,9 +16132,12 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
-                       err = __alc861_create_out_sw(codec, name, nid, i, 3);
+                               index = 0;
+                       }
+                       err = __alc861_create_out_sw(codec, name, nid, index, 3);
                        if (err < 0)
                                return err;
                }
@@ -16132,6 +16261,9 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
                return 0; /* can't find valid BIOS pin config */
 
        err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc_auto_add_multi_channel_mode(codec);
        if (err < 0)
                return err;
        err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
@@ -16806,11 +16938,13 @@ static void alc861vd_lenovo_setup(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
 {
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
        alc88x_simple_mic_automute(codec);
 }
 
@@ -16822,7 +16956,7 @@ static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
                alc88x_simple_mic_automute(codec);
                break;
        default:
-               alc_automute_amp_unsol_event(codec, res);
+               alc_sku_unsol_event(codec, res);
                break;
        }
 }
@@ -16879,6 +17013,8 @@ static void alc861vd_dallas_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -17003,9 +17139,9 @@ static struct alc_config_preset alc861vd_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_dallas_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc861vd_dallas_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC861VD_HP] = {
                .mixers = { alc861vd_hp_mixer },
@@ -17016,9 +17152,9 @@ static struct alc_config_preset alc861vd_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_hp_capture_source,
-               .unsol_event = alc_automute_amp_unsol_event,
+               .unsol_event = alc_sku_unsol_event,
                .setup = alc861vd_dallas_setup,
-               .init_hook = alc_automute_amp,
+               .init_hook = alc_hp_automute,
        },
        [ALC660VD_ASUS_V1S] = {
                .mixers = { alc861vd_lenovo_mixer },
@@ -17117,11 +17253,15 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
        static const char * const chname[4] = {
                "Front", "Surround", "CLFE", "Side"
        };
-       const char *pfx = alc_get_line_out_pfx(cfg, true);
+       const char *pfx = alc_get_line_out_pfx(spec, true);
        hda_nid_t nid_v, nid_s;
-       int i, err;
+       int i, err, noutputs;
 
-       for (i = 0; i < cfg->line_outs; i++) {
+       noutputs = cfg->line_outs;
+       if (spec->multi_ios > 0)
+               noutputs += spec->multi_ios;
+
+       for (i = 0; i < noutputs; i++) {
                if (!spec->multiout.dac_nids[i])
                        continue;
                nid_v = alc861vd_idx_to_mixer_vol(
@@ -17159,16 +17299,19 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
+                               index = 0;
+                       }
                        err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-                                               name, i,
+                                               name, index,
                                          HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
                        err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-                                              name, i,
+                                              name, index,
                                          HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
                                                              HDA_INPUT));
                        if (err < 0)
@@ -17241,6 +17384,9 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
                return 0; /* can't find valid BIOS pin config */
 
        err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc_auto_add_multi_channel_mode(codec);
        if (err < 0)
                return err;
        err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
@@ -17394,6 +17540,7 @@ static int patch_alc861vd(struct hda_codec *codec)
 
        if (board_config == ALC861VD_AUTO)
                spec->init_hook = alc861vd_auto_init;
+       spec->shutup = alc_eapd_shutup;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc861vd_loopbacks;
@@ -17416,8 +17563,8 @@ static int patch_alc861vd(struct hda_codec *codec)
 #define ALC662_DIGOUT_NID      0x06
 #define ALC662_DIGIN_NID       0x0a
 
-static hda_nid_t alc662_dac_nids[4] = {
-       /* front, rear, clfe, rear_surr */
+static hda_nid_t alc662_dac_nids[3] = {
+       /* front, rear, clfe */
        0x02, 0x03, 0x04
 };
 
@@ -17906,32 +18053,13 @@ static struct hda_verb alc662_init_verbs[] = {
        {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 
-       /* always trun on EAPD */
-       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-
        { }
 };
 
-static struct hda_verb alc663_init_verbs[] = {
-       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       { }
-};
-
-static struct hda_verb alc272_init_verbs[] = {
-       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+static struct hda_verb alc662_eapd_init_verbs[] = {
+       /* always trun on EAPD */
+       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
        { }
 };
 
@@ -18675,7 +18803,7 @@ static const char * const alc662_models[ALC662_MODEL_LAST] = {
        [ALC662_3ST_2ch_DIG]    = "3stack-dig",
        [ALC662_3ST_6ch_DIG]    = "3stack-6ch-dig",
        [ALC662_3ST_6ch]        = "3stack-6ch",
-       [ALC662_5ST_DIG]        = "6stack-dig",
+       [ALC662_5ST_DIG]        = "5stack-dig",
        [ALC662_LENOVO_101E]    = "lenovo-101e",
        [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
        [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
@@ -18766,8 +18894,6 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
                      ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
        SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
-                     ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
        SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
@@ -18783,7 +18909,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
 static struct alc_config_preset alc662_presets[] = {
        [ALC662_3ST_2ch_DIG] = {
                .mixers = { alc662_3ST_2ch_mixer },
-               .init_verbs = { alc662_init_verbs },
+               .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
@@ -18794,7 +18920,7 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC662_3ST_6ch_DIG] = {
                .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
-               .init_verbs = { alc662_init_verbs },
+               .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
@@ -18806,7 +18932,7 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC662_3ST_6ch] = {
                .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
-               .init_verbs = { alc662_init_verbs },
+               .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
@@ -18816,7 +18942,7 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC662_5ST_DIG] = {
                .mixers = { alc662_base_mixer, alc662_chmode_mixer },
-               .init_verbs = { alc662_init_verbs },
+               .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
@@ -18827,7 +18953,9 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC662_LENOVO_101E] = {
                .mixers = { alc662_lenovo_101e_mixer },
-               .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc662_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
@@ -18839,6 +18967,7 @@ static struct alc_config_preset alc662_presets[] = {
        [ALC662_ASUS_EEEPC_P701] = {
                .mixers = { alc662_eeepc_p701_mixer },
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc662_eeepc_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
@@ -18852,6 +18981,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc662_eeepc_ep20_mixer,
                            alc662_chmode_mixer },
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc662_eeepc_ep20_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
@@ -18865,6 +18995,7 @@ static struct alc_config_preset alc662_presets[] = {
        [ALC662_ECS] = {
                .mixers = { alc662_ecs_mixer },
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc662_ecs_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
@@ -18876,7 +19007,9 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC663_ASUS_M51VA] = {
                .mixers = { alc663_m51va_mixer },
-               .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc663_m51va_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
@@ -18888,7 +19021,9 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC663_ASUS_G71V] = {
                .mixers = { alc663_g71v_mixer },
-               .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc663_g71v_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
@@ -18900,7 +19035,9 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC663_ASUS_H13] = {
                .mixers = { alc663_m51va_mixer },
-               .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc663_m51va_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
@@ -18910,7 +19047,9 @@ static struct alc_config_preset alc662_presets[] = {
        },
        [ALC663_ASUS_G50V] = {
                .mixers = { alc663_g50v_mixer },
-               .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc663_g50v_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
@@ -18925,6 +19064,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_m51va_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_21jd_amic_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -18940,6 +19080,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc662_1bjd_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc662_1bjd_amic_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
@@ -18954,6 +19095,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_two_hp_m1_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_two_hp_amic_m1_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -18969,6 +19111,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_asus_21jd_clfe_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_21jd_amic_init_verbs},
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -18984,6 +19127,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_asus_15jd_clfe_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_15jd_amic_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -18999,6 +19143,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_two_hp_m2_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_two_hp_amic_m2_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -19014,6 +19159,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_mode7_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_mode7_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -19029,6 +19175,7 @@ static struct alc_config_preset alc662_presets[] = {
                .mixers = { alc663_mode8_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_mode8_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .hp_nid = 0x03,
@@ -19043,9 +19190,11 @@ static struct alc_config_preset alc662_presets[] = {
        [ALC272_DELL] = {
                .mixers = { alc663_m51va_mixer },
                .cap_mixer = alc272_auto_capture_mixer,
-               .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc272_dell_init_verbs },
                .num_dacs = ARRAY_SIZE(alc272_dac_nids),
-               .dac_nids = alc662_dac_nids,
+               .dac_nids = alc272_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .adc_nids = alc272_adc_nids,
                .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
@@ -19058,9 +19207,11 @@ static struct alc_config_preset alc662_presets[] = {
        [ALC272_DELL_ZM1] = {
                .mixers = { alc663_m51va_mixer },
                .cap_mixer = alc662_auto_capture_mixer,
-               .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
+               .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
+                               alc272_dell_zm1_init_verbs },
                .num_dacs = ARRAY_SIZE(alc272_dac_nids),
-               .dac_nids = alc662_dac_nids,
+               .dac_nids = alc272_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .adc_nids = alc662_adc_nids,
                .num_adc_nids = 1,
@@ -19073,6 +19224,7 @@ static struct alc_config_preset alc662_presets[] = {
        [ALC272_SAMSUNG_NC10] = {
                .mixers = { alc272_nc10_mixer },
                .init_verbs = { alc662_init_verbs,
+                               alc662_eapd_init_verbs,
                                alc663_21jd_amic_init_verbs },
                .num_dacs = ARRAY_SIZE(alc272_dac_nids),
                .dac_nids = alc272_dac_nids,
@@ -19091,45 +19243,79 @@ static struct alc_config_preset alc662_presets[] = {
  */
 
 /* convert from MIX nid to DAC */
-static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
-{
-       if (nid == 0x0f)
-               return 0x02;
-       else if (nid >= 0x0c && nid <= 0x0e)
-               return nid - 0x0c + 0x02;
-       else if (nid == 0x26) /* ALC887-VD has this DAC too */
-               return 0x25;
-       else
-               return 0;
+static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+       hda_nid_t list[5];
+       int i, num;
+
+       num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
+       for (i = 0; i < num; i++) {
+               if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
+                       return list[i];
+       }
+       return 0;
+}
+
+/* go down to the selector widget before the mixer */
+static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
+{
+       hda_nid_t srcs[5];
+       int num = snd_hda_get_connections(codec, pin, srcs,
+                                         ARRAY_SIZE(srcs));
+       if (num != 1 ||
+           get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
+               return pin;
+       return srcs[0];
 }
 
 /* get MIX nid connected to the given pin targeted to DAC */
-static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
+static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
                                   hda_nid_t dac)
 {
        hda_nid_t mix[5];
        int i, num;
 
+       pin = alc_go_down_to_selector(codec, pin);
        num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
        for (i = 0; i < num; i++) {
-               if (alc662_mix_to_dac(mix[i]) == dac)
+               if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
                        return mix[i];
        }
        return 0;
 }
 
+/* select the connection from pin to DAC if needed */
+static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
+                              hda_nid_t dac)
+{
+       hda_nid_t mix[5];
+       int i, num;
+
+       pin = alc_go_down_to_selector(codec, pin);
+       num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
+       if (num < 2)
+               return 0;
+       for (i = 0; i < num; i++) {
+               if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
+                       snd_hda_codec_update_cache(codec, pin, 0,
+                                                  AC_VERB_SET_CONNECT_SEL, i);
+                       return 0;
+               }
+       }
+       return 0;
+}
+
 /* look for an empty DAC slot */
-static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
 {
        struct alc_spec *spec = codec->spec;
        hda_nid_t srcs[5];
        int i, j, num;
 
+       pin = alc_go_down_to_selector(codec, pin);
        num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
-       if (num < 0)
-               return 0;
        for (i = 0; i < num; i++) {
-               hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
+               hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
                if (!nid)
                        continue;
                for (j = 0; j < spec->multiout.num_dacs; j++)
@@ -19151,7 +19337,7 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
 
        spec->multiout.dac_nids = spec->private_dac_nids;
        for (i = 0; i < cfg->line_outs; i++) {
-               dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
+               dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
                if (!dac)
                        continue;
                spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
@@ -19190,15 +19376,23 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
        static const char * const chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
-       const char *pfx = alc_get_line_out_pfx(cfg, true);
-       hda_nid_t nid, mix;
-       int i, err;
+       const char *pfx = alc_get_line_out_pfx(spec, true);
+       hda_nid_t nid, mix, pin;
+       int i, err, noutputs;
 
-       for (i = 0; i < cfg->line_outs; i++) {
+       noutputs = cfg->line_outs;
+       if (spec->multi_ios > 0)
+               noutputs += spec->multi_ios;
+
+       for (i = 0; i < noutputs; i++) {
                nid = spec->multiout.dac_nids[i];
                if (!nid)
                        continue;
-               mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
+               if (i >= cfg->line_outs)
+                       pin = spec->multi_io[i - 1].pin;
+               else
+                       pin = cfg->line_out_pins[i];
+               mix = alc_auto_dac_to_mix(codec, pin, nid);
                if (!mix)
                        continue;
                if (!pfx && i == 2) {
@@ -19217,12 +19411,15 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
-                       err = __alc662_add_vol_ctl(spec, name, nid, i, 3);
+                               index = 0;
+                       }
+                       err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
                        if (err < 0)
                                return err;
-                       err = __alc662_add_sw_ctl(spec, name, mix, i, 3);
+                       err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
                        if (err < 0)
                                return err;
                }
@@ -19241,7 +19438,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 
        if (!pin)
                return 0;
-       nid = alc662_look_for_dac(codec, pin);
+       nid = alc_auto_look_for_dac(codec, pin);
        if (!nid) {
                /* the corresponding DAC is already occupied */
                if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
@@ -19251,7 +19448,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
                                   HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
        }
 
-       mix = alc662_dac_to_mix(codec, pin, nid);
+       mix = alc_auto_dac_to_mix(codec, pin, nid);
        if (!mix)
                return 0;
        err = alc662_add_vol_ctl(spec, pfx, nid, 3);
@@ -19275,14 +19472,21 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
        hda_nid_t srcs[HDA_MAX_CONNECTIONS];
 
        alc_set_pin_output(codec, nid, pin_type);
-       /* need the manual connection? */
        num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
-       if (num <= 1)
-               return;
        for (i = 0; i < num; i++) {
-               if (alc662_mix_to_dac(srcs[i]) != dac)
+               if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
                        continue;
-               snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
+               /* need the manual connection? */
+               if (num > 1)
+                       snd_hda_codec_write(codec, nid, 0,
+                                           AC_VERB_SET_CONNECT_SEL, i);
+               /* unmute mixer widget inputs */
+               snd_hda_codec_write(codec, srcs[i], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_IN_UNMUTE(0));
+               snd_hda_codec_write(codec, srcs[i], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_IN_UNMUTE(1));
                return;
        }
 }
@@ -19339,6 +19543,159 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
 
 #define alc662_auto_init_input_src     alc882_auto_init_input_src
 
+/*
+ * multi-io helper
+ */
+static int alc_auto_fill_multi_ios(struct hda_codec *codec,
+                                  unsigned int location)
+{
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int type, i, num_pins = 0;
+
+       for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+               for (i = 0; i < cfg->num_inputs; i++) {
+                       hda_nid_t nid = cfg->inputs[i].pin;
+                       hda_nid_t dac;
+                       unsigned int defcfg, caps;
+                       if (cfg->inputs[i].type != type)
+                               continue;
+                       defcfg = snd_hda_codec_get_pincfg(codec, nid);
+                       if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+                               continue;
+                       if (location && get_defcfg_location(defcfg) != location)
+                               continue;
+                       caps = snd_hda_query_pin_caps(codec, nid);
+                       if (!(caps & AC_PINCAP_OUT))
+                               continue;
+                       dac = alc_auto_look_for_dac(codec, nid);
+                       if (!dac)
+                               continue;
+                       spec->multi_io[num_pins].pin = nid;
+                       spec->multi_io[num_pins].dac = dac;
+                       num_pins++;
+                       spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+               }
+       }
+       spec->multiout.num_dacs = 1;
+       if (num_pins < 2)
+               return 0;
+       return num_pins;
+}
+
+static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_info *uinfo)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct alc_spec *spec = codec->spec;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = spec->multi_ios + 1;
+       if (uinfo->value.enumerated.item > spec->multi_ios)
+               uinfo->value.enumerated.item = spec->multi_ios;
+       sprintf(uinfo->value.enumerated.name, "%dch",
+               (uinfo->value.enumerated.item + 1) * 2);
+       return 0;
+}
+
+static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct alc_spec *spec = codec->spec;
+       ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
+       return 0;
+}
+
+static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
+{
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t nid = spec->multi_io[idx].pin;
+
+       if (!spec->multi_io[idx].ctl_in)
+               spec->multi_io[idx].ctl_in =
+                       snd_hda_codec_read(codec, nid, 0,
+                                          AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+       if (output) {
+               snd_hda_codec_update_cache(codec, nid, 0,
+                                          AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                          PIN_OUT);
+               if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+                       snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+                                                HDA_AMP_MUTE, 0);
+               alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
+       } else {
+               if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+                       snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+                                                HDA_AMP_MUTE, HDA_AMP_MUTE);
+               snd_hda_codec_update_cache(codec, nid, 0,
+                                          AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                          spec->multi_io[idx].ctl_in);
+       }
+       return 0;
+}
+
+static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct alc_spec *spec = codec->spec;
+       int i, ch;
+
+       ch = ucontrol->value.enumerated.item[0];
+       if (ch < 0 || ch > spec->multi_ios)
+               return -EINVAL;
+       if (ch == (spec->ext_channel_count - 1) / 2)
+               return 0;
+       spec->ext_channel_count = (ch + 1) * 2;
+       for (i = 0; i < spec->multi_ios; i++)
+               alc_set_multi_io(codec, i, i < ch);
+       spec->multiout.max_channels = spec->ext_channel_count;
+       return 1;
+}
+
+static struct snd_kcontrol_new alc_auto_channel_mode_enum = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Channel Mode",
+       .info = alc_auto_ch_mode_info,
+       .get = alc_auto_ch_mode_get,
+       .put = alc_auto_ch_mode_put,
+};
+
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       unsigned int location, defcfg;
+       int num_pins;
+
+       if (cfg->line_outs != 1 ||
+           cfg->line_out_type != AUTO_PIN_LINE_OUT)
+               return 0;
+
+       defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
+       location = get_defcfg_location(defcfg);
+
+       num_pins = alc_auto_fill_multi_ios(codec, location);
+       if (num_pins > 0) {
+               struct snd_kcontrol_new *knew;
+
+               knew = alc_kcontrol_new(spec);
+               if (!knew)
+                       return -ENOMEM;
+               *knew = alc_auto_channel_mode_enum;
+               knew->name = kstrdup("Channel Mode", GFP_KERNEL);
+               if (!knew->name)
+                       return -ENOMEM;
+
+               spec->multi_ios = num_pins;
+               spec->ext_channel_count = 2;
+               spec->multiout.num_dacs = num_pins + 1;
+       }
+       return 0;
+}
+
 static int alc662_parse_auto_config(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -19353,6 +19710,9 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
                return 0; /* can't find valid BIOS pin config */
 
        err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc_auto_add_multi_channel_mode(codec);
        if (err < 0)
                return err;
        err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
@@ -19385,14 +19745,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
 
-       add_verb(spec, alc662_init_verbs);
-       if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
-           codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
-               add_verb(spec, alc663_init_verbs);
-
-       if (codec->vendor_id == 0x10ec0272)
-               add_verb(spec, alc272_init_verbs);
-
        err = alc_auto_add_mic_boost(codec);
        if (err < 0)
                return err;
@@ -19438,6 +19790,7 @@ enum {
        ALC662_FIXUP_IDEAPAD,
        ALC272_FIXUP_MARIO,
        ALC662_FIXUP_CZC_P10T,
+       ALC662_FIXUP_GIGABYTE,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -19466,12 +19819,20 @@ static const struct alc_fixup alc662_fixups[] = {
                        {}
                }
        },
+       [ALC662_FIXUP_GIGABYTE] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x14, 0x1114410 }, /* set as speaker */
+                       { }
+               }
+       },
 };
 
 static struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
@@ -19585,6 +19946,7 @@ static int patch_alc662(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC662_AUTO)
                spec->init_hook = alc662_auto_init;
+       spec->shutup = alc_eapd_shutup;
 
        alc_init_jacks(codec);
 
@@ -19783,20 +20145,22 @@ static void alc680_base_setup(struct hda_codec *codec)
        spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
        spec->autocfg.inputs[1].pin = 0x19;
        spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
+       spec->automute = 1;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc680_unsol_event(struct hda_codec *codec,
                                           unsigned int res)
 {
        if ((res >> 26) == ALC880_HP_EVENT)
-               alc_automute_amp(codec);
+               alc_hp_automute(codec);
        if ((res >> 26) == ALC880_MIC_EVENT)
                alc680_rec_autoswitch(codec);
 }
 
 static void alc680_inithook(struct hda_codec *codec)
 {
-       alc_automute_amp(codec);
+       alc_hp_automute(codec);
        alc680_rec_autoswitch(codec);
 }