ALSA: HDA: Realtek: Avoid unnecessary volume control index on Surround/Side
[linux-flexiantxendom0-natty.git] / sound / pci / hda / patch_realtek.c
index 7874023..c2eb6a7 100644 (file)
@@ -394,6 +394,7 @@ struct alc_spec {
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
        unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
+       unsigned int single_input_src:1;
        int init_amp;
        int codec_variant;      /* flag for other variants */
 
@@ -1133,11 +1134,8 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
                nid = spec->autocfg.hp_pins[i];
                if (!nid)
                        break;
-               if (snd_hda_jack_detect(codec, nid)) {
-                       spec->jack_present = 1;
-                       break;
-               }
-               alc_report_jack(codec, spec->autocfg.hp_pins[i]);
+               alc_report_jack(codec, nid);
+               spec->jack_present |= snd_hda_jack_detect(codec, nid);
        }
 
        mute = spec->jack_present ? HDA_AMP_MUTE : 0;
@@ -1721,7 +1719,9 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
 {
        struct alc_spec *spec = codec->spec;
        int id = spec->fixup_id;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        const char *modelname = spec->fixup_name;
+#endif
        int depth = 0;
 
        if (!spec->fixup_list)
@@ -2288,6 +2288,29 @@ static struct snd_kcontrol_new alc888_base_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc888_acer_aspire_4930g_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", 0x0f, 2, 0x0,
+               HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0f, 2, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Side Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Side Playback Switch", 0x0e, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       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, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       { } /* end */
+};
+
+
 static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
        HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -3897,6 +3920,8 @@ static struct hda_amp_list alc880_lg_loopbacks[] = {
  * Common callbacks
  */
 
+static void alc_init_special_input_src(struct hda_codec *codec);
+
 static int alc_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -3907,6 +3932,7 @@ static int alc_init(struct hda_codec *codec)
 
        for (i = 0; i < spec->num_init_verbs; i++)
                snd_hda_sequence_write(codec, spec->init_verbs[i]);
+       alc_init_special_input_src(codec);
 
        if (spec->init_hook)
                spec->init_hook(codec);
@@ -5129,7 +5155,9 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
 
        switch (cfg->line_out_type) {
        case AUTO_PIN_SPEAKER_OUT:
-               return "Speaker";
+               if (cfg->line_outs == 1)
+                       return "Speaker";
+               break;
        case AUTO_PIN_HP_OUT:
                return "Headphone";
        default:
@@ -5183,16 +5211,19 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
+                               index = 0;
+                       }
                        err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-                                               name, i,
+                                               name, index,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
                        err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-                                              name, i,
+                                              name, index,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 2,
                                                              HDA_INPUT));
                        if (err < 0)
@@ -5563,6 +5594,7 @@ static void fixup_single_adc(struct hda_codec *codec)
                        spec->capsrc_nids += i;
                spec->adc_nids += i;
                spec->num_adc_nids = 1;
+               spec->single_input_src = 1;
        }
 }
 
@@ -5574,6 +5606,16 @@ static void fixup_dual_adc_switch(struct hda_codec *codec)
        init_capsrc_for_pin(codec, spec->int_mic.pin);
 }
 
+/* initialize some special cases for input sources */
+static void alc_init_special_input_src(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       if (spec->dual_adc_switch)
+               fixup_dual_adc_switch(codec);
+       else if (spec->single_input_src)
+               init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
+}
+
 static void set_capture_mixer(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -5589,7 +5631,7 @@ static void set_capture_mixer(struct hda_codec *codec)
                int mux = 0;
                int num_adcs = spec->num_adc_nids;
                if (spec->dual_adc_switch)
-                       fixup_dual_adc_switch(codec);
+                       num_adcs = 1;
                else if (spec->auto_mic)
                        fixup_automic_adc(codec);
                else if (spec->input_mux) {
@@ -5598,8 +5640,6 @@ static void set_capture_mixer(struct hda_codec *codec)
                        else if (spec->input_mux->num_items == 1)
                                fixup_single_adc(codec);
                }
-               if (spec->dual_adc_switch)
-                       num_adcs = 1;
                spec->cap_mixer = caps[mux][num_adcs - 1];
        }
 }
