ALSA: hda - Improve auto-cfg mixer name for ALC880
[pandora-kernel.git] / sound / pci / hda / patch_realtek.c
index b2ea432..07fbf7d 100644 (file)
@@ -235,6 +235,8 @@ enum {
        ALC883_FUJITSU_PI2515,
        ALC888_FUJITSU_XA3530,
        ALC883_3ST_6ch_INTEL,
+       ALC889A_INTEL,
+       ALC889_INTEL,
        ALC888_ASUS_M90V,
        ALC888_ASUS_EEE1601,
        ALC889A_MB31,
@@ -256,6 +258,14 @@ enum {
        ALC_INIT_GPIO3,
 };
 
+struct alc_mic_route {
+       hda_nid_t pin;
+       unsigned char mux_idx;
+       unsigned char amix_idx;
+};
+
+#define MUX_IDX_UNDEF  ((unsigned char)-1)
+
 struct alc_spec {
        /* codec parameterization */
        struct snd_kcontrol_new *mixers[5];     /* mixer arrays */
@@ -269,13 +279,13 @@ struct alc_spec {
                                                 */
        unsigned int num_init_verbs;
 
-       char stream_name_analog[16];    /* analog PCM stream */
+       char stream_name_analog[32];    /* analog PCM stream */
        struct hda_pcm_stream *stream_analog_playback;
        struct hda_pcm_stream *stream_analog_capture;
        struct hda_pcm_stream *stream_analog_alt_playback;
        struct hda_pcm_stream *stream_analog_alt_capture;
 
-       char stream_name_digital[16];   /* digital PCM stream */
+       char stream_name_digital[32];   /* digital PCM stream */
        struct hda_pcm_stream *stream_digital_playback;
        struct hda_pcm_stream *stream_digital_capture;
 
@@ -298,6 +308,8 @@ struct alc_spec {
        unsigned int num_mux_defs;
        const struct hda_input_mux *input_mux;
        unsigned int cur_mux[3];
+       struct alc_mic_route ext_mic;
+       struct alc_mic_route int_mic;
 
        /* channel model */
        const struct hda_channel_mode *channel_mode;
@@ -325,6 +337,7 @@ struct alc_spec {
        unsigned int sense_updated: 1;
        unsigned int jack_present: 1;
        unsigned int master_sw: 1;
+       unsigned int auto_mic:1;
 
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
@@ -366,6 +379,7 @@ struct alc_config_preset {
        unsigned int num_mux_defs;
        const struct hda_input_mux *input_mux;
        void (*unsol_event)(struct hda_codec *, unsigned int);
+       void (*setup)(struct hda_codec *);
        void (*init_hook)(struct hda_codec *);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_amp_list *loopbacks;
@@ -413,7 +427,7 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
        mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
        imux = &spec->input_mux[mux_idx];
 
-       type = (get_wcaps(codec, nid) & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+       type = get_wcaps_type(get_wcaps(codec, nid));
        if (type == AC_WID_AUD_MIX) {
                /* Matrix-mixer style (e.g. ALC882) */
                unsigned int *cur_val = &spec->cur_mux[adc_idx];
@@ -555,7 +569,7 @@ static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
 
        /* Find enumerated value for current pinctl setting */
        i = alc_pin_mode_min(dir);
-       while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir))
+       while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
                i++;
        *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
        return 0;
@@ -838,9 +852,10 @@ static void print_realtek_coef(struct snd_info_buffer *buffer,
 /*
  * set up from the preset table
  */
-static void setup_preset(struct alc_spec *spec,
+static void setup_preset(struct hda_codec *codec,
                         const struct alc_config_preset *preset)
 {
+       struct alc_spec *spec = codec->spec;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
@@ -882,6 +897,9 @@ static void setup_preset(struct alc_spec *spec,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        spec->loopback.amplist = preset->loopbacks;
 #endif
+
+       if (preset->setup)
+               preset->setup(codec);
 }
 
 /* Enable GPIO mask and set output */
@@ -961,30 +979,64 @@ static void alc_automute_pin(struct hda_codec *codec)
        }
 }
 
-#if 0 /* it's broken in some cases -- temporarily disabled */
+static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
+                               hda_nid_t nid)
+{
+       hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+       int i, nums;
+
+       nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
+       for (i = 0; i < nums; i++)
+               if (conn[i] == nid)
+                       return i;
+       return -1;
+}
+
 static void alc_mic_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       unsigned int present;
-       unsigned int mic_nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
-       unsigned int fmic_nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
-       unsigned int mix_nid = spec->capsrc_nids[0];
-       unsigned int capsrc_idx_mic, capsrc_idx_fmic;
-
-       capsrc_idx_mic = mic_nid - 0x18;
-       capsrc_idx_fmic = fmic_nid - 0x18;
-       present = snd_hda_codec_read(codec, mic_nid, 0,
-                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                   0x7000 | (capsrc_idx_mic << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                   0x7000 | (capsrc_idx_fmic << 8) | (present ? 0x80 : 0));
-       snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic,
-                        HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+       struct alc_mic_route *dead, *alive;
+       unsigned int present, type;
+       hda_nid_t cap_nid;
+
+       if (!spec->auto_mic)
+               return;
+       if (!spec->int_mic.pin || !spec->ext_mic.pin)
+               return;
+       if (snd_BUG_ON(!spec->adc_nids))
+               return;
+
+       cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
+
+       present = snd_hda_codec_read(codec, spec->ext_mic.pin, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0);
+       present &= AC_PINSENSE_PRESENCE;
+       if (present) {
+               alive = &spec->ext_mic;
+               dead = &spec->int_mic;
+       } else {
+               alive = &spec->int_mic;
+               dead = &spec->ext_mic;
+       }
+
+       type = get_wcaps_type(get_wcaps(codec, cap_nid));
+       if (type == AC_WID_AUD_MIX) {
+               /* Matrix-mixer style (e.g. ALC882) */
+               snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
+                                        alive->mux_idx,
+                                        HDA_AMP_MUTE, 0);
+               snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
+                                        dead->mux_idx,
+                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
+       } else {
+               /* MUX style (e.g. ALC880) */
+               snd_hda_codec_write_cache(codec, cap_nid, 0,
+                                         AC_VERB_SET_CONNECT_SEL,
+                                         alive->mux_idx);
+       }
+
+       /* FIXME: analog mixer */
 }
-#else
-#define alc_mic_automute(codec) do {} while(0) /* NOP */
-#endif /* disabled */
 
 /* unsolicited event for HP jack sensing */
 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -1027,6 +1079,16 @@ static void alc888_coef_init(struct hda_codec *codec)
                                    AC_VERB_SET_PROC_COEF, 0x3030);
 }
 
+static void alc889_coef_init(struct hda_codec *codec)
+{
+       unsigned int tmp;
+
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
+       tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
+}
+
 static void alc_auto_init_amp(struct hda_codec *codec, int type)
 {
        unsigned int tmp;
@@ -1084,15 +1146,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
                case 0x10ec0885:
                case 0x10ec0887:
                case 0x10ec0889:
-                       snd_hda_codec_write(codec, 0x20, 0,
-                                           AC_VERB_SET_COEF_INDEX, 7);
-                       tmp = snd_hda_codec_read(codec, 0x20, 0,
-                                                AC_VERB_GET_PROC_COEF, 0);
-                       snd_hda_codec_write(codec, 0x20, 0,
-                                           AC_VERB_SET_COEF_INDEX, 7);
-                       snd_hda_codec_write(codec, 0x20, 0,
-                                           AC_VERB_SET_PROC_COEF,
-                                           tmp | 0x2010);
+                       alc889_coef_init(codec);
                        break;
                case 0x10ec0888:
                        alc888_coef_init(codec);
@@ -1138,6 +1192,55 @@ static void alc_init_auto_hp(struct hda_codec *codec)
        spec->unsol_event = alc_sku_unsol_event;
 }
 
+static void alc_init_auto_mic(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       hda_nid_t fixed, ext;
+       int i;
+
+       /* there must be only two mic inputs exclusively */
+       for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++)
+               if (cfg->input_pins[i])
+                       return;
+
+       fixed = ext = 0;
+       for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) {
+               hda_nid_t nid = cfg->input_pins[i];
+               unsigned int defcfg;
+               if (!nid)
+                       return;
+               defcfg = snd_hda_codec_get_pincfg(codec, nid);
+               switch (get_defcfg_connect(defcfg)) {
+               case AC_JACK_PORT_FIXED:
+                       if (fixed)
+                               return; /* already occupied */
+                       fixed = nid;
+                       break;
+               case AC_JACK_PORT_COMPLEX:
+                       if (ext)
+                               return; /* already occupied */
+                       ext = nid;
+                       break;
+               default:
+                       return; /* invalid entry */
+               }
+       }
+       if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
+               return; /* no unsol support */
+       snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
+                   ext, fixed);
+       spec->ext_mic.pin = ext;
+       spec->int_mic.pin = fixed;
+       spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
+       spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
+       spec->auto_mic = 1;
+       snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
+                                 AC_VERB_SET_UNSOLICITED_ENABLE,
+                                 AC_USRSP_EN | ALC880_MIC_EVENT);
+       spec->unsol_event = alc_sku_unsol_event;
+}
+
 /* check subsystem ID and set up device-specific initialization;
  * return 1 if initialized, 0 if invalid SSID
  */
@@ -1239,6 +1342,7 @@ do_sku:
        }
 
        alc_init_auto_hp(codec);
+       alc_init_auto_mic(codec);
        return 1;
 }
 
@@ -1251,6 +1355,7 @@ static void alc_ssid_check(struct hda_codec *codec,
                           "Enable default setup for auto mode as fallback\n");
                spec->init_amp = ALC_INIT_DEFAULT;
                alc_init_auto_hp(codec);
+               alc_init_auto_mic(codec);
        }
 }
 
@@ -1432,7 +1537,25 @@ static void alc_automute_amp_unsol_event(struct hda_codec *codec,
                alc_automute_amp(codec);
 }
 
-static void alc888_fujitsu_xa3530_init_hook(struct hda_codec *codec)
+static void alc889_automute_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       spec->autocfg.hp_pins[0] = 0x15;
+       spec->autocfg.speaker_pins[0] = 0x14;
+       spec->autocfg.speaker_pins[1] = 0x16;
+       spec->autocfg.speaker_pins[2] = 0x17;
+       spec->autocfg.speaker_pins[3] = 0x19;
+       spec->autocfg.speaker_pins[4] = 0x1a;
+}
+
+static void alc889_intel_init_hook(struct hda_codec *codec)
+{
+       alc889_coef_init(codec);
+       alc_automute_amp(codec);
+}
+
+static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -1440,7 +1563,6 @@ static void alc888_fujitsu_xa3530_init_hook(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 */
-       alc_automute_amp(codec);
 }
 
 /*
@@ -1639,16 +1761,15 @@ static struct snd_kcontrol_new alc888_base_mixer[] = {
        { } /* end */
 };
 
-static void alc888_acer_aspire_4930g_init_hook(struct hda_codec *codec)
+static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_amp(codec);
 }
 
-static void alc888_acer_aspire_6530g_init_hook(struct hda_codec *codec)
+static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -1656,10 +1777,9 @@ static void alc888_acer_aspire_6530g_init_hook(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
-       alc_automute_amp(codec);
 }
 
