ALSA: hda - Reduce static init verbs for Realtek auto-parsers
authorTakashi Iwai <tiwai@suse.de>
Mon, 27 Jun 2011 08:52:59 +0000 (10:52 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 27 Jun 2011 08:52:59 +0000 (10:52 +0200)
Instead of using fixed init verbs, initialize DACs, ADCs and mixers
more dynamically for Realtek auto-parsers.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_realtek.c

index cb8afdab834972b89363a5efcca4e84669d38f9f..480c4233cca5696e51656bdcefb6d3c2502b2a99 100644 (file)
@@ -348,6 +348,7 @@ struct alc_spec {
        const hda_nid_t *adc_nids;
        const hda_nid_t *capsrc_nids;
        hda_nid_t dig_in_nid;           /* digital-in NID; optional */
+       hda_nid_t mixer_nid;            /* analog-mixer NID */
 
        /* capture setup for dynamic dual-adc switch */
        unsigned int cur_adc_idx;
@@ -2061,15 +2062,23 @@ static void alc_auto_init_digital(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        int i;
-       hda_nid_t pin;
+       hda_nid_t pin, dac;
 
        for (i = 0; i < spec->autocfg.dig_outs; i++) {
                pin = spec->autocfg.dig_out_pins[i];
-               if (pin) {
-                       snd_hda_codec_write(codec, pin, 0,
-                                           AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                           PIN_OUT);
-               }
+               if (!pin)
+                       continue;
+               snd_hda_codec_write(codec, pin, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+               if (!i)
+                       dac = spec->multiout.dig_out_nid;
+               else
+                       dac = spec->slave_dig_outs[i - 1];
+               if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
+                       continue;
+               snd_hda_codec_write(codec, dac, 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_OUT_UNMUTE);
        }
        pin = spec->autocfg.dig_in_pin;
        if (pin)
@@ -5602,6 +5611,19 @@ static int get_pin_type(int line_out_type)
                return PIN_OUT;
 }
 
+static void alc880_auto_init_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+       if (!nid)
+               return;
+       nid = alc880_idx_to_mixer(alc880_dac_to_idx(nid));
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_OUT_ZERO);
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_IN_MUTE(0));
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_IN_MUTE(1));
+}
+
 static void alc880_auto_init_multi_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -5612,12 +5634,16 @@ static void alc880_auto_init_multi_out(struct hda_codec *codec)
                int pin_type = get_pin_type(spec->autocfg.line_out_type);
                alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
        }
+       /* mute DACs */
+       for (i = 0; i < spec->multiout.num_dacs; i++)
+               alc880_auto_init_dac(codec, spec->multiout.dac_nids[i]);
 }
 
 static void alc880_auto_init_extra_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        hda_nid_t pin;
+       int i;
 
        pin = spec->autocfg.speaker_pins[0];
        if (pin) /* connect to front */
@@ -5625,6 +5651,10 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec)
        pin = spec->autocfg.hp_pins[0];
        if (pin) /* connect to front */
                alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+       /* mute DACs */
+       alc880_auto_init_dac(codec, spec->multiout.hp_nid);
+       for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
+               alc880_auto_init_dac(codec, spec->multiout.extra_out_nid[i]);
 }
 
 static void alc880_auto_init_analog_input(struct hda_codec *codec)
@@ -5637,13 +5667,21 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec)
                hda_nid_t nid = cfg->inputs[i].pin;
                if (alc_is_input_pin(codec, nid)) {
                        alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-                       if (nid != ALC880_PIN_CD_NID &&
-                           (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
+                       if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
                                snd_hda_codec_write(codec, nid, 0,
                                                    AC_VERB_SET_AMP_GAIN_MUTE,
                                                    AMP_OUT_MUTE);
                }
        }
+
+       /* mute all loopback inputs */
+       if (spec->mixer_nid) {
+               int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL);
+               for (i = 0; i < nums; i++)
+                       snd_hda_codec_write(codec, spec->mixer_nid, 0,
+                                           AC_VERB_SET_AMP_GAIN_MUTE,
+                                           AMP_IN_MUTE(i));
+       }
 }
 
 static void alc880_auto_init_input_src(struct hda_codec *codec)
@@ -5662,6 +5700,9 @@ static void alc880_auto_init_input_src(struct hda_codec *codec)
                        snd_hda_codec_write(codec, spec->adc_nids[c], 0,
                                            AC_VERB_SET_CONNECT_SEL,
                                            imux->items[0].index);
