ALSA: hda - Use alc_get_pfx_name() for all Realtek codecs
[pandora-kernel.git] / sound / pci / hda / patch_realtek.c
index 7a4e100..cb8afda 100644 (file)
@@ -1141,6 +1141,13 @@ static void update_speakers(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        int on;
 
+       /* Control HP pins/amps depending on master_mute state;
+        * in general, HP pins/amps control should be enabled in all cases,
+        * but currently set only for master_mute, just to be safe
+        */
+       do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+                   spec->autocfg.hp_pins, spec->master_mute, true);
+
        if (!spec->automute)
                on = 0;
        else
@@ -3217,6 +3224,7 @@ static int alc_build_controls(struct hda_codec *codec)
        }
        if (spec->multiout.dig_out_nid) {
                err = snd_hda_create_spdif_out_ctls(codec,
+                                                   spec->multiout.dig_out_nid,
                                                    spec->multiout.dig_out_nid);
                if (err < 0)
                        return err;
@@ -4876,7 +4884,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
        SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
        SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
-       SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
        SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
        SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
        SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
@@ -5352,11 +5359,15 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
        return 0;
 }
 
-static const char *alc_get_line_out_pfx(struct alc_spec *spec,
-                                       bool can_be_master)
+static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
+                                       bool can_be_master, int *index)
 {
        struct auto_pin_cfg *cfg = &spec->autocfg;
+       static const char * const chname[4] = {
+               "Front", "Surround", NULL /*CLFE*/, "Side"
+       };
 
+       *index = 0;
        if (cfg->line_outs == 1 && !spec->multi_ios &&
            !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
                return "Master";
@@ -5367,23 +5378,23 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec,
                        return "Speaker";
                break;
        case AUTO_PIN_HP_OUT:
+               /* for multi-io case, only the primary out */
+               if (ch && spec->multi_ios)
+                       break;
+               *index = ch;
                return "Headphone";
        default:
                if (cfg->line_outs == 1 && !spec->multi_ios)
                        return "PCM";
                break;
        }
-       return NULL;
+       return chname[ch];
 }
 
 /* add playback controls from the parsed DAC table */
 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
-       static const char * const chname[4] = {
-               "Front", "Surround", NULL /*CLFE*/, "Side"
-       };
-       const char *pfx = alc_get_line_out_pfx(spec, false);
        hda_nid_t nid;
        int i, err, noutputs;
 