-static void alc889_acer_aspire_8930g_init_hook(struct hda_codec *codec)
+static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -1667,7 +1787,6 @@ static void alc889_acer_aspire_8930g_init_hook(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x1b;
-       alc_automute_amp(codec);
 }
 
 /*
@@ -2647,13 +2766,17 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec)
        snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
 }
 
-static void alc880_uniwill_init_hook(struct hda_codec *codec)
+static void alc880_uniwill_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x16;
+}
+
+static void alc880_uniwill_init_hook(struct hda_codec *codec)
+{
        alc_automute_amp(codec);
        alc880_uniwill_mic_automute(codec);
 }
@@ -2674,13 +2797,12 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
        }
 }
 
-static void alc880_uniwill_p53_init_hook(struct hda_codec *codec)
+static void alc880_uniwill_p53_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       alc_automute_amp(codec);
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -2943,13 +3065,12 @@ static struct hda_verb alc880_lg_init_verbs[] = {
 };
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_init_hook(struct hda_codec *codec)
+static void alc880_lg_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x17;
-       alc_automute_amp(codec);
 }
 
 /*
@@ -3028,13 +3149,12 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = {
 };
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_lw_init_hook(struct hda_codec *codec)
+static void alc880_lg_lw_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_amp(codec);
 }
 
 static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
@@ -3100,13 +3220,12 @@ static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
                alc880_medion_rim_automute(codec);
 }
 
-static void alc880_medion_rim_init_hook(struct hda_codec *codec)
+static void alc880_medion_rim_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
-       alc880_medion_rim_automute(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -3973,7 +4092,8 @@ static struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_2_jack_modes,
                .input_mux = &alc880_f1734_capture_source,
                .unsol_event = alc880_uniwill_p53_unsol_event,
-               .init_hook = alc880_uniwill_p53_init_hook,
+               .setup = alc880_uniwill_p53_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC880_ASUS] = {
                .mixers = { alc880_asus_mixer },
@@ -4050,6 +4170,7 @@ static struct alc_config_preset alc880_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc880_capture_source,
                .unsol_event = alc880_uniwill_unsol_event,
+               .setup = alc880_uniwill_setup,
                .init_hook = alc880_uniwill_init_hook,
        },
        [ALC880_UNIWILL_P53] = {
@@ -4062,7 +4183,8 @@ static struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_threestack_modes,
                .input_mux = &alc880_capture_source,
                .unsol_event = alc880_uniwill_p53_unsol_event,
-               .init_hook = alc880_uniwill_p53_init_hook,
+               .setup = alc880_uniwill_p53_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC880_FUJITSU] = {
                .mixers = { alc880_fujitsu_mixer },
@@ -4076,7 +4198,8 @@ static struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_2_jack_modes,
                .input_mux = &alc880_capture_source,
                .unsol_event = alc880_uniwill_p53_unsol_event,
-               .init_hook = alc880_uniwill_p53_init_hook,
+               .setup = alc880_uniwill_p53_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC880_CLEVO] = {
                .mixers = { alc880_three_stack_mixer },
@@ -4102,7 +4225,8 @@ static struct alc_config_preset alc880_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc880_lg_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc880_lg_init_hook,
+               .setup = alc880_lg_setup,
+               .init_hook = alc_automute_amp,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
                .loopbacks = alc880_lg_loopbacks,
 #endif
@@ -4118,7 +4242,8 @@ static struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_lg_lw_modes,
                .input_mux = &alc880_lg_lw_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc880_lg_lw_init_hook,
+               .setup = alc880_lg_lw_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC880_MEDION_RIM] = {
                .mixers = { alc880_medion_rim_mixer },
@@ -4132,7 +4257,8 @@ static struct alc_config_preset alc880_presets[] = {
                .channel_mode = alc880_2_jack_modes,
                .input_mux = &alc880_medion_rim_capture_source,
                .unsol_event = alc880_medion_rim_unsol_event,
-               .init_hook = alc880_medion_rim_init_hook,
+               .setup = alc880_medion_rim_setup,
+               .init_hook = alc880_medion_rim_automute,
        },
 #ifdef CONFIG_SND_DEBUG
        [ALC880_TEST] = {
@@ -4185,8 +4311,6 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
 #define alc880_fixed_pin_idx(nid)      ((nid) - 0x14)
 #define alc880_is_multi_pin(nid)       ((nid) >= 0x18)
 #define alc880_multi_pin_idx(nid)      ((nid) - 0x18)
-#define alc880_is_input_pin(nid)       ((nid) >= 0x18)
-#define alc880_input_pin_idx(nid)      ((nid) - 0x18)
 #define alc880_idx_to_dac(nid)         ((nid) + 0x02)
 #define alc880_dac_to_idx(nid)         ((nid) - 0x02)
 #define alc880_idx_to_mixer(nid)       ((nid) + 0x0c)
@@ -4274,13 +4398,19 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                        if (err < 0)
                                return err;
                } else {
-                       sprintf(name, "%s Playback Volume", chname[i]);
+                       const char *pfx;
+                       if (cfg->line_outs == 1 &&
+                           cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+                               pfx = "Speaker";
+                       else
+                               pfx = chname[i];
+                       sprintf(name, "%s Playback Volume", pfx);
                        err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
-                       sprintf(name, "%s Playback Switch", chname[i]);
+                       sprintf(name, "%s Playback Switch", pfx);
                        err = add_control(spec, ALC_CTL_BIND_MUTE, name,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 2,
                                                              HDA_INPUT));
@@ -4354,31 +4484,61 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
        return 0;
 }
 
+static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
+{
+       unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
+       return (pincap & AC_PINCAP_IN) != 0;
+}
+
 /* create playback/capture controls for input pins */
-static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
-                                               const struct auto_pin_cfg *cfg)
+static int alc_auto_create_input_ctls(struct hda_codec *codec,
+                                     const struct auto_pin_cfg *cfg,
+                                     hda_nid_t mixer,
+                                     hda_nid_t cap1, hda_nid_t cap2)
 {
+       struct alc_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
        int i, err, idx;
 
        for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (alc880_is_input_pin(cfg->input_pins[i])) {
-                       idx = alc880_input_pin_idx(cfg->input_pins[i]);
-                       err = new_analog_input(spec, cfg->input_pins[i],
-                                              auto_pin_cfg_labels[i],
-                                              idx, 0x0b);
-                       if (err < 0)
-                               return err;
+               hda_nid_t pin;
+
+               pin = cfg->input_pins[i];
+               if (!alc_is_input_pin(codec, pin))
+                       continue;
+
+               if (mixer) {
+                       idx = get_connection_index(codec, mixer, pin);
+                       if (idx >= 0) {
+                               err = new_analog_input(spec, pin,
+                                                      auto_pin_cfg_labels[i],
+                                                      idx, mixer);
+                               if (err < 0)
+                                       return err;
+                       }
+               }
+
+               if (!cap1)
+                       continue;
+               idx = get_connection_index(codec, cap1, pin);
+               if (idx < 0 && cap2)
+                       idx = get_connection_index(codec, cap2, pin);
+               if (idx >= 0) {
                        imux->items[imux->num_items].label =
                                auto_pin_cfg_labels[i];
-                       imux->items[imux->num_items].index =
-                               alc880_input_pin_idx(cfg->input_pins[i]);
+                       imux->items[imux->num_items].index = idx;
                        imux->num_items++;
                }
        }
        return 0;
 }
 
+static int alc880_auto_create_input_ctls(struct hda_codec *codec,
+                                               const struct auto_pin_cfg *cfg)
+{
+       return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x08, 0x09);
+}
+
 static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
                               unsigned int pin_type)
 {
@@ -4444,7 +4604,7 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec)
 
        for (i = 0; i < AUTO_PIN_LAST; i++) {
                hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (alc880_is_input_pin(nid)) {
+               if (alc_is_input_pin(codec, nid)) {
                        alc_set_input_pin(codec, nid, i);
                        if (nid != ALC880_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
@@ -4487,7 +4647,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
                                           "Headphone");
        if (err < 0)
                return err;
-       err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = alc880_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -4501,12 +4661,6 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
                                              &dig_nid, 1);
                if (err < 0)
                        continue;
-               if (dig_nid > 0x7f) {
-                       printk(KERN_ERR "alc880_auto: invalid dig_nid "
-                               "connection 0x%x for NID 0x%x\n", dig_nid,
-                               spec->autocfg.dig_out_pins[i]);
-                       continue;
-               }
                if (!i)
                        spec->multiout.dig_out_nid = dig_nid;
                else {
@@ -4543,8 +4697,42 @@ static void alc880_auto_init(struct hda_codec *codec)
                alc_inithook(codec);
 }
 
-static void set_capture_mixer(struct alc_spec *spec)
+/* check the ADC/MUX contains all input pins; some ADC/MUX contains only
+ * one of two digital mic pins, e.g. on ALC272
+ */
+static void fixup_automic_adc(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       int i;
+
+       for (i = 0; i < spec->num_adc_nids; i++) {
+               hda_nid_t cap = spec->capsrc_nids ?
+                       spec->capsrc_nids[i] : spec->adc_nids[i];
+               int iidx, eidx;
+
+               iidx = get_connection_index(codec, cap, spec->int_mic.pin);
+               if (iidx < 0)
+                       continue;
+               eidx = get_connection_index(codec, cap, spec->ext_mic.pin);
+               if (eidx < 0)
+                       continue;
+               spec->int_mic.mux_idx = iidx;
+               spec->ext_mic.mux_idx = eidx;
+               if (spec->capsrc_nids)
+                       spec->capsrc_nids += i;
+               spec->adc_nids += i;
+               spec->num_adc_nids = 1;
+               return;
+       }
+       snd_printd(KERN_INFO "hda_codec: %s: "
+                  "No ADC/MUX containing both 0x%x and 0x%x pins\n",
+                  codec->chip_name, spec->int_mic.pin, spec->ext_mic.pin);
+       spec->auto_mic = 0; /* disable auto-mic to be sure */
+}
+
+static void set_capture_mixer(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
        static struct snd_kcontrol_new *caps[2][3] = {
                { alc_capture_mixer_nosrc1,
                  alc_capture_mixer_nosrc2,
@@ -4555,7 +4743,10 @@ static void set_capture_mixer(struct alc_spec *spec)
        };
        if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
                int mux;
-               if (spec->input_mux && spec->input_mux->num_items > 1)
+               if (spec->auto_mic) {
+                       mux = 0;
+                       fixup_automic_adc(codec);
+               } else if (spec->input_mux && spec->input_mux->num_items > 1)
                        mux = 1;
                else
                        mux = 0;
@@ -4586,8 +4777,8 @@ static int patch_alc880(struct hda_codec *codec)
                                                  alc880_models,
                                                  alc880_cfg_tbl);
        if (board_config < 0) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC880_AUTO;
        }
 
@@ -4612,7 +4803,7 @@ static int patch_alc880(struct hda_codec *codec)
        }
 
        if (board_config != ALC880_AUTO)
-               setup_preset(spec, &alc880_presets[board_config]);
+               setup_preset(codec, &alc880_presets[board_config]);
 
        spec->stream_analog_playback = &alc880_pcm_analog_playback;
        spec->stream_analog_capture = &alc880_pcm_analog_capture;
@@ -4625,7 +4816,7 @@ static int patch_alc880(struct hda_codec *codec)
                /* check whether NID 0x07 is valid */
                unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
                /* get type */
-               wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+               wcap = get_wcaps_type(wcap);
                if (wcap != AC_WID_AUD_IN) {
                        spec->adc_nids = alc880_adc_nids_alt;
                        spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
@@ -4634,7 +4825,7 @@ static int patch_alc880(struct hda_codec *codec)
                        spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
                }
        }
-       set_capture_mixer(spec);
+       set_capture_mixer(codec);
        set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
        spec->vmaster_nid = 0x0c;
@@ -5849,39 +6040,10 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
 }
 
 /* create playback/capture controls for input pins */
-static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
+static int alc260_auto_create_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (cfg->input_pins[i] >= 0x12) {
-                       idx = cfg->input_pins[i] - 0x12;
-                       err = new_analog_input(spec, cfg->input_pins[i],
-                                              auto_pin_cfg_labels[i], idx,
-                                              0x07);
-                       if (err < 0)
-                               return err;
-                       imux->items[imux->num_items].label =
-                               auto_pin_cfg_labels[i];
-                       imux->items[imux->num_items].index = idx;
-                       imux->num_items++;
-               }
-               if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){
-                       idx = cfg->input_pins[i] - 0x09;
-                       err = new_analog_input(spec, cfg->input_pins[i],
-                                              auto_pin_cfg_labels[i], idx,
-                                              0x07);
-                       if (err < 0)
-                               return err;
-                       imux->items[imux->num_items].label =
-                               auto_pin_cfg_labels[i];
-                       imux->items[imux->num_items].index = idx;
-                       imux->num_items++;
-               }
-       }
-       return 0;
+       return alc_auto_create_input_ctls(codec, cfg, 0x07, 0x04, 0x05);
 }
 
 static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
@@ -5995,7 +6157,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
                return err;
        if (!spec->kctls.list)
                return 0; /* can't find valid BIOS pin config */
-       err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = alc260_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -6230,8 +6392,7 @@ static int patch_alc260(struct hda_codec *codec)
                                                  alc260_models,
                                                  alc260_cfg_tbl);
        if (board_config < 0) {
-               snd_printd(KERN_INFO "hda_codec: Unknown model for %s, "
-                          "trying auto-probe from BIOS...\n",
+               snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
                           codec->chip_name);
                board_config = ALC260_AUTO;
        }
@@ -6257,7 +6418,7 @@ static int patch_alc260(struct hda_codec *codec)
        }
 
        if (board_config != ALC260_AUTO)
-               setup_preset(spec, &alc260_presets[board_config]);
+               setup_preset(codec, &alc260_presets[board_config]);
 
        spec->stream_analog_playback = &alc260_pcm_analog_playback;
        spec->stream_analog_capture = &alc260_pcm_analog_capture;