@@ -10357,7 +10397,7 @@ static struct alc_config_preset alc882_presets[] = {
                .init_hook = alc_automute_amp,
        },
        [ALC888_ACER_ASPIRE_4930G] = {
-               .mixers = { alc888_base_mixer,
+               .mixers = { alc888_acer_aspire_4930g_mixer,
                                alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
                                alc888_acer_aspire_4930g_verbs },
@@ -10726,6 +10766,7 @@ static struct alc_config_preset alc882_presets[] = {
  */
 enum {
        PINFIX_ABIT_AW9D_MAX,
+       PINFIX_LENOVO_Y530,
        PINFIX_PB_M5210,
        PINFIX_ACER_ASPIRE_7736,
 };
@@ -10740,6 +10781,14 @@ static const struct alc_fixup alc882_fixups[] = {
                        { }
                }
        },
+       [PINFIX_LENOVO_Y530] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x15, 0x99130112 }, /* rear int speakers */
+                       { 0x16, 0x99130111 }, /* subwoofer */
+                       { }
+               }
+       },
        [PINFIX_PB_M5210] = {
                .type = ALC_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -10755,6 +10804,7 @@ static const struct alc_fixup alc882_fixups[] = {
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
+       SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
        SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
        {}
@@ -10807,23 +10857,28 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
        hda_nid_t pin, dac;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
-               pin = spec->autocfg.hp_pins[i];
-               if (!pin)
-                       break;
-               dac = spec->multiout.hp_nid;
-               if (!dac)
-                       dac = spec->multiout.dac_nids[0]; /* to front */
-               alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+       if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
+               for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+                       pin = spec->autocfg.hp_pins[i];
+                       if (!pin)
+                               break;
+                       dac = spec->multiout.hp_nid;
+                       if (!dac)
+                               dac = spec->multiout.dac_nids[0]; /* to front */
+                       alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+               }
        }
-       for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
-               pin = spec->autocfg.speaker_pins[i];
-               if (!pin)
-                       break;
-               dac = spec->multiout.extra_out_nid[0];
-               if (!dac)
-                       dac = spec->multiout.dac_nids[0]; /* to front */
-               alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+
+       if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
+               for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+                       pin = spec->autocfg.speaker_pins[i];
+                       if (!pin)
+                               break;
+                       dac = spec->multiout.extra_out_nid[0];
+                       if (!dac)
+                               dac = spec->multiout.dac_nids[0]; /* to front */
+                       alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+               }
        }
 }
 
@@ -14952,8 +15007,11 @@ static struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
-       SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
        {}
@@ -14987,7 +15045,7 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
-       SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC),
+       SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269VB_AMIC),
        SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
@@ -16027,9 +16085,12 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
-                       err = __alc861_create_out_sw(codec, name, nid, i, 3);
+                               index = 0;
+                       }
+                       err = __alc861_create_out_sw(codec, name, nid, index, 3);
                        if (err < 0)
                                return err;
                }
@@ -17180,16 +17241,19 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
+                               index = 0;
+                       }
                        err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-                                               name, i,
+                                               name, index,
                                          HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
                                                              HDA_OUTPUT));
                        if (err < 0)
                                return err;
                        err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-                                              name, i,
+                                              name, index,
                                          HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
                                                              HDA_INPUT));
                        if (err < 0)
@@ -18797,6 +18861,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
                                        ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
                           ALC663_ASUS_H13),
+       SND_PCI_QUIRK(0x1991, 0x5628, "Ordissimo EVE", ALC662_LENOVO_101E),
        {}
 };
 
@@ -19237,12 +19302,15 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
                                return err;
                } else {
                        const char *name = pfx;
-                       if (!name)
+                       int index = i;
+                       if (!name) {
                                name = chname[i];
-                       err = __alc662_add_vol_ctl(spec, name, nid, i, 3);
+                               index = 0;
+                       }
+                       err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
                        if (err < 0)
                                return err;
-                       err = __alc662_add_sw_ctl(spec, name, mix, i, 3);
+                       err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
                        if (err < 0)
                                return err;
                }
@@ -19457,6 +19525,7 @@ enum {
        ALC662_FIXUP_ASPIRE,
        ALC662_FIXUP_IDEAPAD,
        ALC272_FIXUP_MARIO,
+       ALC662_FIXUP_CZC_P10T,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -19477,14 +19546,23 @@ static const struct alc_fixup alc662_fixups[] = {
        [ALC272_FIXUP_MARIO] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc272_fixup_mario,
-       }
+       },
+       [ALC662_FIXUP_CZC_P10T] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
+                       {}
+               }
+       },
 };
 
 static struct snd_pci_quirk alc662_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
+       SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
        {}
 };