Increase readability and understandability in the automute code.
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
 };
 
 /* bind hp and internal speaker mute (with plug check) as master switch */
-static void alc262_hippo_master_update(struct hda_codec *codec)
-{
-       update_speakers(codec);
-}
 
 static int alc262_hippo_master_sw_get(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_value *ucontrol)
        if (val == spec->master_mute)
                return 0;
        spec->master_mute = val;
-       alc262_hippo_master_update(codec);
+       update_outputs(codec);
        return 1;
 }
 
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc262_hippo1_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 
        spec->ext_mic_pin = 0x18;
        spec->int_mic_pin = 0x12;
        spec->auto_mic = 1;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_PIN;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_PIN);
 }
 
 /*
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.hp_pins[1] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 /* bind volumes of both NID 0x0c and 0x0d */
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
        mute = 0;
        /* auto-mute only when HP is used as HP */
        if (!spec->cur_mux[0]) {
-               spec->jack_present = snd_hda_jack_detect(codec, 0x15);
-               if (spec->jack_present)
+               spec->hp_jack_present = snd_hda_jack_detect(codec, 0x15);
+               if (spec->hp_jack_present)
                        mute = HDA_AMP_MUTE;
        }
        /* mute/unmute internal speaker */
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x16;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc880_uniwill_init_hook(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 /*
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
        struct alc_spec *spec = codec->spec;
        alc_hp_automute(codec);
        /* toggle EAPD */
-       if (spec->jack_present)
+       if (spec->hp_jack_present)
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
        else
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 
        spec->autocfg.speaker_pins[2] = 0x17;
        spec->autocfg.speaker_pins[3] = 0x19;
        spec->autocfg.speaker_pins[4] = 0x1a;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc889_intel_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 */
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 /*
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x1b;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 #define ALC882_DIGOUT_NID      0x06
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
        spec->autocfg.speaker_pins[1] = 0x1a;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 #define alc885_mb5_setup       alc885_imac24_setup
 /* Macbook Air 2,1 */
 static void alc885_mba21_setup(struct hda_codec *codec)
 {
-       struct alc_spec *spec = codec->spec;
+       struct alc_spec *spec = codec->spec;
 
-       spec->autocfg.hp_pins[0] = 0x14;
-       spec->autocfg.speaker_pins[0] = 0x18;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       spec->autocfg.hp_pins[0] = 0x14;
+       spec->autocfg.speaker_pins[0] = 0x18;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc885_imac91_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
        spec->autocfg.speaker_pins[1] = 0x1a;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct hda_verb alc882_targa_verbs[] = {
        struct alc_spec *spec = codec->spec;
        alc_hp_automute(codec);
        snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
-                                 spec->jack_present ? 1 : 3);
+                                 spec->hp_jack_present ? 1 : 3);
 }
 
 static void alc882_targa_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x1b;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
 
        spec->autocfg.hp_pins[0] = 0x1a;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct hda_verb alc883_mitac_verbs[] = {
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x16;
        spec->autocfg.speaker_pins[2] = 0x18;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct hda_verb alc888_3st_hp_verbs[] = {
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.line_out_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 /* toggle speaker-output according to the hp-jack state */
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 /* toggle speaker-output according to the hp-jack state */
 
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc883_haier_w66_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc883_lenovo_101e_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x1b;
        spec->autocfg.line_out_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
-       spec->automute = 1;
-       spec->detect_line = 1;
-       spec->automute_lines = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 /* toggle speaker-output according to the hp-jack state */
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x15;
        spec->autocfg.speaker_pins[1] = 0x16;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct hda_verb alc883_acer_eapd_verbs[] = {
        spec->autocfg.speaker_pins[1] = 0x15;
        spec->autocfg.speaker_pins[2] = 0x16;
        spec->autocfg.speaker_pins[3] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc888_lenovo_sky_setup(struct hda_codec *codec)
        spec->autocfg.speaker_pins[2] = 0x16;
        spec->autocfg.speaker_pins[3] = 0x17;
        spec->autocfg.speaker_pins[4] = 0x1a;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static void alc883_vaiott_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x17;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct hda_verb alc888_asus_m90v_verbs[] = {
        spec->ext_mic_pin = 0x18;
        spec->int_mic_pin = 0x19;
        spec->auto_mic = 1;
-       spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_AMP;
+       alc_simple_setup_automute(spec, ALC_AUTOMUTE_AMP);
 }
 
 static const struct hda_verb alc888_asus_eee1601_verbs[] = {
 
        alc_fixup_autocfg_pin_nums(codec);
 }
 
+static void alc_simple_setup_automute(struct alc_spec *spec, int mode)
+{
+       int lo_pin = spec->autocfg.line_out_pins[0];
+
+       if (lo_pin == spec->autocfg.speaker_pins[0] ||
+               lo_pin == spec->autocfg.hp_pins[0])
+               lo_pin = 0;
+       spec->automute_mode = mode;
+       spec->detect_hp = !!spec->autocfg.hp_pins[0];
+       spec->detect_lo = !!lo_pin;
+       spec->automute_lo = spec->automute_lo_possible = !!lo_pin;
+       spec->automute_speaker = spec->automute_speaker_possible = !!spec->autocfg.speaker_pins[0];
+}
 
 /* auto-toggle front mic */
 static void alc88x_simple_mic_automute(struct hda_codec *codec)
 
        void (*automute_hook)(struct hda_codec *codec);
 
        /* for pin sensing */
-       unsigned int jack_present: 1;
+       unsigned int hp_jack_present:1;
        unsigned int line_jack_present:1;
        unsigned int master_mute:1;
        unsigned int auto_mic:1;
        unsigned int auto_mic_valid_imux:1;     /* valid imux for auto-mic */
-       unsigned int automute:1;        /* HP automute enabled */
-       unsigned int detect_line:1;     /* Line-out detection enabled */
-       unsigned int automute_lines:1;  /* automute line-out as well; NOP when automute_hp_lo isn't set */
-       unsigned int automute_hp_lo:1;  /* both HP and LO available */
+       unsigned int automute_speaker:1; /* automute speaker outputs */
+       unsigned int automute_lo:1; /* automute LO outputs */
+       unsigned int detect_hp:1;       /* Headphone detection enabled */
+       unsigned int detect_lo:1;       /* Line-out detection enabled */
+       unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
+       unsigned int automute_lo_possible:1;      /* there are line outs and HP */
 
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
        }
 }
 
-/* Toggle internal speakers muting */
-static void update_speakers(struct hda_codec *codec)
+/* Toggle outputs muting */
+static void update_outputs(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        int on;
        do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
                    spec->autocfg.hp_pins, spec->master_mute, true);
 
-       if (!spec->automute)
+       if (!spec->automute_speaker)
                on = 0;
        else
-               on = spec->jack_present | spec->line_jack_present;
+               on = spec->hp_jack_present | spec->line_jack_present;
        on |= spec->master_mute;
        do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
                    spec->autocfg.speaker_pins, on, false);
        if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
            spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
                return;