+               snd_hda_codec_write(codec, spec->adc_nids[c], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_IN_MUTE(0));
        }
 }
 
@@ -5713,8 +5754,6 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       add_verb(spec, alc880_volume_init_verbs);
-
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
 
@@ -5984,6 +6023,8 @@ static int patch_alc880(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x0b;
+
        board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
                                                  alc880_models,
                                                  alc880_cfg_tbl);
@@ -7228,10 +7269,24 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
        }
 }
 
+static void alc260_auto_init_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+       if (!nid)
+               return;
+       nid += 0x06; /* DAC -> MIX */
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_OUT_ZERO);
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_IN_MUTE(0));
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_IN_MUTE(1));
+}
+
 static void alc260_auto_init_multi_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        hda_nid_t nid;
+       int i;
 
        nid = spec->autocfg.line_out_pins[0];
        if (nid) {
@@ -7246,74 +7301,17 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
        nid = spec->autocfg.hp_pins[0];
        if (nid)
                alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
-}
-
-#define ALC260_PIN_CD_NID              0x16
-static void alc260_auto_init_analog_input(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i;
 
-       for (i = 0; i < cfg->num_inputs; i++) {
-               hda_nid_t nid = cfg->inputs[i].pin;
-               if (nid >= 0x12) {
-                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-                       if (nid != ALC260_PIN_CD_NID &&
-                           (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-                               snd_hda_codec_write(codec, nid, 0,
-                                                   AC_VERB_SET_AMP_GAIN_MUTE,
-                                                   AMP_OUT_MUTE);
-               }
-       }
+       /* mute DACs */
+       for (i = 0; i < spec->multiout.num_dacs; i++)
+               alc260_auto_init_dac(codec, spec->multiout.dac_nids[i]);
+       alc260_auto_init_dac(codec, spec->multiout.extra_out_nid[0]);
+       alc260_auto_init_dac(codec, spec->multiout.hp_nid);
 }
 
+#define alc260_auto_init_analog_input  alc880_auto_init_analog_input
 #define alc260_auto_init_input_src     alc880_auto_init_input_src
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc260_volume_init_verbs[] = {
-       /*
-        * Unmute ADC0-1 and set the default input to mic-in
-        */
-       {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-       /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-        * mixer widget
-        * Note: PASD motherboards uses the Line In 2 as the input for
-        * front panel mic (mic 2)
-        */
-       /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-       /* mute analog inputs */
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-       /*
-        * Set up output mixers (0x08 - 0x0a)
-        */
-       /* set vol=0 to output mixers */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       /* set up input amps for analog loopback */
-       /* Amp Indices: DAC = 0, mixer = 1 */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-       { }
-};
-
 static int alc260_parse_auto_config(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -7340,8 +7338,6 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       add_verb(spec, alc260_volume_init_verbs);
-
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
 
@@ -7588,6 +7584,8 @@ static int patch_alc260(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x07;
+
        board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
                                                  alc260_models,
                                                  alc260_cfg_tbl);
@@ -9035,48 +9033,6 @@ static void alc885_imac24_init_hook(struct hda_codec *codec)
        alc_hp_automute(codec);
 }
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc883_auto_init_verbs[] = {
-       /*
-        * Unmute ADC0-2 and set the default input to mic-in
-        */
-       {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-       /*
-        * Set up output mixers (0x0c - 0x0f)
-        */
-       /* set vol=0 to output mixers */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       /* set up input amps for analog loopback */
-       /* Amp Indices: DAC = 0, mixer = 1 */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-       /* FIXME: use matrix-type input source selection */
-       /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-       /* Input mixer2 */
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       /* Input mixer3 */
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       { }
-};
-
 /* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
 static const struct hda_verb alc889A_mb31_ch2_init[] = {
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},             /* HP as front */
@@ -11036,6 +10992,9 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
        /* set as output */
        alc_set_pin_output(codec, nid, pin_type);
 
+       if (snd_hda_get_conn_list(codec, nid, NULL) < 2)
+               return;
+
        if (dac == 0x25)
                idx = 4;
        else if (dac >= 0x02 && dac <= 0x05)
@@ -11045,6 +11004,8 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 }
 
+#define alc882_auto_init_dac   alc880_auto_init_dac
+
 static void alc882_auto_init_multi_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -11057,6 +11018,9 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec)
                        alc882_auto_set_output_and_unmute(codec, nid, pin_type,
                                        spec->multiout.dac_nids[i]);
        }
+       /* mute DACs */
+       for (i = 0; i < spec->multiout.num_dacs; i++)
+               alc882_auto_init_dac(codec, spec->multiout.dac_nids[i]);
 }
 
 static void alc882_auto_init_hp_out(struct hda_codec *codec)