@@ -6268,7 +6429,7 @@ static int patch_alc260(struct hda_codec *codec)
        if (!spec->adc_nids && spec->input_mux) {
                /* check whether NID 0x04 is valid */
                unsigned int wcap = get_wcaps(codec, 0x04);
-               wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+               wcap = get_wcaps_type(wcap);
                /* get type */
                if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
                        spec->adc_nids = alc260_adc_nids_alt;
@@ -6278,7 +6439,7 @@ static int patch_alc260(struct hda_codec *codec)
                        spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
                }
        }
-       set_capture_mixer(spec);
+       set_capture_mixer(codec);
        set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
 
        spec->vmaster_nid = 0x08;
@@ -6354,6 +6515,15 @@ static struct hda_input_mux alc882_capture_source = {
 
 #define alc883_capture_source  alc882_capture_source
 
+static struct hda_input_mux alc889_capture_source = {
+       .num_items = 3,
+       .items = {
+               { "Front Mic", 0x0 },
+               { "Mic", 0x3 },
+               { "Line", 0x2 },
+       },
+};
+
 static struct hda_input_mux mb5_capture_source = {
        .num_items = 3,
        .items = {
@@ -6674,6 +6844,52 @@ static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
        { 6, alc883_3ST_ch6_intel_init },
 };
 
+/*
+ * 2ch mode
+ */
+static struct hda_verb alc889_ch2_intel_init[] = {
+       { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc889_ch6_intel_init[] = {
+       { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
+       { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
+       { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static struct hda_verb alc889_ch8_intel_init[] = {
+       { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
+       { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
+       { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
+       { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
+       { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       { } /* end */
+};
+
+static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
+       { 2, alc889_ch2_intel_init },
+       { 6, alc889_ch6_intel_init },
+       { 8, alc889_ch8_intel_init },
+};
+
 /*
  * 6ch mode
  */
@@ -6935,37 +7151,139 @@ static struct hda_verb alc882_eapd_verbs[] = {
        { }
 };
 
-#define alc883_init_verbs      alc882_base_init_verbs
+static struct hda_verb alc889_eapd_verbs[] = {
+       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       { }
+};
 
-/* Mac Pro test */
-static struct snd_kcontrol_new alc882_macpro_mixer[] = {
-       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-       HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
-       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
-       /* FIXME: this looks suspicious...
-       HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
-       */
-       { } /* end */
+static struct hda_verb alc_hp15_unsol_verbs[] = {
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {}
 };
 
-static struct hda_verb alc882_macpro_init_verbs[] = {
+static struct hda_verb alc885_init_verbs[] = {
        /* Front mixer: unmute input/output amp left and right (volume = 0) */
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       /* Front Pin: output 0 (0x0c) */
-       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       /* Rear mixer */
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       /* CLFE mixer */
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       /* Side mixer */
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+       /* mute analog input loopbacks */
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+
+       /* Front HP Pin: output 0 (0x0c) */
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* Front Pin: output 0 (0x0c) */
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* Rear Pin: output 1 (0x0d) */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
+       /* CLFE Pin: output 2 (0x0e) */
+       {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+       /* Side Pin: output 3 (0x0f) */
+       {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+       /* Mic (rear) pin: input vref at 80% */
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
        /* Front Mic pin: input vref at 80% */
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       /* Speaker:  output */
-       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Line In pin: input */
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+       /* Mixer elements: 0x18, , 0x1a, 0x1b */
+       /* Input mixer1 */
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       /* Input mixer2 */
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       /* Input mixer3 */
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+       /* ADC2: mute amp left and right */
+       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       /* ADC3: mute amp left and right */
+       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+
+       { }
+};
+
+static struct hda_verb alc885_init_input_verbs[] = {
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+       { }
+};
+
+
+/* Unmute Selector 24h and set the default input to front mic */
+static struct hda_verb alc889_init_input_verbs[] = {
+       {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       { }
+};
+
+
+#define alc883_init_verbs      alc882_base_init_verbs
+
+/* Mac Pro test */
+static struct snd_kcontrol_new alc882_macpro_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
+       /* FIXME: this looks suspicious...
+       HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       */
+       { } /* end */
+};
+
+static struct hda_verb alc882_macpro_init_verbs[] = {
+       /* Front mixer: unmute input/output amp left and right (volume = 0) */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+       /* Front Pin: output 0 (0x0c) */
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+       /* Front Mic pin: input vref at 80% */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Speaker:  output */
+       {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
        /* Headphone output (output 0 - 0x0c) */
        {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -7140,23 +7458,21 @@ static struct hda_verb alc885_imac24_init_verbs[] = {
 };
 
 /* Toggle speaker-output according to the hp-jack state */
-static void alc885_imac24_automute_init_hook(struct hda_codec *codec)
+static void alc885_imac24_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
        spec->autocfg.speaker_pins[1] = 0x1a;
-       alc_automute_amp(codec);
 }
 
-static void alc885_mbp3_init_hook(struct hda_codec *codec)
+static void alc885_mbp3_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_amp(codec);
 }
 
 
@@ -7184,13 +7500,12 @@ static void alc882_targa_automute(struct hda_codec *codec)
                                  spec->jack_present ? 1 : 3);
 }
 
-static void alc882_targa_init_hook(struct hda_codec *codec)
+static void alc882_targa_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
-       alc882_targa_automute(codec);
 }
 
 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -7278,7 +7593,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);
-       alc885_imac24_automute_init_hook(codec);
+       alc_automute_amp(codec);
 }
 
 /*
@@ -7503,6 +7818,30 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+                             HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x1b, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
 static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
        HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7744,14 +8083,13 @@ static struct snd_kcontrol_new alc883_chmode_mixer[] = {
 };
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc883_mitac_init_hook(struct hda_codec *codec)
+static void alc883_mitac_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x17;
-       alc_automute_amp(codec);
 }
 
 /* auto-toggle front mic */
@@ -7906,7 +8244,7 @@ static struct hda_verb alc883_vaiott_verbs[] = {
        { } /* end */
 };
 
-static void alc888_3st_hp_init_hook(struct hda_codec *codec)
+static void alc888_3st_hp_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -7914,7 +8252,6 @@ static void alc888_3st_hp_init_hook(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x18;
-       alc_automute_amp(codec);
 }
 
 static struct hda_verb alc888_3st_hp_verbs[] = {
@@ -8011,13 +8348,12 @@ static struct hda_verb alc883_medion_md2_verbs[] = {
 };
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc883_medion_md2_init_hook(struct hda_codec *codec)
+static void alc883_medion_md2_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       alc_automute_amp(codec);
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -8034,12 +8370,16 @@ static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
                                 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
 }
 
-static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
+static void alc883_clevo_m720_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
+}
+
+static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
+{
        alc_automute_amp(codec);
        alc883_clevo_m720_mic_automute(codec);
 }
@@ -8058,22 +8398,20 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
 }
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc883_2ch_fujitsu_pi2515_init_hook(struct hda_codec *codec)
+static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       alc_automute_amp(codec);
 }
 
-static void alc883_haier_w66_init_hook(struct hda_codec *codec)
+static void alc883_haier_w66_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_amp(codec);
 }
 
 static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
@@ -8112,14 +8450,13 @@ static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
 }
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc883_acer_aspire_init_hook(struct hda_codec *codec)
+static void alc883_acer_aspire_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
        spec->autocfg.speaker_pins[1] = 0x16;
-       alc_automute_amp(codec);
 }
 
 static struct hda_verb alc883_acer_eapd_verbs[] = {
@@ -8140,7 +8477,7 @@ static struct hda_verb alc883_acer_eapd_verbs[] = {
        { }
 };
 
-static void alc888_6st_dell_init_hook(struct hda_codec *codec)
+static void alc888_6st_dell_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -8149,10 +8486,9 @@ static void alc888_6st_dell_init_hook(struct hda_codec *codec)
        spec->autocfg.speaker_pins[1] = 0x15;
        spec->autocfg.speaker_pins[2] = 0x16;
        spec->autocfg.speaker_pins[3] = 0x17;
-       alc_automute_amp(codec);
 }
 
-static void alc888_lenovo_sky_init_hook(struct hda_codec *codec)
+static void alc888_lenovo_sky_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -8162,17 +8498,15 @@ static void alc888_lenovo_sky_init_hook(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x16;
        spec->autocfg.speaker_pins[3] = 0x17;
        spec->autocfg.speaker_pins[4] = 0x1a;
-       alc_automute_amp(codec);
 }
 
-static void alc883_vaiott_init_hook(struct hda_codec *codec)
+static void alc883_vaiott_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x17;
-       alc_automute_amp(codec);
 }
 
 static struct hda_verb alc888_asus_m90v_verbs[] = {
@@ -8185,19 +8519,7 @@ static struct hda_verb alc888_asus_m90v_verbs[] = {
        { } /* end */
 };
 
-static void alc883_nb_mic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
-}
-
-static void alc883_M90V_init_hook(struct hda_codec *codec)
+static void alc883_mode2_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
@@ -8205,26 +8527,11 @@ static void alc883_M90V_init_hook(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x15;
        spec->autocfg.speaker_pins[2] = 0x16;
-       alc_automute_pin(codec);
-}
-
-static void alc883_mode2_unsol_event(struct hda_codec *codec,
-                                          unsigned int res)
-{
-       switch (res >> 26) {
-       case ALC880_MIC_EVENT:
-               alc883_nb_mic_automute(codec);
-               break;
-       default:
-               alc_sku_unsol_event(codec, res);
-               break;
-       }
-}
-
-static void alc883_mode2_inithook(struct hda_codec *codec)
-{
-       alc883_M90V_init_hook(codec);
-       alc883_nb_mic_automute(codec);
+       spec->ext_mic.pin = 0x18;
+       spec->int_mic.pin = 0x19;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
 }
 
 static struct hda_verb alc888_asus_eee1601_verbs[] = {
@@ -8346,6 +8653,8 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {
        [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
        [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
        [ALC883_3ST_6ch_INTEL]  = "3stack-6ch-intel",
+       [ALC889A_INTEL]         = "intel-alc889a",
+       [ALC889_INTEL]          = "intel-x58",
        [ALC1200_ASUS_P5Q]      = "asus-p5q",
        [ALC889A_MB31]          = "mb31",
        [ALC883_SONY_VAIO_TT]   = "sony-vaio-tt",
@@ -8465,7 +8774,9 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
-       SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC883_3ST_6ch_INTEL),
+       SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
+       SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
+       SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
        SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
 
        {}
@@ -8551,7 +8862,8 @@ static struct alc_config_preset alc882_presets[] = {
                .dig_out_nid = ALC882_DIGOUT_NID,
                .dig_in_nid = ALC882_DIGIN_NID,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc885_mbp3_init_hook,
+               .setup = alc885_mbp3_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC885_MB5] = {
                .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
@@ -8588,6 +8900,7 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc882_ch_modes,
                .input_mux = &alc882_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
+               .setup = alc885_imac24_setup,
                .init_hook = alc885_imac24_init_hook,
        },
        [ALC882_TARGA] = {
@@ -8605,7 +8918,8 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc882_capture_source,
                .unsol_event = alc882_targa_unsol_event,
-               .init_hook = alc882_targa_init_hook,
+               .setup = alc882_targa_setup,
+               .init_hook = alc882_targa_automute,
        },
        [ALC882_ASUS_A7J] = {
                .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
@@ -8681,6 +8995,46 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_3stack_6ch_intel,
        },
+       [ALC889A_INTEL] = {
+               .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
+               .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
+                               alc_hp15_unsol_verbs },
+               .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+               .dac_nids = alc883_dac_nids,
+               .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
+               .adc_nids = alc889_adc_nids,
+               .dig_out_nid = ALC883_DIGOUT_NID,
+               .dig_in_nid = ALC883_DIGIN_NID,
+               .slave_dig_outs = alc883_slave_dig_outs,
+               .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
+               .channel_mode = alc889_8ch_intel_modes,
+               .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,
+               .need_dac_fix = 1,
+       },
+       [ALC889_INTEL] = {
+               .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
+               .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
+                               alc889_eapd_verbs, alc_hp15_unsol_verbs},
+               .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+               .dac_nids = alc883_dac_nids,
+               .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
+               .adc_nids = alc889_adc_nids,
+               .dig_out_nid = ALC883_DIGOUT_NID,
+               .dig_in_nid = ALC883_DIGIN_NID,
+               .slave_dig_outs = alc883_slave_dig_outs,
+               .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
+               .channel_mode = alc889_8ch_intel_modes,
+               .capsrc_nids = alc889_capsrc_nids,
+               .input_mux = &alc889_capture_source,
+               .setup = alc889_automute_setup,
+               .init_hook = alc889_intel_init_hook,
+               .unsol_event = alc_automute_amp_unsol_event,
+               .need_dac_fix = 1,
+       },
        [ALC883_6ST_DIG] = {
                .mixers = { alc883_base_mixer, alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs },
@@ -8704,7 +9058,8 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc883_targa_unsol_event,
-               .init_hook = alc883_targa_init_hook,
+               .setup = alc882_targa_setup,
+               .init_hook = alc882_targa_automute,
        },
        [ALC883_TARGA_2ch_DIG] = {
                .mixers = { alc883_targa_2ch_mixer},
@@ -8719,7 +9074,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc883_targa_unsol_event,
-               .init_hook = alc883_targa_init_hook,
+               .setup = alc882_targa_setup,
+               .init_hook = alc882_targa_automute,
        },
        [ALC883_TARGA_8ch_DIG] = {
                .mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -8737,7 +9093,8 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc883_targa_unsol_event,
-               .init_hook = alc883_targa_init_hook,
+               .setup = alc882_targa_setup,
+               .init_hook = alc882_targa_automute,
        },
        [ALC883_ACER] = {
                .mixers = { alc883_base_mixer },
@@ -8763,7 +9120,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_acer_aspire_init_hook,
+               .setup = alc883_acer_aspire_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_4930G] = {
                .mixers = { alc888_base_mixer,
@@ -8783,7 +9141,8 @@ static struct alc_config_preset alc882_presets[] = {
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_2_capture_sources,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc888_acer_aspire_4930g_init_hook,
+               .setup = alc888_acer_aspire_4930g_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_6530G] = {
                .mixers = { alc888_acer_aspire_6530_mixer },
@@ -8801,7 +9160,8 @@ static struct alc_config_preset alc882_presets[] = {
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_acer_aspire_6530_sources,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc888_acer_aspire_6530g_init_hook,
+               .setup = alc888_acer_aspire_6530g_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_8930G] = {
                .mixers = { alc888_base_mixer,
@@ -8822,7 +9182,8 @@ static struct alc_config_preset alc882_presets[] = {
                        ARRAY_SIZE(alc889_capture_sources),
                .input_mux = alc889_capture_sources,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc889_acer_aspire_8930g_init_hook,
+               .setup = alc889_acer_aspire_8930g_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC883_MEDION] = {
                .mixers = { alc883_fivestack_mixer,
@@ -8847,7 +9208,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_medion_md2_init_hook,
+               .setup = alc883_medion_md2_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC883_LAPTOP_EAPD] = {
                .mixers = { alc883_base_mixer },
@@ -8868,6 +9230,7 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc883_clevo_m720_unsol_event,
+               .setup = alc883_clevo_m720_setup,
                .init_hook = alc883_clevo_m720_init_hook,
        },
        [ALC883_LENOVO_101E_2ch] = {
@@ -8893,7 +9256,8 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_lenovo_nb0763_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_medion_md2_init_hook,
+               .setup = alc883_medion_md2_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_LENOVO_MS7195_DIG] = {
                .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -8918,7 +9282,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_haier_w66_init_hook,
+               .setup = alc883_haier_w66_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_3ST_HP] = {
                .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -8930,7 +9295,8 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc888_3st_hp_init_hook,
+               .setup = alc888_3st_hp_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_6ST_DELL] = {
                .mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -8943,7 +9309,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc888_6st_dell_init_hook,
+               .setup = alc888_6st_dell_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC883_MITAC] = {
                .mixers = { alc883_mitac_mixer },
@@ -8954,7 +9321,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_mitac_init_hook,
+               .setup = alc883_mitac_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC883_FUJITSU_PI2515] = {
                .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
@@ -8967,7 +9335,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_fujitsu_pi2515_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_2ch_fujitsu_pi2515_init_hook,
+               .setup = alc883_2ch_fujitsu_pi2515_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_FUJITSU_XA3530] = {
                .mixers = { alc888_base_mixer, alc883_chmode_mixer },
@@ -8985,7 +9354,8 @@ static struct alc_config_preset alc882_presets[] = {
                        ARRAY_SIZE(alc888_2_capture_sources),
                .input_mux = alc888_2_capture_sources,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc888_fujitsu_xa3530_init_hook,
+               .setup = alc888_fujitsu_xa3530_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_LENOVO_SKY] = {
                .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
@@ -8998,7 +9368,8 @@ static struct alc_config_preset alc882_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_lenovo_sky_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc888_lenovo_sky_init_hook,
+               .setup = alc888_lenovo_sky_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC888_ASUS_M90V] = {
                .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -9011,8 +9382,9 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
                .input_mux = &alc883_fujitsu_pi2515_capture_source,
-               .unsol_event = alc883_mode2_unsol_event,
-               .init_hook = alc883_mode2_inithook,
+               .unsol_event = alc_sku_unsol_event,
+               .setup = alc883_mode2_setup,
+               .init_hook = alc_inithook,
        },
        [ALC888_ASUS_EEE1601] = {
                .mixers = { alc883_asus_eee1601_mixer },
@@ -9065,7 +9437,8 @@ static struct alc_config_preset alc882_presets[] = {
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc883_vaiott_init_hook,
+               .setup = alc883_vaiott_setup,
+               .init_hook = alc_automute_amp,
        },
 };
 
@@ -9096,6 +9469,12 @@ static struct snd_pci_quirk alc882_pinfix_tbl[] = {
 /*
  * BIOS auto configuration
  */
+static int alc882_auto_create_input_ctls(struct hda_codec *codec,
+                                               const struct auto_pin_cfg *cfg)
+{
+       return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x23, 0x22);
+}
+
 static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid, int pin_type,
                                              int dac_idx)
@@ -9236,44 +9615,73 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
 static int alc882_parse_auto_config(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *autocfg = &spec->autocfg;
-       unsigned int wcap;
-       int i;
-       int err = alc880_parse_auto_config(codec);
+       static hda_nid_t alc882_ignore[] = { 0x1d, 0 };
+       int i, err;
 
+       err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+                                          alc882_ignore);
        if (err < 0)
                return err;
-       else if (!err)
-               return 0; /* no config found */
+       if (!spec->autocfg.line_outs)
+               return 0; /* can't find valid BIOS pin config */
 
-       err = alc_auto_add_mic_boost(codec);
+       err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
+       if (err < 0)
+               return err;
+       err = alc880_auto_create_extra_out(spec,
+                                          spec->autocfg.speaker_pins[0],
+                                          "Speaker");
+       if (err < 0)
+               return err;
+       err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
+                                          "Headphone");
        if (err < 0)
                return err;
+       err = alc882_auto_create_input_ctls(codec, &spec->autocfg);
+       if (err < 0)
+               return err;
+
+       spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+       /* check multiple SPDIF-out (for recent codecs) */
+       for (i = 0; i < spec->autocfg.dig_outs; i++) {
+               hda_nid_t dig_nid;
+               err = snd_hda_get_connections(codec,
+                                             spec->autocfg.dig_out_pins[i],
+                                             &dig_nid, 1);
+               if (err < 0)
+                       continue;
+               if (!i)
+                       spec->multiout.dig_out_nid = dig_nid;
+               else {
+                       spec->multiout.slave_dig_outs = spec->slave_dig_outs;
+                       spec->slave_dig_outs[i - 1] = dig_nid;
+                       if (i == ARRAY_SIZE(spec->slave_dig_outs) - 1)
+                               break;
+               }
+       }
+       if (spec->autocfg.dig_in_pin)
+               spec->dig_in_nid = ALC880_DIGIN_NID;
 
-       /* hack - override the init verbs */
-       spec->init_verbs[0] = alc883_auto_init_verbs;
+       if (spec->kctls.list)
+               add_mixer(spec, spec->kctls.list);
+
+       add_verb(spec, alc883_auto_init_verbs);
        /* if ADC 0x07 is available, initialize it, too */
-       wcap = get_wcaps(codec, 0x07);
-       wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-       if (wcap == AC_WID_AUD_IN)
+       if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
                add_verb(spec, alc882_adc1_init_verbs);
 
-       /* digital-mic input pin is excluded in alc880_auto_create..()
-        * because it's under 0x18
-        */
-       if (autocfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
-           autocfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
-               struct hda_input_mux *imux = &spec->private_imux[0];
-               for (i = 1; i < 3; i++)
-                       memcpy(&spec->private_imux[i],
-                              &spec->private_imux[0],
-                              sizeof(spec->private_imux[0]));
-               imux->items[imux->num_items].label = "Int DMic";
-               imux->items[imux->num_items].index = 0x0b;
-               imux->num_items++;
-               spec->num_mux_defs = 3;
-               spec->input_mux = spec->private_imux;
-       }
+       spec->num_mux_defs = 1;
+       spec->input_mux = &spec->private_imux[0];
+
+       alc_ssid_check(codec, 0x15, 0x1b, 0x14);
+
+       err = alc_auto_add_mic_boost(codec);
+       if (err < 0)
+               return err;
 
        return 1; /* config found */
 }
@@ -9320,8 +9728,7 @@ static int patch_alc882(struct hda_codec *codec)
                        ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
 
        if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n",
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
                       codec->chip_name);
                board_config = ALC882_AUTO;
        }
@@ -9349,7 +9756,7 @@ static int patch_alc882(struct hda_codec *codec)
        }
 
        if (board_config != ALC882_AUTO)
-               setup_preset(spec, &alc882_presets[board_config]);
+               setup_preset(codec, &alc882_presets[board_config]);
 
        spec->stream_analog_playback = &alc882_pcm_analog_playback;
        spec->stream_analog_capture = &alc882_pcm_analog_capture;
@@ -9371,7 +9778,7 @@ static int patch_alc882(struct hda_codec *codec)
                        hda_nid_t nid = alc882_adc_nids[i];
                        unsigned int wcap = get_wcaps(codec, nid);
                        /* get type */
-                       wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+                       wcap = get_wcaps_type(wcap);
                        if (wcap != AC_WID_AUD_IN)
                                continue;
                        spec->private_adc_nids[spec->num_adc_nids] = nid;
@@ -9385,7 +9792,7 @@ static int patch_alc882(struct hda_codec *codec)
                spec->capsrc_nids = spec->private_capsrc_nids;
        }
 
-       set_capture_mixer(spec);
+       set_capture_mixer(codec);
        set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
        spec->vmaster_nid = 0x0c;
@@ -9578,13 +9985,12 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
 };
 
 /* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hp_t5735_init_hook(struct hda_codec *codec)
+static void alc262_hp_t5735_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x0c; /* HACK: not actually a pin */
-       alc_automute_amp(codec);
 }
 
 static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@ -9741,22 +10147,20 @@ static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
        alc262_hippo_automute(codec);
 }
 
-static void alc262_hippo_init_hook(struct hda_codec *codec)
+static void alc262_hippo_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc262_hippo_automute(codec);
 }
 
-static void alc262_hippo1_init_hook(struct hda_codec *codec)
+static void alc262_hippo1_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc262_hippo_automute(codec);
 }
 
 
@@ -9813,13 +10217,12 @@ static struct hda_verb alc262_tyan_verbs[] = {
 };
 
 /* unsolicited event for HP jack sensing */
-static void alc262_tyan_init_hook(struct hda_codec *codec)
+static void alc262_tyan_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x15;
-       alc_automute_amp(codec);
 }
 
 