-       if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
+       if (!spec->automute_lo)
                on = 0;
        else
-               on = spec->jack_present;
+               on = spec->hp_jack_present;
        on |= spec->master_mute;
        do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                    spec->autocfg.line_out_pins, on, false);
 }
 
-static void call_update_speakers(struct hda_codec *codec)
+static void call_update_outputs(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        if (spec->automute_hook)
                spec->automute_hook(codec);
        else
-               update_speakers(codec);
+               update_outputs(codec);
 }
 
 /* standard HP-automute helper */
 {
        struct alc_spec *spec = codec->spec;
 
-       spec->jack_present =
+       spec->hp_jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
                             spec->autocfg.hp_pins);
-       if (!spec->automute)
+       if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
                return;
-       call_update_speakers(codec);
+       call_update_outputs(codec);
 }
 
 /* standard line-out-automute helper */
        spec->line_jack_present =
                detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
                             spec->autocfg.line_out_pins);
-       if (!spec->automute || !spec->detect_line)
+       if (!spec->automute_speaker || !spec->detect_lo)
                return;
-       call_update_speakers(codec);
+       call_update_outputs(codec);
 }
 
 #define get_connection_index(codec, mux, nid) \
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
-       if (spec->automute_hp_lo) {
+       if (spec->automute_speaker_possible && spec->automute_lo_possible) {
                uinfo->value.enumerated.items = 3;
                texts = texts3;
        } else {
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct alc_spec *spec = codec->spec;
-       unsigned int val;
-       if (!spec->automute)
-               val = 0;
-       else if (!spec->automute_hp_lo || !spec->automute_lines)
-               val = 1;
-       else
-               val = 2;
+       unsigned int val = 0;
+       if (spec->automute_speaker)
+               val++;
+       if (spec->automute_lo)
+               val++;
+
        ucontrol->value.enumerated.item[0] = val;
        return 0;
 }
 
        switch (ucontrol->value.enumerated.item[0]) {
        case 0:
-               if (!spec->automute)
+               if (!spec->automute_speaker && !spec->automute_lo)
                        return 0;
-               spec->automute = 0;
+               spec->automute_speaker = 0;
+               spec->automute_lo = 0;
                break;
        case 1:
-               if (spec->automute &&
-                   (!spec->automute_hp_lo || !spec->automute_lines))
-                       return 0;
-               spec->automute = 1;
-               spec->automute_lines = 0;
+               if (spec->automute_speaker_possible) {
+                       if (!spec->automute_lo && spec->automute_speaker)
+                               return 0;
+                       spec->automute_speaker = 1;
+                       spec->automute_lo = 0;
+               } else if (spec->automute_lo_possible) {
+                       if (spec->automute_lo)
+                               return 0;
+                       spec->automute_lo = 1;
+               } else
+                       return -EINVAL;
                break;
        case 2:
-               if (!spec->automute_hp_lo)
+               if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
                        return -EINVAL;
-               if (spec->automute && spec->automute_lines)
+               if (spec->automute_speaker && spec->automute_lo)
                        return 0;
-               spec->automute = 1;
-               spec->automute_lines = 1;
+               spec->automute_speaker = 1;
+               spec->automute_lo = 1;
                break;
        default:
                return -EINVAL;
        }
-       call_update_speakers(codec);
+       call_update_outputs(codec);
        return 1;
 }
 
  * Check the availability of HP/line-out auto-mute;
  * Set up appropriately if really supported
  */
