[ALSA] hda-codec - Clean up capture source selection of Realtek codecs
authorTakashi Iwai <tiwai@suse.de>
Mon, 11 Feb 2008 17:32:32 +0000 (18:32 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 24 Apr 2008 10:00:09 +0000 (12:00 +0200)
Clean up the codes of the capture source selection for Realtek codecs.
Now using common helper functions with the new capsrc_nids field.

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

index 3a73587..f1fa1d2 100644 (file)
@@ -238,6 +238,7 @@ struct alc_spec {
        /* capture */
        unsigned int num_adc_nids;
        hda_nid_t *adc_nids;
+       hda_nid_t *capsrc_nids;
        hda_nid_t dig_in_nid;           /* digital-in NID; optional */
 
        /* capture source */
@@ -291,6 +292,7 @@ struct alc_config_preset {
        hda_nid_t hp_nid;               /* optional */
        unsigned int num_adc_nids;
        hda_nid_t *adc_nids;
+       hda_nid_t *capsrc_nids;
        hda_nid_t dig_in_nid;
        unsigned int num_channel_mode;
        const struct hda_channel_mode *channel_mode;
@@ -337,9 +339,10 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
        struct alc_spec *spec = codec->spec;
        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
        unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+       hda_nid_t nid = spec->capsrc_nids ?
+               spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
        return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
-                                    spec->adc_nids[adc_idx],
-                                    &spec->cur_mux[adc_idx]);
+                                    nid, &spec->cur_mux[adc_idx]);
 }
 
 