@@ -9911,12 +10314,6 @@ static struct hda_verb alc262_eapd_verbs[] = {
        { }
 };
 
-static struct hda_verb alc262_hippo_unsol_verbs[] = {
-       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-       {}
-};
-
 static struct hda_verb alc262_hippo1_unsol_verbs[] = {
        {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
        {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -9937,14 +10334,6 @@ static struct hda_verb alc262_sony_unsol_verbs[] = {
        {}
 };
 
-static struct hda_input_mux alc262_dmic_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "Int DMic", 0x9 },
-               { "Mic", 0x0 },
-       },
-};
-
 static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
        HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -9966,35 +10355,17 @@ static struct hda_verb alc262_toshiba_s06_verbs[] = {
        {}
 };
 
-static void alc262_dmic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                                       AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x22, 0,
-                               AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x09);
-}
-
-
-/* unsolicited event for HP jack sensing */
-static void alc262_toshiba_s06_unsol_event(struct hda_codec *codec,
-                                      unsigned int res)
-{
-       if ((res >> 26) == ALC880_MIC_EVENT)
-               alc262_dmic_automute(codec);
-       else
-               alc_sku_unsol_event(codec, res);
-}
-
-static void alc262_toshiba_s06_init_hook(struct hda_codec *codec)
+static void alc262_toshiba_s06_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_pin(codec);
-       alc262_dmic_automute(codec);
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x12;
+       spec->int_mic.mux_idx = 9;
+       spec->auto_mic = 1;
 }
 
 /*
@@ -10183,6 +10554,18 @@ static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
        alc262_lenovo_3000_automute(codec, 1);
 }
 
+static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
+                                 int dir, int idx, long *valp)
+{
+       int i, change = 0;
+
+       for (i = 0; i < 2; i++, valp++)
+               change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
+                                                  HDA_AMP_MUTE,
+                                                  *valp ? 0 : HDA_AMP_MUTE);
+       return change;
+}
+
 /* bind hp and internal speaker mute (with plug check) */
 static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