-static void alc_init_auto_hp(struct hda_codec *codec)
+static void alc_init_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
                present++;
        if (present < 2) /* need two different output types */
                return;
-       if (present == 3)
-               spec->automute_hp_lo = 1; /* both HP and LO automute */
 
        if (!cfg->speaker_pins[0] &&
            cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
                cfg->hp_outs = cfg->line_outs;
        }
 
+       spec->automute_mode = ALC_AUTOMUTE_PIN;
+
        for (i = 0; i < cfg->hp_outs; i++) {
                hda_nid_t nid = cfg->hp_pins[i];
                if (!is_jack_detectable(codec, nid))
                snd_hda_codec_write_cache(codec, nid, 0,
                                  AC_VERB_SET_UNSOLICITED_ENABLE,
                                  AC_USRSP_EN | ALC_HP_EVENT);
-               spec->automute = 1;
-               spec->automute_mode = ALC_AUTOMUTE_PIN;
-       }
-       if (spec->automute && cfg->line_out_pins[0] &&
-           cfg->speaker_pins[0] &&
-           cfg->line_out_pins[0] != cfg->hp_pins[0] &&
-           cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
-               for (i = 0; i < cfg->line_outs; i++) {
-                       hda_nid_t nid = cfg->line_out_pins[i];
-                       if (!is_jack_detectable(codec, nid))
-                               continue;
-                       snd_printdd("realtek: Enable Line-Out auto-muting "
-                                   "on NID 0x%x\n", nid);
-                       snd_hda_codec_write_cache(codec, nid, 0,
-                                       AC_VERB_SET_UNSOLICITED_ENABLE,
-                                       AC_USRSP_EN | ALC_FRONT_EVENT);
-                       spec->detect_line = 1;
+               spec->detect_hp = 1;
+       }
+
+       if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
+               if (cfg->speaker_outs)
+                       for (i = 0; i < cfg->line_outs; i++) {
+                               hda_nid_t nid = cfg->line_out_pins[i];
+                               if (!is_jack_detectable(codec, nid))
+                                       continue;
+                               snd_printdd("realtek: Enable Line-Out "
+                                           "auto-muting on NID 0x%x\n", nid);
+                               snd_hda_codec_write_cache(codec, nid, 0,
+                                               AC_VERB_SET_UNSOLICITED_ENABLE,
+                                               AC_USRSP_EN | ALC_FRONT_EVENT);
+                               spec->detect_lo = 1;
                }
-               spec->automute_lines = spec->detect_line;
+               spec->automute_lo_possible = spec->detect_hp;
        }
 
-       if (spec->automute) {
+       spec->automute_speaker_possible = cfg->speaker_outs &&
+               (spec->detect_hp || spec->detect_lo);
+
+       spec->automute_lo = spec->automute_lo_possible;
+       spec->automute_speaker = spec->automute_speaker_possible;
+
+       if (spec->automute_speaker_possible || spec->automute_lo_possible) {
                /* create a control for automute mode */
                alc_add_automute_mode_enum(codec);
                spec->unsol_event = alc_sku_unsol_event;
 /* check the availabilities of auto-mute and auto-mic switches */
 static void alc_auto_check_switches(struct hda_codec *codec)
 {
-       alc_init_auto_hp(codec);
+       alc_init_automute(codec);
        alc_init_auto_mic(codec);
 }
 
 
 static void alc269_quanta_automute(struct hda_codec *codec)
 {
-       update_speakers(codec);
+       update_outputs(codec);
 
        snd_hda_codec_write(codec, 0x20, 0,
                        AC_VERB_SET_COEF_INDEX, 0x0c);