@@ -5392,10 +5403,13 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                noutputs += spec->multi_ios;
 
        for (i = 0; i < noutputs; i++) {
+               const char *name;
+               int index;
                if (!spec->multiout.dac_nids[i])
                        continue;
                nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
-               if (!pfx && i == 2) {
+               name = alc_get_line_out_pfx(spec, i, false, &index);
+               if (!name) {
                        /* Center/LFE */
                        err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
                                              "Center",
@@ -5422,12 +5436,6 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
                        if (err < 0)
                                return err;
                } else {
-                       const char *name = pfx;
-                       int index = i;
-                       if (!name) {
-                               name = chname[i];
-                               index = 0;
-                       }
                        err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
                                                name, index,
                                          HDA_COMPOSE_AMP_VAL(nid, 3, 0,
@@ -6201,11 +6209,6 @@ static const struct snd_kcontrol_new alc260_input_mixer[] = {
 /* update HP, line and mono out pins according to the master switch */
 static void alc260_hp_master_update(struct hda_codec *codec)
 {
-       struct alc_spec *spec = codec->spec;
-
-       /* change HP pins */
-       do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
-                   spec->autocfg.hp_pins, spec->master_mute, true);
        update_speakers(codec);
 }
 
@@ -7181,12 +7184,8 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
        nid = cfg->line_out_pins[0];
        if (nid) {
                const char *pfx;
-               if (!cfg->speaker_pins[0] && !cfg->hp_pins[0])
-                       pfx = "Master";
-               else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-                       pfx = "Speaker";
-               else
-                       pfx = "Front";
+               int index;
+               pfx = alc_get_line_out_pfx(spec, 0, true, &index);
                err = alc260_add_playback_controls(spec, nid, pfx, &vols);
                if (err < 0)
                        return err;
@@ -11924,7 +11923,7 @@ static const struct hda_verb alc262_nec_verbs[] = {
  *  0x1b = port replicator headphone out
  */
 
-#define ALC_HP_EVENT   0x37
+#define ALC_HP_EVENT   ALC880_HP_EVENT
 
 static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
        {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
@@ -12255,17 +12254,18 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
 {
        const char *pfx;
        int vbits;
-       int i, err;
+       int i, index, err;
 
        spec->multiout.num_dacs = 1;    /* only use one dac */
        spec->multiout.dac_nids = spec->private_dac_nids;
        spec->private_dac_nids[0] = 2;
 
-       pfx = alc_get_line_out_pfx(spec, true);
-       if (!pfx)
-               pfx = "Front";
        for (i = 0; i < 2; i++) {
-               err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i);
+               pfx = alc_get_line_out_pfx(spec, i, true, &index);
+               if (!pfx)
+                       pfx = "PCM";
+               err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx,
+                                           index);
                if (err < 0)
                        return err;
                if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
@@ -12285,10 +12285,11 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
        vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
                alc262_check_volbit(cfg->speaker_pins[0]) |
                alc262_check_volbit(cfg->hp_pins[0]);
-       if (vbits == 1 || vbits == 2)
-               pfx = "Master"; /* only one mixer is used */
        vbits = 0;
        for (i = 0; i < 2; i++) {
+               pfx = alc_get_line_out_pfx(spec, i, true, &index);
+               if (!pfx)
+                       pfx = "PCM";
                err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
                                             &vbits, i);
                if (err < 0)
@@ -12598,6 +12599,7 @@ static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
  */
 enum {
        PINFIX_FSC_H270,
+       PINFIX_HP_Z200,
 };
 
 static const struct alc_fixup alc262_fixups[] = {
@@ -12610,9 +12612,17 @@ static const struct alc_fixup alc262_fixups[] = {
                        { }
                }
        },
+       [PINFIX_HP_Z200] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x16, 0x99130120 }, /* internal speaker */
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
        SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
        {}
 };
@@ -12729,6 +12739,8 @@ static const struct snd_pci_quirk alc262_cfg_tbl[] = {
                           ALC262_HP_BPC),
        SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
                           ALC262_HP_BPC),
+       SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
+                          ALC262_AUTO),
        SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
                           ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
@@ -13314,9 +13326,8 @@ static void alc268_acer_lc_setup(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute_mixer_nid[0] = 0x0f;
        spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_MIXER;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
        spec->ext_mic.pin = 0x18;
        spec->ext_mic.mux_idx = 0;
        spec->int_mic.pin = 0x12;
@@ -13624,10 +13635,8 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
        nid = cfg->line_out_pins[0];
        if (nid) {
                const char *name;
-               if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-                       name = "Speaker";
-               else
-                       name = "Front";
+               int index;
+               name = alc_get_line_out_pfx(spec, 0, true, &index);
                err = alc268_new_analog_output(spec, nid, name, 0);
                if (err < 0)
                        return err;
@@ -13860,6 +13869,7 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
                                                ALC268_ACER_ASPIRE_ONE),
        SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
+       SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
        SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
                        "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
        /* almost compatible with toshiba but with optional digital outs;
@@ -13870,7 +13880,6 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
        SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
        SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
-       SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
        SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
        {}
 };
@@ -16023,10 +16032,6 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
                                             const struct auto_pin_cfg *cfg)
 {
        struct alc_spec *spec = codec->spec;
-       static const char * const chname[4] = {
-               "Front", "Surround", NULL /*CLFE*/, "Side"
-       };
-       const char *pfx = alc_get_line_out_pfx(spec, true);
        hda_nid_t nid;
        int i, err, noutputs;
 
@@ -16035,10 +16040,13 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
                noutputs += spec->multi_ios;
 
        for (i = 0; i < noutputs; i++) {
+               const char *name;
+               int index;
                nid = spec->multiout.dac_nids[i];
                if (!nid)
                        continue;
-               if (!pfx && i == 2) {
+               name = alc_get_line_out_pfx(spec, i, true, &index);
+               if (!name) {
                        /* Center/LFE */
                        err = alc861_create_out_sw(codec, "Center", nid, 1);
                        if (err < 0)
@@ -16047,12 +16055,6 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
                        if (err < 0)
                                return err;
                } else {
-                       const char *name = pfx;
-                       int index = i;
-                       if (!name) {
-                               name = chname[i];
-                               index = 0;
-                       }
                        err = __alc861_create_out_sw(codec, name, nid, index, 3);
                        if (err < 0)
                                return err;
@@ -17166,10 +17168,6 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
 static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                                             const struct auto_pin_cfg *cfg)
 {
-       static const char * const chname[4] = {
-               "Front", "Surround", "CLFE", "Side"
-       };
-       const char *pfx = alc_get_line_out_pfx(spec, true);
        hda_nid_t nid_v, nid_s;
        int i, err, noutputs;
 
@@ -17178,6 +17176,8 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                noutputs += spec->multi_ios;
 
        for (i = 0; i < noutputs; i++) {
+               const char *name;
+               int index;
                if (!spec->multiout.dac_nids[i])
                        continue;
                nid_v = alc861vd_idx_to_mixer_vol(
@@ -17187,7 +17187,8 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                                alc880_dac_to_idx(
                                        spec->multiout.dac_nids[i]));
 
-               if (!pfx && i == 2) {
+               name = alc_get_line_out_pfx(spec, i, true, &index);
+               if (!name) {
                        /* Center/LFE */
                        err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
                                              "Center",
@@ -17214,12 +17215,6 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
                        if (err < 0)
                                return err;
                } else {
-                       const char *name = pfx;
-                       int index = i;
-                       if (!name) {
-                               name = chname[i];
-                               index = 0;
-                       }
                        err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
                                                name, index,
                                          HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
@@ -18980,6 +18975,7 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
        hda_nid_t dac;
 
        spec->multiout.dac_nids = spec->private_dac_nids;
+       spec->multiout.num_dacs = 0;
        for (i = 0; i < cfg->line_outs; i++) {
                dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
                if (!dac)
@@ -19017,10 +19013,6 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
                                             const struct auto_pin_cfg *cfg)
 {
        struct alc_spec *spec = codec->spec;
-       static const char * const chname[4] = {
-               "Front", "Surround", NULL /*CLFE*/, "Side"
-       };
-       const char *pfx = alc_get_line_out_pfx(spec, true);
        hda_nid_t nid, mix, pin;
        int i, err, noutputs;
 
@@ -19029,6 +19021,8 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
                noutputs += spec->multi_ios;
 
        for (i = 0; i < noutputs; i++) {
+               const char *name;
+               int index;
                nid = spec->multiout.dac_nids[i];
                if (!nid)
                        continue;
@@ -19039,7 +19033,8 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
                mix = alc_auto_dac_to_mix(codec, pin, nid);
                if (!mix)
                        continue;
-               if (!pfx && i == 2) {
+               name = alc_get_line_out_pfx(spec, i, true, &index);
+               if (!name) {
                        /* Center/LFE */
                        err = alc662_add_vol_ctl(spec, "Center", nid, 1);
                        if (err < 0)
@@ -19054,12 +19049,6 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
                        if (err < 0)
                                return err;
                } else {
-                       const char *name = pfx;
-                       int index = i;
-                       if (!name) {
-                               name = chname[i];
-                               index = 0;
-                       }
                        err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
                        if (err < 0)
                                return err;
@@ -19314,8 +19303,20 @@ static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
        unsigned int location, defcfg;
        int num_pins;
 
+       if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
+               /* use HP as primary out */
+               cfg->speaker_outs = cfg->line_outs;
+               memcpy(cfg->speaker_pins, cfg->line_out_pins,
+                      sizeof(cfg->speaker_pins));
+               cfg->line_outs = cfg->hp_outs;
+               memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
+               cfg->hp_outs = 0;
+               memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+               cfg->line_out_type = AUTO_PIN_HP_OUT;
+               alc662_auto_fill_dac_nids(codec, cfg);
+       }
        if (cfg->line_outs != 1 ||
-           cfg->line_out_type != AUTO_PIN_LINE_OUT)
+           cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
                return 0;
 
        defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
@@ -19864,10 +19865,8 @@ static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec,
        nid = cfg->line_out_pins[0];
        if (nid) {
                const char *name;
-               if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-                       name = "Speaker";
-               else
-                       name = "Front";
+               int index;
+               name = alc_get_line_out_pfx(spec, 0, true, &index);
                err = alc680_new_analog_output(spec, nid, name, 0);
                if (err < 0)
                        return err;