@@ -10191,13 +10574,8 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-                                                HDA_AMP_MUTE,
-                                                valp ? 0 : HDA_AMP_MUTE);
-       change |= snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
-                                                HDA_AMP_MUTE,
-                                                valp ? 0 : HDA_AMP_MUTE);
-
+       change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
+       change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
        if (change)
                alc262_fujitsu_automute(codec, 0);
        return change;
@@ -10232,10 +10610,7 @@ static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
-                                                HDA_AMP_MUTE,
-                                                valp ? 0 : HDA_AMP_MUTE);
-
+       change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
        if (change)
                alc262_lenovo_3000_automute(codec, 0);
        return change;
@@ -10485,27 +10860,8 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
        return 0;
 }
 
-static int alc262_auto_create_analog_input_ctls(struct alc_spec *spec,
-                                               const struct auto_pin_cfg *cfg)
-{
-       int err;
-
-       err = alc880_auto_create_analog_input_ctls(spec, cfg);
-       if (err < 0)
-               return err;
-       /* digital-mic input pin is excluded in alc880_auto_create..()
-        * because it's under 0x18
-        */
-       if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
-           cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
-               struct hda_input_mux *imux = &spec->private_imux[0];
-               imux->items[imux->num_items].label = "Int Mic";
-               imux->items[imux->num_items].index = 0x09;
-               imux->num_items++;
-       }
-       return 0;
-}
-
+#define alc262_auto_create_input_ctls \
+       alc880_auto_create_input_ctls
 
 /*
  * generic initialization of ADC, input mixers and output mixers
@@ -10823,7 +11179,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
        err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
        if (err < 0)
                return err;
-       err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = alc262_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -10954,7 +11310,7 @@ static struct alc_config_preset alc262_presets[] = {
        },
        [ALC262_HIPPO] = {
                .mixers = { alc262_hippo_mixer },
-               .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
+               .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
@@ -10963,7 +11319,8 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc262_hippo_unsol_event,
-               .init_hook = alc262_hippo_init_hook,
+               .setup = alc262_hippo_setup,
+               .init_hook = alc262_hippo_automute,
        },
        [ALC262_HIPPO_1] = {
                .mixers = { alc262_hippo1_mixer },
@@ -10976,7 +11333,8 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc262_hippo_unsol_event,
-               .init_hook = alc262_hippo1_init_hook,
+               .setup = alc262_hippo1_setup,
+               .init_hook = alc262_hippo_automute,
        },
        [ALC262_FUJITSU] = {
                .mixers = { alc262_fujitsu_mixer },
@@ -11039,7 +11397,8 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc262_hp_t5735_init_hook,
+               .setup = alc262_hp_t5735_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC262_HP_RP5700] = {
                .mixers = { alc262_hp_rp5700_mixer },
@@ -11070,11 +11429,13 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc262_hippo_unsol_event,
-               .init_hook = alc262_hippo_init_hook,
+               .setup = alc262_hippo_setup,
+               .init_hook = alc262_hippo_automute,
        },
        [ALC262_BENQ_T31] = {
                .mixers = { alc262_benq_t31_mixer },
-               .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs },
+               .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
+                               alc_hp15_unsol_verbs },
                .num_dacs = ARRAY_SIZE(alc262_dac_nids),
                .dac_nids = alc262_dac_nids,
                .hp_nid = 0x03,
@@ -11082,7 +11443,8 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc262_hippo_unsol_event,
-               .init_hook = alc262_hippo_init_hook,
+               .setup = alc262_hippo_setup,
+               .init_hook = alc262_hippo_automute,
        },
        [ALC262_ULTRA] = {
                .mixers = { alc262_ultra_mixer },
@@ -11134,9 +11496,9 @@ static struct alc_config_preset alc262_presets[] = {
                .dig_out_nid = ALC262_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc262_modes),
                .channel_mode = alc262_modes,
-               .input_mux = &alc262_dmic_capture_source,
-               .unsol_event = alc262_toshiba_s06_unsol_event,
-               .init_hook = alc262_toshiba_s06_init_hook,
+               .unsol_event = alc_sku_unsol_event,
+               .setup = alc262_toshiba_s06_setup,
+               .init_hook = alc_inithook,
        },
        [ALC262_TOSHIBA_RX1] = {
                .mixers = { alc262_toshiba_rx1_mixer },
@@ -11148,7 +11510,8 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc262_hippo_unsol_event,
-               .init_hook = alc262_hippo_init_hook,
+               .setup = alc262_hippo_setup,
+               .init_hook = alc262_hippo_automute,
        },
        [ALC262_TYAN] = {
                .mixers = { alc262_tyan_mixer },
@@ -11161,7 +11524,8 @@ static struct alc_config_preset alc262_presets[] = {
                .channel_mode = alc262_modes,
                .input_mux = &alc262_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc262_tyan_init_hook,
+               .setup = alc262_tyan_setup,
+               .init_hook = alc_automute_amp,
        },
 };
 
@@ -11196,8 +11560,8 @@ static int patch_alc262(struct hda_codec *codec)
                                                  alc262_cfg_tbl);
 
        if (board_config < 0) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC262_AUTO;
        }
 
@@ -11224,7 +11588,7 @@ static int patch_alc262(struct hda_codec *codec)
        }
 
        if (board_config != ALC262_AUTO)
-               setup_preset(spec, &alc262_presets[board_config]);
+               setup_preset(codec, &alc262_presets[board_config]);
 
        spec->stream_analog_playback = &alc262_pcm_analog_playback;
        spec->stream_analog_capture = &alc262_pcm_analog_capture;
@@ -11250,7 +11614,7 @@ static int patch_alc262(struct hda_codec *codec)
                        unsigned int wcap = get_wcaps(codec, 0x07);
 
                        /* get type */
-                       wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+                       wcap = get_wcaps_type(wcap);
                        if (wcap != AC_WID_AUD_IN) {
                                spec->adc_nids = alc262_adc_nids_alt;
                                spec->num_adc_nids =
@@ -11265,7 +11629,7 @@ static int patch_alc262(struct hda_codec *codec)
                }
        }
        if (!spec->cap_mixer && !spec->no_analog)
-               set_capture_mixer(spec);
+               set_capture_mixer(codec);
        if (!spec->no_analog)
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
@@ -11357,14 +11721,6 @@ static struct hda_verb alc268_toshiba_verbs[] = {
        { } /* end */
 };
 
-static struct hda_input_mux alc268_acer_lc_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "i-Mic", 0x6 },
-               { "E-Mic", 0x0 },
-       },
-};
-
 /* Acer specific */
 /* bind volumes of both NID 0x02 and 0x03 */
 static struct hda_bind_ctls alc268_acer_bind_master_vol = {
@@ -11406,12 +11762,7 @@ static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
        long *valp = ucontrol->value.integer.value;
        int change;
 
-       change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
-                                         HDA_AMP_MUTE,
-                                         valp[0] ? 0 : HDA_AMP_MUTE);
-       change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
-                                          HDA_AMP_MUTE,
-                                          valp[1] ? 0 : HDA_AMP_MUTE);
+       change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
        if (change)
                alc268_acer_automute(codec, 0);
        return change;
@@ -11488,7 +11839,8 @@ static struct hda_verb alc268_acer_verbs[] = {
 
 /* unsolicited event for HP jack sensing */
 #define alc268_toshiba_unsol_event     alc262_hippo_unsol_event
-#define alc268_toshiba_init_hook       alc262_hippo_init_hook
+#define alc268_toshiba_setup           alc262_hippo_setup
+#define alc268_toshiba_automute                alc262_hippo_automute
 
 static void alc268_acer_unsol_event(struct hda_codec *codec,
                                       unsigned int res)
@@ -11518,30 +11870,33 @@ static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
                                AMP_IN_MUTE(0), bits);
 }
 
-
-static void alc268_acer_mic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                               AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CONNECT_SEL,
-                           present ? 0x0 : 0x6);
-}
-
 static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
                                    unsigned int res)
 {
-       if ((res >> 26) == ALC880_HP_EVENT)
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
                alc268_aspire_one_speaker_automute(codec);
-       if ((res >> 26) == ALC880_MIC_EVENT)
-               alc268_acer_mic_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
+}
+
+static void alc268_acer_lc_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x12;
+       spec->int_mic.mux_idx = 6;
+       spec->auto_mic = 1;
 }
 
 static void alc268_acer_lc_init_hook(struct hda_codec *codec)
 {
        alc268_aspire_one_speaker_automute(codec);
-       alc268_acer_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 static struct snd_kcontrol_new alc268_dell_mixer[] = {
@@ -11559,17 +11914,22 @@ static struct hda_verb alc268_dell_verbs[] = {
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
        {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
        { }
 };
 
 /* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_dell_init_hook(struct hda_codec *codec)
+static void alc268_dell_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_pin(codec);
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
 }
 
 static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
@@ -11590,38 +11950,16 @@ static struct hda_verb alc267_quanta_il1_verbs[] = {
        { }
 };
 
-static void alc267_quanta_il1_mic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x23, 0,
-                           AC_VERB_SET_CONNECT_SEL,
-                           present ? 0x00 : 0x01);
-}
-
-static void alc267_quanta_il1_init_hook(struct hda_codec *codec)
+static void alc267_quanta_il1_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_pin(codec);
-       alc267_quanta_il1_mic_automute(codec);
-}
-
-static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
-                                          unsigned int res)
-{
-       switch (res >> 26) {
-       case ALC880_MIC_EVENT:
-               alc267_quanta_il1_mic_automute(codec);
-               break;
-       default:
-               alc_sku_unsol_event(codec, res);
-               break;
-       }
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
 }
 
 /*
@@ -11701,21 +12039,16 @@ static struct hda_verb alc268_volume_init_verbs[] = {
        { }
 };
 
+static struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
+       HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
+       { } /* end */
+};
+
 static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               /* The multiple "Capture Source" controls confuse alsamixer
-                * So call somewhat different..
-                */
-               /* .name = "Capture Source", */
-               .name = "Input Source",
-               .count = 1,
-               .info = alc_mux_enum_info,
-               .get = alc_mux_enum_get,
-               .put = alc_mux_enum_put,
-       },
+       _DEFINE_CAPSRC(1),
        { } /* end */
 };
 
@@ -11724,18 +12057,7 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = {
        HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
-       {
-               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-               /* The multiple "Capture Source" controls confuse alsamixer
-                * So call somewhat different..
-                */
-               /* .name = "Capture Source", */
-               .name = "Input Source",
-               .count = 2,
-               .info = alc_mux_enum_info,
-               .get = alc_mux_enum_get,
-               .put = alc_mux_enum_put,
-       },
+       _DEFINE_CAPSRC(2),
        { } /* end */
 };
 
@@ -11911,38 +12233,10 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
 }
 
 /* create playback/capture controls for input pins */
-static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
+static int alc268_auto_create_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, idx1;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               switch(cfg->input_pins[i]) {
-               case 0x18:
-                       idx1 = 0;       /* Mic 1 */
-                       break;
-               case 0x19:
-                       idx1 = 1;       /* Mic 2 */
-                       break;
-               case 0x1a:
-                       idx1 = 2;       /* Line In */
-                       break;
-               case 0x1c:
-                       idx1 = 3;       /* CD */
-                       break;
-               case 0x12:
-               case 0x13:
-                       idx1 = 6;       /* digital mics */
-                       break;
-               default:
-                       continue;
-               }
-               imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
-               imux->items[imux->num_items].index = idx1;
-               imux->num_items++;
-       }
-       return 0;
+       return alc_auto_create_input_ctls(codec, cfg, 0, 0x23, 0x24);
 }
 
 static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
@@ -12019,7 +12313,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
        err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
        if (err < 0)
                return err;
-       err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = alc268_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -12038,7 +12332,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
                add_mixer(spec, alc268_beep_mixer);
 
        add_verb(spec, alc268_volume_init_verbs);
-       spec->num_mux_defs = 1;
+       spec->num_mux_defs = 2;
        spec->input_mux = &spec->private_imux[0];
 
        err = alc_auto_add_mic_boost(codec);
@@ -12098,8 +12392,6 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
                           ALC268_TOSHIBA),
        SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
        SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
-       SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
-                          ALC268_TOSHIBA),
        SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
        SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
        SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
@@ -12107,9 +12399,19 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
        {}
 };
 