@@ -708,6 +711,7 @@ static void setup_preset(struct alc_spec *spec,
 
        spec->num_adc_nids = preset->num_adc_nids;
        spec->adc_nids = preset->adc_nids;
+       spec->capsrc_nids = preset->capsrc_nids;
        spec->dig_in_nid = preset->dig_in_nid;
 
        spec->unsol_event = preset->unsol_event;
@@ -5219,6 +5223,9 @@ static hda_nid_t alc882_dac_nids[4] = {
 #define alc882_adc_nids                alc880_adc_nids
 #define alc882_adc_nids_alt    alc880_adc_nids_alt
 
+static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
+static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -5241,15 +5248,10 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
        struct alc_spec *spec = codec->spec;
        const struct hda_input_mux *imux = spec->input_mux;
        unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
-       hda_nid_t nid;
+       hda_nid_t nid = spec->capsrc_nids[adc_idx];
        unsigned int *cur_val = &spec->cur_mux[adc_idx];
        unsigned int i, idx;
 
-       if (spec->num_adc_nids < 3)
-               nid = capture_mixers[adc_idx + 1];
-       else
-               nid = capture_mixers[adc_idx];
        idx = ucontrol->value.enumerated.item[0];
        if (idx >= imux->num_items)
                idx = imux->num_items - 1;
@@ -6126,6 +6128,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dig_out_nid = ALC882_DIGOUT_NID,
                .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
                .adc_nids = alc882_adc_nids,
+               .capsrc_nids = alc882_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
                .channel_mode = alc882_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -6142,6 +6145,7 @@ static struct alc_config_preset alc882_presets[] = {
                .dig_out_nid = ALC882_DIGOUT_NID,
                .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
                .adc_nids = alc882_adc_nids,
+               .capsrc_nids = alc882_capsrc_nids,
                .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
                .channel_mode = alc882_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -6387,12 +6391,14 @@ static int patch_alc882(struct hda_codec *codec)
                if (wcap != AC_WID_AUD_IN) {
                        spec->adc_nids = alc882_adc_nids_alt;
                        spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
+                       spec->capsrc_nids = alc882_capsrc_nids_alt;
                        spec->mixers[spec->num_mixers] =
                                alc882_capture_alt_mixer;
                        spec->num_mixers++;
                } else {
                        spec->adc_nids = alc882_adc_nids;
                        spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
+                       spec->capsrc_nids = alc882_capsrc_nids;
                        spec->mixers[spec->num_mixers] = alc882_capture_mixer;
                        spec->num_mixers++;
                }
@@ -6435,6 +6441,8 @@ static hda_nid_t alc883_adc_nids[2] = {
        0x08, 0x09,
 };
 
+static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -6468,33 +6476,8 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
 
 #define alc883_mux_enum_info alc_mux_enum_info
 #define alc883_mux_enum_get alc_mux_enum_get
-
-static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct alc_spec *spec = codec->spec;
-       const struct hda_input_mux *imux = spec->input_mux;
-       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
-       hda_nid_t nid = capture_mixers[adc_idx];
-       unsigned int *cur_val = &spec->cur_mux[adc_idx];
-       unsigned int i, idx;
-
-       idx = ucontrol->value.enumerated.item[0];
-       if (idx >= imux->num_items)
-               idx = imux->num_items - 1;
-       if (*cur_val == idx)
-               return 0;
-       for (i = 0; i < imux->num_items; i++) {
-               unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-               snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-                                        imux->items[i].index,
-                                        HDA_AMP_MUTE, v);
-       }
-       *cur_val = idx;
-       return 1;
-}
+/* ALC883 has the ALC882-type input selection */
+#define alc883_mux_enum_put alc882_mux_enum_put
 
 /*
  * 2ch mode
@@ -7667,8 +7650,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
@@ -7680,8 +7661,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
@@ -7693,8 +7672,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -7706,8 +7683,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
@@ -7719,8 +7694,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -7734,8 +7707,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7752,8 +7723,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7764,8 +7733,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7779,8 +7746,6 @@ static struct alc_config_preset alc883_presets[] = {
                                alc883_medion_eapd_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
                .input_mux = &alc883_capture_source,
@@ -7791,8 +7756,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7804,8 +7767,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7815,8 +7776,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_lenovo_101e_capture_source,
@@ -7828,8 +7787,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .need_dac_fix = 1,
@@ -7843,8 +7800,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
                .channel_mode = alc883_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -7858,8 +7813,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -7872,8 +7825,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
@@ -7884,8 +7835,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
                .channel_mode = alc888_3st_hp_modes,
                .need_dac_fix = 1,
@@ -7897,8 +7846,6 @@ static struct alc_config_preset alc883_presets[] = {
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
                .dig_out_nid = ALC883_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .dig_in_nid = ALC883_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
                .channel_mode = alc883_sixstack_modes,
@@ -7911,8 +7858,6 @@ static struct alc_config_preset alc883_presets[] = {
                .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
                .num_dacs = ARRAY_SIZE(alc883_dac_nids),
                .dac_nids = alc883_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
-               .adc_nids = alc883_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
                .channel_mode = alc883_3ST_2ch_modes,
                .input_mux = &alc883_capture_source,
@@ -8072,10 +8017,9 @@ static int patch_alc883(struct hda_codec *codec)
        spec->stream_digital_playback = &alc883_pcm_digital_playback;
        spec->stream_digital_capture = &alc883_pcm_digital_capture;
 
-       if (!spec->adc_nids && spec->input_mux) {
-               spec->adc_nids = alc883_adc_nids;
-               spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
-       }
+       spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+       spec->adc_nids = alc883_adc_nids;
+       spec->capsrc_nids = alc883_capsrc_nids;
 
        spec->vmaster_nid = 0x0c;
 
@@ -9532,6 +9476,8 @@ static hda_nid_t alc268_adc_nids_alt[1] = {
        0x08
 };
 
+static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
+
 static struct snd_kcontrol_new alc268_base_mixer[] = {
        /* output mixer control */
        HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
@@ -9787,21 +9733,7 @@ static struct hda_verb alc268_volume_init_verbs[] = {
 
 #define alc268_mux_enum_info alc_mux_enum_info
 #define alc268_mux_enum_get alc_mux_enum_get
-
-static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct alc_spec *spec = codec->spec;
-
-       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       static hda_nid_t capture_mixers[3] = { 0x23, 0x24 };
-       hda_nid_t nid = capture_mixers[adc_idx];
-
-       return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-                                    nid,
-                                    &spec->cur_mux[adc_idx]);
-}
+#define alc268_mux_enum_put alc_mux_enum_put
 
 static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