@@ -11088,31 +11052,21 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
                        alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
                }
        }
-}
-
-static void alc882_auto_init_analog_input(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i;
 
-       for (i = 0; i < cfg->num_inputs; i++) {
-               hda_nid_t nid = cfg->inputs[i].pin;
-               alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-               if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
-                       snd_hda_codec_write(codec, nid, 0,
-                                           AC_VERB_SET_AMP_GAIN_MUTE,
-                                           AMP_OUT_MUTE);
-       }
+       /* mute DACs */
+       alc882_auto_init_dac(codec, spec->multiout.hp_nid);
+       for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
+               alc882_auto_init_dac(codec, spec->multiout.extra_out_nid[i]);
 }
 
+#define alc882_auto_init_analog_input  alc880_auto_init_analog_input
+
 static void alc882_auto_init_input_src(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        int c;
 
        for (c = 0; c < spec->num_adc_nids; c++) {
-               hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
                hda_nid_t nid = spec->capsrc_nids[c];
                unsigned int mux_idx;
                const struct hda_input_mux *imux;
@@ -11123,9 +11077,8 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
                                    AC_VERB_SET_AMP_GAIN_MUTE,
                                    AMP_IN_MUTE(0));
 
-               conns = snd_hda_get_connections(codec, nid, conn_list,
-                                               ARRAY_SIZE(conn_list));
-               if (conns < 0)
+               conns = snd_hda_get_conn_list(codec, nid, NULL);
+               if (conns <= 0)
                        continue;
                mux_idx = c >= spec->num_mux_defs ? 0 : c;
                imux = &spec->input_mux[mux_idx];
@@ -11241,7 +11194,6 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
        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 */
        if (get_wcaps_type(get_wcaps(codec, 0x07)) == AC_WID_AUD_IN)
                add_verb(spec, alc882_adc1_init_verbs);
@@ -11282,6 +11234,8 @@ static int patch_alc882(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x0b;
+
        switch (codec->vendor_id) {
        case 0x10ec0882:
        case 0x10ec0885:
@@ -11353,7 +11307,6 @@ static int patch_alc882(struct hda_codec *codec)
                for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
                        const struct hda_input_mux *imux = spec->input_mux;
                        hda_nid_t cap;
-                       hda_nid_t items[16];
                        hda_nid_t nid = alc882_adc_nids[i];
                        unsigned int wcap = get_wcaps(codec, nid);
                        /* get type */
@@ -11364,8 +11317,7 @@ static int patch_alc882(struct hda_codec *codec)
                        err = snd_hda_get_connections(codec, nid, &cap, 1);
                        if (err < 0)
                                continue;
-                       err = snd_hda_get_connections(codec, cap, items,
-                                                     ARRAY_SIZE(items));
+                       err = snd_hda_get_conn_list(codec, cap, NULL);
                        if (err < 0)
                                continue;
                        for (j = 0; j < imux->num_items; j++)
@@ -12313,70 +12265,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
 #define alc262_auto_create_input_ctls \
        alc882_auto_create_input_ctls
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc262_volume_init_verbs[] = {
-       /*
-        * Unmute ADC0-2 and set the default input to mic-in
-        */
-       {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-       {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-       /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
-        * mixer widget
-        * Note: PASD motherboards uses the Line In 2 as the input for
-        * front panel mic (mic 2)
-        */
-       /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-       {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-       /*
-        * Set up output mixers (0x0c - 0x0f)
-        */
-       /* set vol=0 to output mixers */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
-       /* set up input amps for analog loopback */
-       /* Amp Indices: DAC = 0, mixer = 1 */
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-       /* FIXME: use matrix-type input source selection */
-       /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
-       /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-       /* Input mixer2 */
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-       /* Input mixer3 */
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-       {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-
-       { }
-};
-
 static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
        /*
         * Unmute ADC0-2 and set the default input to mic-in
@@ -12674,7 +12562,6 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       add_verb(spec, alc262_volume_init_verbs);
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
 
@@ -13034,6 +12921,9 @@ static int patch_alc262(struct hda_codec *codec)
                return -ENOMEM;
 
        codec->spec = spec;
+
+       spec->mixer_nid = 0x0b;
+
 #if 0
        /* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
         * under-run
@@ -13450,6 +13340,8 @@ static const struct hda_verb alc268_base_init_verbs[] = {
        { }
 };
 
+/* only for model=test */
+#ifdef CONFIG_SND_DEBUG
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -13470,12 +13362,15 @@ static const struct hda_verb alc268_volume_init_verbs[] = {
 
        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       { }
+};
+#endif /* CONFIG_SND_DEBUG */
 
-       /* set PCBEEP vol = 0, mute connections */
+/* set PCBEEP vol = 0, mute connections */
+static const struct hda_verb alc268_beep_init_verbs[] = {
        {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
        {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
        { }
 };
 
@@ -13690,6 +13585,14 @@ static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 }
 
+static void alc268_auto_init_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+       if (!nid)
+               return;
+       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           AMP_OUT_MUTE);
+}
+
 static void alc268_auto_init_multi_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -13700,6 +13603,9 @@ static void alc268_auto_init_multi_out(struct hda_codec *codec)
                int pin_type = get_pin_type(spec->autocfg.line_out_type);
                alc268_auto_set_output_and_unmute(codec, nid, pin_type);
        }
+       /* mute DACs */
+       for (i = 0; i < spec->multiout.num_dacs; i++)
+               alc268_auto_init_dac(codec, spec->multiout.dac_nids[i]);
 }
 
 static void alc268_auto_init_hp_out(struct hda_codec *codec)
@@ -13719,6 +13625,10 @@ static void alc268_auto_init_hp_out(struct hda_codec *codec)
        if (spec->autocfg.mono_out_pin)
                snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       /* mute DACs */
+       alc268_auto_init_dac(codec, spec->multiout.hp_nid);
+       for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++)
+               alc268_auto_init_dac(codec, spec->multiout.extra_out_nid[i]);
 }
 
 static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
@@ -13812,7 +13722,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
        if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d)
                add_mixer(spec, alc268_beep_mixer);
 
-       add_verb(spec, alc268_volume_init_verbs);
+       add_verb(spec, alc268_beep_init_verbs);
        spec->num_mux_defs = 2;
        spec->input_mux = &spec->private_imux[0];
 
@@ -14037,7 +13947,8 @@ static const struct alc_config_preset alc268_presets[] = {
        [ALC268_TEST] = {
                .mixers = { alc268_test_mixer, alc268_capture_mixer },
                .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
-                               alc268_volume_init_verbs },
+                               alc268_volume_init_verbs,
+                               alc268_beep_init_verbs },
                .num_dacs = ARRAY_SIZE(alc268_dac_nids),
                .dac_nids = alc268_dac_nids,
                .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
@@ -14064,6 +13975,8 @@ static int patch_alc268(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       /* ALC268 has no aa-loopback mixer */
+
        board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST,
                                                  alc268_models,
                                                  alc268_cfg_tbl);
@@ -14775,13 +14688,10 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       if (spec->codec_variant != ALC269_TYPE_NORMAL) {
-               add_verb(spec, alc269vb_init_verbs);
+       if (spec->codec_variant != ALC269_TYPE_NORMAL)
                alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
-       } else {
-               add_verb(spec, alc269_init_verbs);
+       else
                alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
-       }
 
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
@@ -15231,6 +15141,8 @@ static int patch_alc269(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x0b;
+
        alc_auto_parse_customize_define(codec);
 
        if (codec->vendor_id == 0x10ec0269) {
@@ -15858,58 +15770,6 @@ static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
        { }
 };
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc861_auto_init_verbs[] = {
-       /*
-        * Unmute ADC0 and set the default input to mic-in
-        */
-       /* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
-       {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
-       /* Unmute DAC0~3 & spdif out*/
-       {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-       {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-       /* Unmute Mixer 14 (mic) 1c (Line in)*/
-       {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-       /* Unmute Stereo Mixer 15 */
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-       {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
-
-       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-       {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-
-       {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},  /* set Mic 1 */
-
-       { }
-};
-
 static const struct hda_verb alc861_toshiba_init_verbs[] = {
        {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
 
@@ -16123,7 +15983,7 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        int i;
 
-       for (i = 0; i < spec->autocfg.line_outs; i++) {
+       for (i = 0; i < spec->autocfg.line_outs + spec->multi_ios; i++) {
                hda_nid_t nid = spec->autocfg.line_out_pins[i];
                int pin_type = get_pin_type(spec->autocfg.line_out_type);
                if (nid)
@@ -16148,18 +16008,7 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
                                                  spec->multiout.dac_nids[0]);
 }
 
-static void alc861_auto_init_analog_input(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i;
-
-       for (i = 0; i < cfg->num_inputs; i++) {
-               hda_nid_t nid = cfg->inputs[i].pin;
-               if (nid >= 0x0c && nid <= 0x11)
-                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-       }
-}
+#define alc861_auto_init_analog_input  alc880_auto_init_analog_input
 
 /* parse the BIOS configuration and set up the alc_spec */
 /* return 1 if successful, 0 if the proper config is not found,
@@ -16201,8 +16050,6 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       add_verb(spec, alc861_auto_init_verbs);
-
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
 
@@ -16417,6 +16264,8 @@ static int patch_alc861(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x15;
+
         board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
                                                  alc861_models,
                                                  alc861_cfg_tbl);
@@ -17102,61 +16951,9 @@ static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
 }
 
 
-static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
-                               hda_nid_t nid, int pin_type, int dac_idx)
-{
-       alc_set_pin_output(codec, nid, pin_type);
-}
-
-static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       int i;
-
-       for (i = 0; i <= HDA_SIDE; i++) {
-               hda_nid_t nid = spec->autocfg.line_out_pins[i];
-               int pin_type = get_pin_type(spec->autocfg.line_out_type);
-               if (nid)
-                       alc861vd_auto_set_output_and_unmute(codec, nid,
-                                                           pin_type, i);
-       }
-}
-
-
-static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       hda_nid_t pin;
-
-       pin = spec->autocfg.hp_pins[0];
-       if (pin) /* connect to front and use dac 0 */
-               alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
-       pin = spec->autocfg.speaker_pins[0];
-       if (pin)
-               alc861vd_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
-}
-
-#define ALC861VD_PIN_CD_NID            ALC880_PIN_CD_NID
-
-static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i;
-
-       for (i = 0; i < cfg->num_inputs; i++) {
-               hda_nid_t nid = cfg->inputs[i].pin;
-               if (alc_is_input_pin(codec, nid)) {
-                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-                       if (nid != ALC861VD_PIN_CD_NID &&
-                           (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-                               snd_hda_codec_write(codec, nid, 0,
-                                               AC_VERB_SET_AMP_GAIN_MUTE,
-                                               AMP_OUT_MUTE);
-               }
-       }
-}
-
+#define alc861vd_auto_init_multi_out   alc882_auto_init_multi_out
+#define alc861vd_auto_init_hp_out      alc882_auto_init_hp_out
+#define alc861vd_auto_init_analog_input        alc882_auto_init_analog_input
 #define alc861vd_auto_init_input_src   alc882_auto_init_input_src
 
 #define alc861vd_idx_to_mixer_vol(nid)         ((nid) + 0x02)
@@ -17324,8 +17121,6 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       add_verb(spec, alc861vd_volume_init_verbs);
-
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
 
@@ -17384,6 +17179,8 @@ static int patch_alc861vd(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x0b;
+
        board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
                                                  alc861vd_models,
                                                  alc861vd_cfg_tbl);
@@ -19153,27 +18950,7 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
                                        spec->multiout.extra_out_nid[0]);
 }
 
-#define ALC662_PIN_CD_NID              ALC880_PIN_CD_NID
-
-static void alc662_auto_init_analog_input(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i;
-
-       for (i = 0; i < cfg->num_inputs; i++) {
-               hda_nid_t nid = cfg->inputs[i].pin;
-               if (alc_is_input_pin(codec, nid)) {
-                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
-                       if (nid != ALC662_PIN_CD_NID &&
-                           (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
-                               snd_hda_codec_write(codec, nid, 0,
-                                                   AC_VERB_SET_AMP_GAIN_MUTE,
-                                                   AMP_OUT_MUTE);
-               }
-       }
-}
-
+#define alc662_auto_init_analog_input  alc882_auto_init_analog_input
 #define alc662_auto_init_input_src     alc882_auto_init_input_src
 
 /*
@@ -19499,6 +19276,8 @@ static int patch_alc662(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       spec->mixer_nid = 0x0b;
+
        alc_auto_parse_customize_define(codec);
 
        alc_fix_pll_init(codec, 0x20, 0x04, 15);
@@ -19958,8 +19737,6 @@ static int alc680_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       add_verb(spec, alc680_init_verbs);
-
        err = alc_auto_add_mic_boost(codec);
        if (err < 0)
                return err;
@@ -20023,6 +19800,8 @@ static int patch_alc680(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       /* ALC680 has no aa-loopback mixer */
+
        board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST,
                                                  alc680_models,
                                                  alc680_cfg_tbl);