+/* Toshiba laptops have no unique PCI SSID but only codec SSID */
+static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
+       SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
+       SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
+                          ALC268_TOSHIBA),
+       {}
+};
+
 static struct alc_config_preset alc268_presets[] = {
        [ALC267_QUANTA_IL1] = {
-               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
+               .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
+                           alc268_capture_nosrc_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc267_quanta_il1_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -12119,9 +12421,9 @@ static struct alc_config_preset alc268_presets[] = {
                .hp_nid = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
                .channel_mode = alc268_modes,
-               .input_mux = &alc268_capture_source,
-               .unsol_event = alc267_quanta_il1_unsol_event,
-               .init_hook = alc267_quanta_il1_init_hook,
+               .unsol_event = alc_sku_unsol_event,
+               .setup = alc267_quanta_il1_setup,
+               .init_hook = alc_inithook,
        },
        [ALC268_3ST] = {
                .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
@@ -12153,10 +12455,11 @@ static struct alc_config_preset alc268_presets[] = {
                .channel_mode = alc268_modes,
                .input_mux = &alc268_capture_source,
                .unsol_event = alc268_toshiba_unsol_event,
-               .init_hook = alc268_toshiba_init_hook,
+               .setup = alc268_toshiba_setup,
+               .init_hook = alc268_toshiba_automute,
        },
        [ALC268_ACER] = {
-               .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
+               .mixers = { alc268_acer_mixer, alc268_capture_nosrc_mixer,
                            alc268_beep_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_verbs },
@@ -12192,7 +12495,7 @@ static struct alc_config_preset alc268_presets[] = {
        [ALC268_ACER_ASPIRE_ONE] = {
                .mixers = { alc268_acer_aspire_one_mixer,
                            alc268_beep_mixer,
-                           alc268_capture_alt_mixer },
+                           alc268_capture_nosrc_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_acer_aspire_one_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
@@ -12203,22 +12506,26 @@ static struct alc_config_preset alc268_presets[] = {
                .hp_nid = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
                .channel_mode = alc268_modes,
-               .input_mux = &alc268_acer_lc_capture_source,
                .unsol_event = alc268_acer_lc_unsol_event,
+               .setup = alc268_acer_lc_setup,
                .init_hook = alc268_acer_lc_init_hook,
        },
        [ALC268_DELL] = {
-               .mixers = { alc268_dell_mixer, alc268_beep_mixer },
+               .mixers = { alc268_dell_mixer, alc268_beep_mixer,
+                           alc268_capture_nosrc_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
                                alc268_dell_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
                .dac_nids = alc268_dac_nids,
+               .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
+               .adc_nids = alc268_adc_nids_alt,
+               .capsrc_nids = alc268_capsrc_nids,
                .hp_nid = 0x02,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
                .channel_mode = alc268_modes,
                .unsol_event = alc_sku_unsol_event,
-               .init_hook = alc268_dell_init_hook,
-               .input_mux = &alc268_capture_source,
+               .setup = alc268_dell_setup,
+               .init_hook = alc_inithook,
        },
        [ALC268_ZEPTO] = {
                .mixers = { alc268_base_mixer, alc268_capture_alt_mixer,
@@ -12235,8 +12542,8 @@ static struct alc_config_preset alc268_presets[] = {
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
                .channel_mode = alc268_modes,
                .input_mux = &alc268_capture_source,
-               .unsol_event = alc268_toshiba_unsol_event,
-               .init_hook = alc268_toshiba_init_hook
+               .setup = alc268_toshiba_setup,
+               .init_hook = alc268_toshiba_automute,
        },
 #ifdef CONFIG_SND_DEBUG
        [ALC268_TEST] = {
@@ -12273,9 +12580,13 @@ static int patch_alc268(struct hda_codec *codec)
                                                  alc268_models,
                                                  alc268_cfg_tbl);
 
+       if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
+               board_config = snd_hda_check_board_codec_sid_config(codec,
+                       ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
+
        if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC268_AUTO;
        }
 
@@ -12294,7 +12605,7 @@ static int patch_alc268(struct hda_codec *codec)
        }
 
        if (board_config != ALC268_AUTO)
-               setup_preset(spec, &alc268_presets[board_config]);
+               setup_preset(codec, &alc268_presets[board_config]);
 
        spec->stream_analog_playback = &alc268_pcm_analog_playback;
        spec->stream_analog_capture = &alc268_pcm_analog_capture;
@@ -12331,11 +12642,15 @@ static int patch_alc268(struct hda_codec *codec)
                int i;
 
                /* get type */
-               wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-               if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+               wcap = get_wcaps_type(wcap);
+               if (spec->auto_mic ||
+                   wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
                        spec->adc_nids = alc268_adc_nids_alt;
                        spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
-                       add_mixer(spec, alc268_capture_alt_mixer);
+                       if (spec->auto_mic || spec->input_mux->num_items == 1)
+                               add_mixer(spec, alc268_capture_nosrc_mixer);
+                       else
+                               add_mixer(spec, alc268_capture_alt_mixer);
                } else {
                        spec->adc_nids = alc268_adc_nids;
                        spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
@@ -12346,6 +12661,8 @@ static int patch_alc268(struct hda_codec *codec)
                for (i = 0; i < spec->num_adc_nids; i++)
                        snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
                                0, AC_VERB_SET_CONNECT_SEL,
+                               i < spec->num_mux_defs ?
+                               spec->input_mux[i].items[0].index :
                                spec->input_mux->items[0].index);
        }
 
@@ -12380,22 +12697,6 @@ static hda_nid_t alc269_capsrc_nids[1] = {
  *       not a mux!
  */
 
-static struct hda_input_mux alc269_eeepc_dmic_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "i-Mic", 0x5 },
-               { "e-Mic", 0x0 },
-       },
-};
-
-static struct hda_input_mux alc269_eeepc_amic_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "i-Mic", 0x1 },
-               { "e-Mic", 0x0 },
-       },
-};
-
 #define alc269_modes           alc260_modes
 #define alc269_capture_source  alc880_lg_lw_capture_source
 
@@ -12557,16 +12858,6 @@ static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
                        AC_VERB_SET_PROC_COEF, 0x480);
 }
 
-static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                               AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x23, 0,
-                           AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1);
-}
-
 static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
 {
        unsigned int present_laptop;
@@ -12593,10 +12884,14 @@ static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
 static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
                                    unsigned int res)
 {
-       if ((res >> 26) == ALC880_HP_EVENT)
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
                alc269_quanta_fl1_speaker_automute(codec);
-       if ((res >> 26) == ALC880_MIC_EVENT)
-               alc269_quanta_fl1_mic_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
 }
 
 static void alc269_lifebook_unsol_event(struct hda_codec *codec,
@@ -12608,10 +12903,20 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec,
                alc269_lifebook_mic_autoswitch(codec);
 }
 
+static void alc269_quanta_fl1_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
+}
+
 static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
 {
        alc269_quanta_fl1_speaker_automute(codec);
-       alc269_quanta_fl1_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 static void alc269_lifebook_init_hook(struct hda_codec *codec)
@@ -12656,60 +12961,44 @@ static void alc269_speaker_automute(struct hda_codec *codec)
                                AMP_IN_MUTE(0), bits);
 }
 
-static void alc269_eeepc_dmic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                               AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x23, 0,
-                               AC_VERB_SET_CONNECT_SEL,  (present ? 0 : 5));
-}
-
-static void alc269_eeepc_amic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                               AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                               0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                               0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
-}
-
 /* unsolicited event for HP jack sensing */
-static void alc269_eeepc_dmic_unsol_event(struct hda_codec *codec,
+static void alc269_eeepc_unsol_event(struct hda_codec *codec,
                                     unsigned int res)
 {
-       if ((res >> 26) == ALC880_HP_EVENT)
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
                alc269_speaker_automute(codec);
-
-       if ((res >> 26) == ALC880_MIC_EVENT)
-               alc269_eeepc_dmic_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc_mic_automute(codec);
+               break;
+       }
 }
 
-static void alc269_eeepc_dmic_inithook(struct hda_codec *codec)
+static void alc269_eeepc_dmic_setup(struct hda_codec *codec)
 {
-       alc269_speaker_automute(codec);
-       alc269_eeepc_dmic_automute(codec);
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x12;
+       spec->int_mic.mux_idx = 5;
+       spec->auto_mic = 1;
 }
 
-/* unsolicited event for HP jack sensing */
-static void alc269_eeepc_amic_unsol_event(struct hda_codec *codec,
-                                    unsigned int res)
+static void alc269_eeepc_amic_setup(struct hda_codec *codec)
 {
-       if ((res >> 26) == ALC880_HP_EVENT)
-               alc269_speaker_automute(codec);
-
-       if ((res >> 26) == ALC880_MIC_EVENT)
-               alc269_eeepc_amic_automute(codec);
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
 }
 
-static void alc269_eeepc_amic_inithook(struct hda_codec *codec)
+static void alc269_eeepc_inithook(struct hda_codec *codec)
 {
        alc269_speaker_automute(codec);
-       alc269_eeepc_amic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 /*
@@ -12782,89 +13071,10 @@ static struct hda_verb alc269_init_verbs[] = {
        { }
 };
 
-/* add playback controls from the parsed DAC table */
-static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,
-                                            const struct auto_pin_cfg *cfg)
-{
-       hda_nid_t nid;
-       int err;
-
-       spec->multiout.num_dacs = 1;    /* only use one dac */
-       spec->multiout.dac_nids = spec->private_dac_nids;
-       spec->multiout.dac_nids[0] = 2;
-
-       nid = cfg->line_out_pins[0];
-       if (nid) {
-               err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                 "Front Playback Volume",
-                                 HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT));
-               if (err < 0)
-                       return err;
-               err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                 "Front Playback Switch",
-                                 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
-               if (err < 0)
-                       return err;
-       }
-
-       nid = cfg->speaker_pins[0];
-       if (nid) {
-               if (!cfg->line_out_pins[0]) {
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                         "Speaker Playback Volume",
-                                         HDA_COMPOSE_AMP_VAL(0x02, 3, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               }
-               if (nid == 0x16) {
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Speaker Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 2, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               } else {
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Speaker Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               }
-       }
-       nid = cfg->hp_pins[0];
-       if (nid) {
-               /* spec->multiout.hp_nid = 2; */
-               if (!cfg->line_out_pins[0] && !cfg->speaker_pins[0]) {
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                         "Headphone Playback Volume",
-                                         HDA_COMPOSE_AMP_VAL(0x02, 3, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               }
-               if (nid == 0x16) {
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Headphone Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 2, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               } else {
-                       err = add_control(spec, ALC_CTL_WIDGET_MUTE,
-                                         "Headphone Playback Switch",
-                                         HDA_COMPOSE_AMP_VAL(nid, 3, 0,
-                                                             HDA_OUTPUT));
-                       if (err < 0)
-                               return err;
-               }
-       }
-       return 0;
-}
-
-#define alc269_auto_create_analog_input_ctls \
-       alc262_auto_create_analog_input_ctls
+#define alc269_auto_create_multi_out_ctls \
+       alc268_auto_create_multi_out_ctls
+#define alc269_auto_create_input_ctls \
+       alc268_auto_create_input_ctls
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 #define alc269_loopbacks       alc880_loopbacks
@@ -12914,7 +13124,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
        if (err < 0)
                return err;
-       err = alc269_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -12939,7 +13149,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
                return err;
 
        if (!spec->cap_mixer && !spec->no_analog)
-               set_capture_mixer(spec);
+               set_capture_mixer(codec);
 
        alc_ssid_check(codec, 0x15, 0x1b, 0x14);
 
@@ -13015,6 +13225,7 @@ static struct alc_config_preset alc269_presets[] = {
                .channel_mode = alc269_modes,
                .input_mux = &alc269_capture_source,
                .unsol_event = alc269_quanta_fl1_unsol_event,
+               .setup = alc269_quanta_fl1_setup,
                .init_hook = alc269_quanta_fl1_init_hook,
        },
        [ALC269_ASUS_EEEPC_P703] = {
@@ -13027,9 +13238,9 @@ static struct alc_config_preset alc269_presets[] = {
                .hp_nid = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc269_modes),
                .channel_mode = alc269_modes,
-               .input_mux = &alc269_eeepc_amic_capture_source,
-               .unsol_event = alc269_eeepc_amic_unsol_event,
-               .init_hook = alc269_eeepc_amic_inithook,
+               .unsol_event = alc269_eeepc_unsol_event,
+               .setup = alc269_eeepc_amic_setup,
+               .init_hook = alc269_eeepc_inithook,
        },
        [ALC269_ASUS_EEEPC_P901] = {
                .mixers = { alc269_eeepc_mixer },
@@ -13041,9 +13252,9 @@ static struct alc_config_preset alc269_presets[] = {
                .hp_nid = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc269_modes),
                .channel_mode = alc269_modes,
-               .input_mux = &alc269_eeepc_dmic_capture_source,
-               .unsol_event = alc269_eeepc_dmic_unsol_event,
-               .init_hook = alc269_eeepc_dmic_inithook,
+               .unsol_event = alc269_eeepc_unsol_event,
+               .setup = alc269_eeepc_dmic_setup,
+               .init_hook = alc269_eeepc_inithook,
        },
        [ALC269_FUJITSU] = {
                .mixers = { alc269_fujitsu_mixer },
@@ -13055,9 +13266,9 @@ static struct alc_config_preset alc269_presets[] = {
                .hp_nid = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc269_modes),
                .channel_mode = alc269_modes,
-               .input_mux = &alc269_eeepc_dmic_capture_source,
-               .unsol_event = alc269_eeepc_dmic_unsol_event,
-               .init_hook = alc269_eeepc_dmic_inithook,
+               .unsol_event = alc269_eeepc_unsol_event,
+               .setup = alc269_eeepc_dmic_setup,
+               .init_hook = alc269_eeepc_inithook,
        },
        [ALC269_LIFEBOOK] = {
                .mixers = { alc269_lifebook_mixer },
@@ -13092,8 +13303,8 @@ static int patch_alc269(struct hda_codec *codec)
                                                  alc269_cfg_tbl);
 
        if (board_config < 0) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC269_AUTO;
        }
 