@@ -10145,6 +10077,7 @@ static struct alc_config_preset alc268_presets[] = {
                .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 = 0x03,
                .dig_out_nid = ALC268_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10159,6 +10092,7 @@ static struct alc_config_preset alc268_presets[] = {
                .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 = 0x03,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
                .channel_mode = alc268_modes,
@@ -10174,6 +10108,7 @@ static struct alc_config_preset alc268_presets[] = {
                .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,
@@ -10202,6 +10137,7 @@ static struct alc_config_preset alc268_presets[] = {
                .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 = 0x03,
                .dig_out_nid = ALC268_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10219,6 +10155,7 @@ static struct alc_config_preset alc268_presets[] = {
                .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 = 0x03,
                .dig_out_nid = ALC268_DIGOUT_NID,
                .num_channel_mode = ARRAY_SIZE(alc268_modes),
@@ -10294,6 +10231,7 @@ static int patch_alc268(struct hda_codec *codec)
                                alc268_capture_mixer;
                        spec->num_mixers++;
                }
+               spec->capsrc_nids = alc268_capsrc_nids;
        }
 
        spec->vmaster_nid = 0x02;
@@ -11850,6 +11788,8 @@ static hda_nid_t alc861vd_adc_nids[1] = {
        0x09,
 };
 
+static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 static struct hda_input_mux alc861vd_capture_source = {
@@ -11881,33 +11821,8 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
 
 #define alc861vd_mux_enum_info alc_mux_enum_info
 #define alc861vd_mux_enum_get alc_mux_enum_get
-
-static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct alc_spec *spec = codec->spec;
-       const struct hda_input_mux *imux = spec->input_mux;
-       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       static hda_nid_t capture_mixers[1] = { 0x22 };
-       hda_nid_t nid = capture_mixers[adc_idx];
-       unsigned int *cur_val = &spec->cur_mux[adc_idx];
-       unsigned int i, idx;
-
-       idx = ucontrol->value.enumerated.item[0];
-       if (idx >= imux->num_items)
-               idx = imux->num_items - 1;
-       if (*cur_val == idx)
-               return 0;
-       for (i = 0; i < imux->num_items; i++) {
-               unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-               snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-                                        imux->items[i].index,
-                                        HDA_AMP_MUTE, v);
-       }
-       *cur_val = idx;
-       return 1;
-}
+/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
+#define alc861vd_mux_enum_put alc882_mux_enum_put
 
 /*
  * 2ch mode
@@ -12390,8 +12305,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                                 alc861vd_3stack_init_verbs },
                .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
                .dac_nids = alc660vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
@@ -12403,8 +12316,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
                .dac_nids = alc660vd_dac_nids,
                .dig_out_nid = ALC861VD_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
@@ -12449,8 +12360,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                                alc861vd_lenovo_unsol_verbs },
                .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
                .dac_nids = alc660vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_capture_source,
@@ -12462,8 +12371,6 @@ static struct alc_config_preset alc861vd_presets[] = {
                .init_verbs = { alc861vd_dallas_verbs },
                .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
                .dac_nids = alc861vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_dallas_capture_source,
@@ -12475,9 +12382,7 @@ static struct alc_config_preset alc861vd_presets[] = {
                .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
                .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
                .dac_nids = alc861vd_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
                .dig_out_nid = ALC861VD_DIGOUT_NID,
-               .adc_nids = alc861vd_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
                .channel_mode = alc861vd_3stack_2ch_modes,
                .input_mux = &alc861vd_hp_capture_source,
@@ -12779,6 +12684,7 @@ static int patch_alc861vd(struct hda_codec *codec)
 
        spec->adc_nids = alc861vd_adc_nids;
        spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
+       spec->capsrc_nids = alc861vd_capsrc_nids;
 
        spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
        spec->num_mixers++;
@@ -12820,9 +12726,11 @@ static hda_nid_t alc662_adc_nids[1] = {
        /* ADC1-2 */
        0x09,
 };
+
+static hda_nid_t alc662_capsrc_nids[1] = { 0x23 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
-
 static struct hda_input_mux alc662_capture_source = {
        .num_items = 4,
        .items = {
@@ -12851,33 +12759,8 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
 
 #define alc662_mux_enum_info alc_mux_enum_info
 #define alc662_mux_enum_get alc_mux_enum_get
+#define alc662_mux_enum_put alc882_mux_enum_put
 
-static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct alc_spec *spec = codec->spec;
-       const struct hda_input_mux *imux = spec->input_mux;
-       unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       static hda_nid_t capture_mixers[2] = { 0x23, 0x22 };
-       hda_nid_t nid = capture_mixers[adc_idx];
-       unsigned int *cur_val = &spec->cur_mux[adc_idx];
-       unsigned int i, idx;
-
-       idx = ucontrol->value.enumerated.item[0];
-       if (idx >= imux->num_items)
-               idx = imux->num_items - 1;
-       if (*cur_val == idx)
-               return 0;
-       for (i = 0; i < imux->num_items; i++) {
-               unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
-               snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
-                                        imux->items[i].index,
-                                        HDA_AMP_MUTE, v);
-       }
-       *cur_val = idx;
-       return 1;
-}
 /*
  * 2ch mode
  */
@@ -13354,8 +13237,6 @@ static struct alc_config_preset alc662_presets[] = {
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .dig_in_nid = ALC662_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
@@ -13368,8 +13249,6 @@ static struct alc_config_preset alc662_presets[] = {
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .dig_in_nid = ALC662_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
                .channel_mode = alc662_3ST_6ch_modes,
@@ -13382,8 +13261,6 @@ static struct alc_config_preset alc662_presets[] = {
                .init_verbs = { alc662_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
                .channel_mode = alc662_3ST_6ch_modes,
                .need_dac_fix = 1,
@@ -13396,8 +13273,6 @@ static struct alc_config_preset alc662_presets[] = {
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
                .dig_out_nid = ALC662_DIGOUT_NID,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .dig_in_nid = ALC662_DIGIN_NID,
                .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
                .channel_mode = alc662_5stack_modes,
@@ -13408,8 +13283,6 @@ static struct alc_config_preset alc662_presets[] = {
                .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
                .input_mux = &alc662_lenovo_101e_capture_source,
@@ -13422,8 +13295,6 @@ static struct alc_config_preset alc662_presets[] = {
                                alc662_eeepc_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
                .channel_mode = alc662_3ST_2ch_modes,
                .input_mux = &alc662_eeepc_capture_source,
@@ -13437,8 +13308,6 @@ static struct alc_config_preset alc662_presets[] = {
                                alc662_eeepc_ep20_sue_init_verbs },
                .num_dacs = ARRAY_SIZE(alc662_dac_nids),
                .dac_nids = alc662_dac_nids,
-               .num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
-               .adc_nids = alc662_adc_nids,
                .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
                .channel_mode = alc662_3ST_6ch_modes,
                .input_mux = &alc662_lenovo_101e_capture_source,
@@ -13750,10 +13619,9 @@ static int patch_alc662(struct hda_codec *codec)
        spec->stream_digital_playback = &alc662_pcm_digital_playback;
        spec->stream_digital_capture = &alc662_pcm_digital_capture;
 
-       if (!spec->adc_nids && spec->input_mux) {
-               spec->adc_nids = alc662_adc_nids;
-               spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
-       }
+       spec->adc_nids = alc662_adc_nids;
+       spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+       spec->capsrc_nids = alc662_capsrc_nids;
 
        spec->vmaster_nid = 0x02;