@@ -13118,7 +13329,7 @@ static int patch_alc269(struct hda_codec *codec)
        }
 
        if (board_config != ALC269_AUTO)
-               setup_preset(spec, &alc269_presets[board_config]);
+               setup_preset(codec, &alc269_presets[board_config]);
 
        if (codec->subsystem_id == 0x17aa3bf8) {
                /* Due to a hardware problem on Lenovo Ideadpad, we need to
@@ -13137,9 +13348,11 @@ static int patch_alc269(struct hda_codec *codec)
        spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
        spec->capsrc_nids = alc269_capsrc_nids;
        if (!spec->cap_mixer)
-               set_capture_mixer(spec);
+               set_capture_mixer(codec);
        set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
 
+       spec->vmaster_nid = 0x02;
+
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC269_AUTO)
                spec->init_hook = alc269_auto_init;
@@ -13786,8 +13999,7 @@ static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
                return 0;
        for (i = 0; i < num; i++) {
                unsigned int type;
-               type = (get_wcaps(codec, srcs[i]) & AC_WCAP_TYPE)
-                       >> AC_WCAP_TYPE_SHIFT;
+               type = get_wcaps_type(get_wcaps(codec, srcs[i]));
                if (type != AC_WID_AUD_OUT)
                        continue;
                for (j = 0; j < spec->multiout.num_dacs; j++)
@@ -13893,49 +14105,10 @@ static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int alc861_auto_create_analog_input_ctls(struct hda_codec *codec,
+static int alc861_auto_create_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       struct alc_spec *spec = codec->spec;
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx, idx1;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               switch (cfg->input_pins[i]) {
-               case 0x0c:
-                       idx1 = 1;
-                       idx = 2;        /* Line In */
-                       break;
-               case 0x0f:
-                       idx1 = 2;
-                       idx = 2;        /* Line In */
-                       break;
-               case 0x0d:
-                       idx1 = 0;
-                       idx = 1;        /* Mic In */
-                       break;
-               case 0x10:
-                       idx1 = 3;
-                       idx = 1;        /* Mic In */
-                       break;
-               case 0x11:
-                       idx1 = 4;
-                       idx = 0;        /* CD */
-                       break;
-               default:
-                       continue;
-               }
-
-               err = new_analog_input(spec, cfg->input_pins[i],
-                                      auto_pin_cfg_labels[i], idx, 0x15);
-               if (err < 0)
-                       return err;
-
-               imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
-               imux->items[imux->num_items].index = idx1;
-               imux->num_items++;
-       }
-       return 0;
+       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x08, 0);
 }
 
 static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
@@ -14032,7 +14205,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
        err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = alc861_auto_create_analog_input_ctls(codec, &spec->autocfg);
+       err = alc861_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -14051,7 +14224,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
 
        spec->adc_nids = alc861_adc_nids;
        spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
-       set_capture_mixer(spec);
+       set_capture_mixer(codec);
 
        alc_ssid_check(codec, 0x0e, 0x0f, 0x0b);
 
@@ -14244,8 +14417,8 @@ static int patch_alc861(struct hda_codec *codec)
                                                  alc861_cfg_tbl);
 
        if (board_config < 0) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC861_AUTO;
        }
 
@@ -14270,7 +14443,7 @@ static int patch_alc861(struct hda_codec *codec)
        }
 
        if (board_config != ALC861_AUTO)
-               setup_preset(spec, &alc861_presets[board_config]);
+               setup_preset(codec, &alc861_presets[board_config]);
 
        spec->stream_analog_playback = &alc861_pcm_analog_playback;
        spec->stream_analog_capture = &alc861_pcm_analog_capture;
@@ -14673,12 +14846,15 @@ static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
                                 HDA_AMP_MUTE, bits);
 }
 
-static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
+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;
+}
+
+static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
+{
        alc_automute_amp(codec);
        alc861vd_lenovo_mic_automute(codec);
 }
@@ -14742,13 +14918,12 @@ static struct hda_verb alc861vd_dallas_verbs[] = {
 };
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc861vd_dallas_init_hook(struct hda_codec *codec)
+static void alc861vd_dallas_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       alc_automute_amp(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -14787,7 +14962,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
        SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
        SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
        /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
-       SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS),
+       SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
        SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
@@ -14862,6 +15037,7 @@ static struct alc_config_preset alc861vd_presets[] = {
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
                .unsol_event = alc861vd_lenovo_unsol_event,
+               .setup = alc861vd_lenovo_setup,
                .init_hook = alc861vd_lenovo_init_hook,
        },
        [ALC861VD_DALLAS] = {
@@ -14873,7 +15049,8 @@ static struct alc_config_preset alc861vd_presets[] = {
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_dallas_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc861vd_dallas_init_hook,
+               .setup = alc861vd_dallas_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC861VD_HP] = {
                .mixers = { alc861vd_hp_mixer },
@@ -14885,7 +15062,8 @@ static struct alc_config_preset alc861vd_presets[] = {
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_hp_capture_source,
                .unsol_event = alc_automute_amp_unsol_event,
-               .init_hook = alc861vd_dallas_init_hook,
+               .setup = alc861vd_dallas_setup,
+               .init_hook = alc_automute_amp,
        },
        [ALC660VD_ASUS_V1S] = {
                .mixers = { alc861vd_lenovo_mixer },
@@ -14900,6 +15078,7 @@ static struct alc_config_preset alc861vd_presets[] = {
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
                .unsol_event = alc861vd_lenovo_unsol_event,
+               .setup = alc861vd_lenovo_setup,
                .init_hook = alc861vd_lenovo_init_hook,
        },
 };
@@ -14907,6 +15086,13 @@ static struct alc_config_preset alc861vd_presets[] = {
 /*
  * BIOS auto configuration
  */
+static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
+                                               const struct auto_pin_cfg *cfg)
+{
+       return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
+}
+
+
 static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
                                hda_nid_t nid, int pin_type, int dac_idx)
 {
@@ -14941,7 +15127,6 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
                alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
 }
 
-#define alc861vd_is_input_pin(nid)     alc880_is_input_pin(nid)
 #define ALC861VD_PIN_CD_NID            ALC880_PIN_CD_NID
 
 static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
@@ -14951,7 +15136,7 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
 
        for (i = 0; i < AUTO_PIN_LAST; i++) {
                hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (alc861vd_is_input_pin(nid)) {
+               if (alc_is_input_pin(codec, nid)) {
                        alc_set_input_pin(codec, nid, i);
                        if (nid != ALC861VD_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
@@ -15114,7 +15299,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
                                             "Headphone");
        if (err < 0)
                return err;
-       err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = alc861vd_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -15168,8 +15353,8 @@ static int patch_alc861vd(struct hda_codec *codec)
                                                  alc861vd_cfg_tbl);
 
        if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC861VD_AUTO;
        }
 
@@ -15194,7 +15379,7 @@ static int patch_alc861vd(struct hda_codec *codec)
        }
 
        if (board_config != ALC861VD_AUTO)
-               setup_preset(spec, &alc861vd_presets[board_config]);
+               setup_preset(codec, &alc861vd_presets[board_config]);
 
        if (codec->vendor_id == 0x10ec0660) {
                /* always turn on EAPD */
@@ -15207,11 +15392,14 @@ static int patch_alc861vd(struct hda_codec *codec)
        spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
        spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
 
-       spec->adc_nids = alc861vd_adc_nids;
-       spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
-       spec->capsrc_nids = alc861vd_capsrc_nids;
+       if (!spec->adc_nids) {
+               spec->adc_nids = alc861vd_adc_nids;
+               spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
+       }
+       if (!spec->capsrc_nids)
+               spec->capsrc_nids = alc861vd_capsrc_nids;
 
-       set_capture_mixer(spec);
+       set_capture_mixer(codec);
        set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
        spec->vmaster_nid = 0x02;
@@ -15252,9 +15440,9 @@ static hda_nid_t alc272_dac_nids[2] = {
        0x02, 0x03
 };
 
-static hda_nid_t alc662_adc_nids[1] = {
+static hda_nid_t alc662_adc_nids[2] = {
        /* ADC1-2 */
-       0x09,
+       0x09, 0x08
 };
 
 static hda_nid_t alc272_adc_nids[1] = {
@@ -15262,7 +15450,7 @@ static hda_nid_t alc272_adc_nids[1] = {
        0x08,
 };
 
-static hda_nid_t alc662_capsrc_nids[1] = { 0x22 };
+static hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
 static hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
 
 
@@ -15286,14 +15474,6 @@ static struct hda_input_mux alc662_lenovo_101e_capture_source = {
        },
 };
 
-static struct hda_input_mux alc662_eeepc_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "i-Mic", 0x1 },
-               { "e-Mic", 0x0 },
-       },
-};
-
 static struct hda_input_mux alc663_capture_source = {
        .num_items = 3,
        .items = {
@@ -15303,23 +15483,7 @@ static struct hda_input_mux alc663_capture_source = {
        },
 };
 
-static struct hda_input_mux alc663_m51va_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "Ext-Mic", 0x0 },
-               { "D-Mic", 0x9 },
-       },
-};
-
-#if 1 /* set to 0 for testing other input sources below */
-static struct hda_input_mux alc272_nc10_capture_source = {
-       .num_items = 2,
-       .items = {
-               { "Autoselect Mic", 0x0 },
-               { "Internal Mic", 0x1 },
-       },
-};
-#else
+#if 0 /* set to 1 for testing other input sources below */
 static struct hda_input_mux alc272_nc10_capture_source = {
        .num_items = 16,
        .items = {
@@ -15988,47 +16152,44 @@ static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
                alc662_lenovo_101e_ispeaker_automute(codec);
 }
 
-static void alc662_eeepc_mic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-       snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
-       snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                           0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
-}
-
 /* unsolicited event for HP jack sensing */
 static void alc662_eeepc_unsol_event(struct hda_codec *codec,
                                     unsigned int res)
 {
        if ((res >> 26) == ALC880_MIC_EVENT)
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
        else
                alc262_hippo_unsol_event(codec, res);
 }
 
+static void alc662_eeepc_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       alc262_hippo1_setup(codec);
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x19;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
+}
+
 static void alc662_eeepc_inithook(struct hda_codec *codec)
 {
-       alc262_hippo1_init_hook(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc262_hippo_automute(codec);
+       alc_mic_automute(codec);
 }
 
-static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)
+static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
-       alc262_hippo_master_update(codec);
 }
 
+#define alc662_eeepc_ep20_inithook     alc262_hippo_master_update
+
 static void alc663_m51va_speaker_automute(struct hda_codec *codec)
 {
        unsigned int present;
@@ -16139,23 +16300,6 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
        }
 }
 
-static void alc663_m51va_mic_automute(struct hda_codec *codec)
-{
-       unsigned int present;
-
-       present = snd_hda_codec_read(codec, 0x18, 0,
-                       AC_VERB_GET_PIN_SENSE, 0)
-                       & AC_PINSENSE_PRESENCE;
-       snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                       0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                       0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
-       snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                       0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
-       snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-                       0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
-}
-
 static void alc663_m51va_unsol_event(struct hda_codec *codec,
                                           unsigned int res)
 {
@@ -16164,36 +16308,32 @@ static void alc663_m51va_unsol_event(struct hda_codec *codec,
                alc663_m51va_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc663_m51va_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+static void alc663_m51va_setup(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->ext_mic.pin = 0x18;
+       spec->ext_mic.mux_idx = 0;
+       spec->int_mic.pin = 0x12;
+       spec->int_mic.mux_idx = 1;
+       spec->auto_mic = 1;
+}
+
 static void alc663_m51va_inithook(struct hda_codec *codec)
 {
        alc663_m51va_speaker_automute(codec);
-       alc663_m51va_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 /* ***************** Mode1 ******************************/
-static void alc663_mode1_unsol_event(struct hda_codec *codec,
-                                          unsigned int res)
-{
-       switch (res >> 26) {
-       case ALC880_HP_EVENT:
-               alc663_m51va_speaker_automute(codec);
-               break;
-       case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
-               break;
-       }
-}
+#define alc663_mode1_unsol_event       alc663_m51va_unsol_event
+#define alc663_mode1_setup             alc663_m51va_setup
+#define alc663_mode1_inithook          alc663_m51va_inithook
 
-static void alc663_mode1_inithook(struct hda_codec *codec)
-{
-       alc663_m51va_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
-}
 /* ***************** Mode2 ******************************/
 static void alc662_mode2_unsol_event(struct hda_codec *codec,
                                           unsigned int res)
@@ -16203,15 +16343,17 @@ static void alc662_mode2_unsol_event(struct hda_codec *codec,
                alc662_f5z_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc662_mode2_setup     alc663_m51va_setup
+
 static void alc662_mode2_inithook(struct hda_codec *codec)
 {
        alc662_f5z_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 /* ***************** Mode3 ******************************/
 static void alc663_mode3_unsol_event(struct hda_codec *codec,
@@ -16222,15 +16364,17 @@ static void alc663_mode3_unsol_event(struct hda_codec *codec,
                alc663_two_hp_m1_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc663_mode3_setup     alc663_m51va_setup
+
 static void alc663_mode3_inithook(struct hda_codec *codec)
 {
        alc663_two_hp_m1_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 /* ***************** Mode4 ******************************/
 static void alc663_mode4_unsol_event(struct hda_codec *codec,
@@ -16241,15 +16385,17 @@ static void alc663_mode4_unsol_event(struct hda_codec *codec,
                alc663_21jd_two_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc663_mode4_setup     alc663_m51va_setup
+
 static void alc663_mode4_inithook(struct hda_codec *codec)
 {
        alc663_21jd_two_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 /* ***************** Mode5 ******************************/
 static void alc663_mode5_unsol_event(struct hda_codec *codec,
@@ -16260,15 +16406,17 @@ static void alc663_mode5_unsol_event(struct hda_codec *codec,
                alc663_15jd_two_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc663_mode5_setup     alc663_m51va_setup
+
 static void alc663_mode5_inithook(struct hda_codec *codec)
 {
        alc663_15jd_two_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 /* ***************** Mode6 ******************************/
 static void alc663_mode6_unsol_event(struct hda_codec *codec,
@@ -16279,15 +16427,17 @@ static void alc663_mode6_unsol_event(struct hda_codec *codec,
                alc663_two_hp_m2_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc663_mode6_setup     alc663_m51va_setup
+
 static void alc663_mode6_inithook(struct hda_codec *codec)
 {
        alc663_two_hp_m2_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 static void alc663_g71v_hp_automute(struct hda_codec *codec)
@@ -16329,16 +16479,18 @@ static void alc663_g71v_unsol_event(struct hda_codec *codec,
                alc663_g71v_front_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc663_g71v_setup      alc663_m51va_setup
+
 static void alc663_g71v_inithook(struct hda_codec *codec)
 {
        alc663_g71v_front_automute(codec);
        alc663_g71v_hp_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 static void alc663_g50v_unsol_event(struct hda_codec *codec,
@@ -16349,15 +16501,17 @@ static void alc663_g50v_unsol_event(struct hda_codec *codec,
                alc663_m51va_speaker_automute(codec);
                break;
        case ALC880_MIC_EVENT:
-               alc662_eeepc_mic_automute(codec);
+               alc_mic_automute(codec);
                break;
        }
 }
 
+#define alc663_g50v_setup      alc663_m51va_setup
+
 static void alc663_g50v_inithook(struct hda_codec *codec)
 {
        alc663_m51va_speaker_automute(codec);
-       alc662_eeepc_mic_automute(codec);
+       alc_mic_automute(codec);
 }
 
 static struct snd_kcontrol_new alc662_ecs_mixer[] = {
@@ -16561,8 +16715,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc662_eeepc_unsol_event,
+               .setup = alc662_eeepc_setup,
                .init_hook = alc662_eeepc_inithook,
        },
        [ALC662_ASUS_EEEPC_EP20] = {
@@ -16576,6 +16730,7 @@ static struct alc_config_preset alc662_presets[] = {
                .channel_mode = alc662_3ST_6ch_modes,
                .input_mux = &alc662_lenovo_101e_capture_source,
                .unsol_event = alc662_eeepc_unsol_event,
+               .setup = alc662_eeepc_ep20_setup,
                .init_hook = alc662_eeepc_ep20_inithook,
        },
        [ALC662_ECS] = {
@@ -16586,8 +16741,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc662_eeepc_unsol_event,
+               .setup = alc662_eeepc_setup,
                .init_hook = alc662_eeepc_inithook,
        },
        [ALC663_ASUS_M51VA] = {
@@ -16598,8 +16753,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc663_m51va_capture_source,
                .unsol_event = alc663_m51va_unsol_event,
+               .setup = alc663_m51va_setup,
                .init_hook = alc663_m51va_inithook,
        },
        [ALC663_ASUS_G71V] = {
@@ -16610,8 +16765,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc663_g71v_unsol_event,
+               .setup = alc663_g71v_setup,
                .init_hook = alc663_g71v_inithook,
        },
        [ALC663_ASUS_H13] = {
@@ -16621,7 +16776,6 @@ static struct alc_config_preset alc662_presets[] = {
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc663_m51va_capture_source,
                .unsol_event = alc663_m51va_unsol_event,
                .init_hook = alc663_m51va_inithook,
        },
@@ -16635,6 +16789,7 @@ static struct alc_config_preset alc662_presets[] = {
                .channel_mode = alc662_3ST_6ch_modes,
                .input_mux = &alc663_capture_source,
                .unsol_event = alc663_g50v_unsol_event,
+               .setup = alc663_g50v_setup,
                .init_hook = alc663_g50v_inithook,
        },
        [ALC663_ASUS_MODE1] = {
@@ -16648,8 +16803,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc663_mode1_unsol_event,
+               .setup = alc663_mode1_setup,
                .init_hook = alc663_mode1_inithook,
        },
        [ALC662_ASUS_MODE2] = {
@@ -16662,8 +16817,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc662_mode2_unsol_event,
+               .setup = alc662_mode2_setup,
                .init_hook = alc662_mode2_inithook,
        },
        [ALC663_ASUS_MODE3] = {
@@ -16677,8 +16832,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc663_mode3_unsol_event,
+               .setup = alc663_mode3_setup,
                .init_hook = alc663_mode3_inithook,
        },
        [ALC663_ASUS_MODE4] = {
@@ -16692,8 +16847,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc663_mode4_unsol_event,
+               .setup = alc663_mode4_setup,
                .init_hook = alc663_mode4_inithook,
        },
        [ALC663_ASUS_MODE5] = {
@@ -16707,8 +16862,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc663_mode5_unsol_event,
+               .setup = alc663_mode5_setup,
                .init_hook = alc663_mode5_inithook,
        },
        [ALC663_ASUS_MODE6] = {
@@ -16722,8 +16877,8 @@ static struct alc_config_preset alc662_presets[] = {
                .dig_out_nid = ALC662_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc662_eeepc_capture_source,
                .unsol_event = alc663_mode6_unsol_event,
+               .setup = alc663_mode6_setup,
                .init_hook = alc663_mode6_inithook,
        },
        [ALC272_DELL] = {
@@ -16737,8 +16892,8 @@ static struct alc_config_preset alc662_presets[] = {
                .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
                .capsrc_nids = alc272_capsrc_nids,
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc663_m51va_capture_source,
                .unsol_event = alc663_m51va_unsol_event,
+               .setup = alc663_m51va_setup,
                .init_hook = alc663_m51va_inithook,
        },
        [ALC272_DELL_ZM1] = {
@@ -16749,11 +16904,11 @@ static struct alc_config_preset alc662_presets[] = {
                .dac_nids = alc662_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .adc_nids = alc662_adc_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+               .num_adc_nids = 1,
                .capsrc_nids = alc662_capsrc_nids,
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc663_m51va_capture_source,
                .unsol_event = alc663_m51va_unsol_event,
+               .setup = alc663_m51va_setup,
                .init_hook = alc663_m51va_inithook,
        },
        [ALC272_SAMSUNG_NC10] = {
@@ -16764,8 +16919,9 @@ static struct alc_config_preset alc662_presets[] = {
                .dac_nids = alc272_dac_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
-               .input_mux = &alc272_nc10_capture_source,
+               /*.input_mux = &alc272_nc10_capture_source,*/
                .unsol_event = alc663_mode4_unsol_event,
+               .setup = alc663_mode4_setup,
                .init_hook = alc663_mode4_inithook,
        },
 };
@@ -16885,62 +17041,9 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
        return 0;
 }
 
-/* return the index of the src widget from the connection list of the nid.
- * return -1 if not found
- */
-static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid,
-                               hda_nid_t src)
-{
-       hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-       int i, conns;
-
-       conns = snd_hda_get_connections(codec, nid, conn_list,
-                                       ARRAY_SIZE(conn_list));
-       if (conns < 0)
-               return -1;
-       for (i = 0; i < conns; i++)
-               if (conn_list[i] == src)
-                       return i;
-       return -1;
-}
-
-static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
-{
-       unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
-       return (pincap & AC_PINCAP_IN) != 0;
-}
-
 /* create playback/capture controls for input pins */
-static int alc662_auto_create_analog_input_ctls(struct hda_codec *codec,
-                                               const struct auto_pin_cfg *cfg)
-{
-       struct alc_spec *spec = codec->spec;
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (alc662_is_input_pin(codec, cfg->input_pins[i])) {
-                       idx = alc662_input_pin_idx(codec, 0x0b,
-                                                  cfg->input_pins[i]);
-                       if (idx >= 0) {
-                               err = new_analog_input(spec, cfg->input_pins[i],
-                                                      auto_pin_cfg_labels[i],
-                                                      idx, 0x0b);
-                               if (err < 0)
-                                       return err;
-                       }
-                       idx = alc662_input_pin_idx(codec, 0x22,
-                                                  cfg->input_pins[i]);
-                       if (idx >= 0) {
-                               imux->items[imux->num_items].label =
-                                       auto_pin_cfg_labels[i];
-                               imux->items[imux->num_items].index = idx;
-                               imux->num_items++;
-                       }
-               }
-       }
-       return 0;
-}
+#define alc662_auto_create_input_ctls \
+       alc880_auto_create_input_ctls
 
 static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
                                              hda_nid_t nid, int pin_type,
@@ -16994,7 +17097,7 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
 
        for (i = 0; i < AUTO_PIN_LAST; i++) {
                hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (alc662_is_input_pin(codec, nid)) {
+               if (alc_is_input_pin(codec, nid)) {
                        alc_set_input_pin(codec, nid, i);
                        if (nid != ALC662_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
@@ -17035,7 +17138,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
                                           "Headphone");
        if (err < 0)
                return err;
-       err = alc662_auto_create_analog_input_ctls(codec, &spec->autocfg);
+       err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -17092,8 +17195,8 @@ static int patch_alc662(struct hda_codec *codec)
                                                  alc662_models,
                                                  alc662_cfg_tbl);
        if (board_config < 0) {
-               printk(KERN_INFO "hda_codec: Unknown model for %s, "
-                      "trying auto-probe from BIOS...\n", codec->chip_name);
+               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                      codec->chip_name);
                board_config = ALC662_AUTO;
        }
 
@@ -17118,7 +17221,7 @@ static int patch_alc662(struct hda_codec *codec)
        }
 
        if (board_config != ALC662_AUTO)
-               setup_preset(spec, &alc662_presets[board_config]);
+               setup_preset(codec, &alc662_presets[board_config]);
 
        spec->stream_analog_playback = &alc662_pcm_analog_playback;
        spec->stream_analog_capture = &alc662_pcm_analog_capture;
@@ -17126,12 +17229,15 @@ static int patch_alc662(struct hda_codec *codec)
        spec->stream_digital_playback = &alc662_pcm_digital_playback;
        spec->stream_digital_capture = &alc662_pcm_digital_capture;
 
-       spec->adc_nids = alc662_adc_nids;
-       spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
-       spec->capsrc_nids = alc662_capsrc_nids;
+       if (!spec->adc_nids) {
+               spec->adc_nids = alc662_adc_nids;
+               spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+       }
+       if (!spec->capsrc_nids)
+               spec->capsrc_nids = alc662_capsrc_nids;
 
        if (!spec->cap_mixer)
-               set_capture_mixer(spec);
+               set_capture_mixer(codec);
        if (codec->vendor_id == 0x10ec0662)
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
        else