ALSA: hda - Avoid overwrite of jack events with STAC/IDT
[pandora-kernel.git] / sound / pci / hda / patch_sigmatel.c
index 93e47c9..307e86c 100644 (file)
@@ -238,6 +238,11 @@ struct sigmatel_spec {
        unsigned int num_dmuxes;
        hda_nid_t *smux_nids;
        unsigned int num_smuxes;
+
+       unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */
+       unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */
+       unsigned int num_caps; /* number of capture volume/switch elements */
+
        const char **spdif_labels;
 
        hda_nid_t dig_in_nid;
@@ -334,6 +339,13 @@ static hda_nid_t stac92hd73xx_smux_nids[2] = {
        0x22, 0x23,
 };
 
+#define STAC92HD73XX_NUM_CAPS  2
+static unsigned long stac92hd73xx_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x20, 3, 0, HDA_OUTPUT),
+       HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
+};
+#define stac92hd73xx_capsws    stac92hd73xx_capvols
+
 #define STAC92HD83XXX_NUM_DMICS        2
 static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
        0x11, 0x12, 0
@@ -365,6 +377,13 @@ static hda_nid_t stac92hd83xxx_amp_nids[1] = {
        0xc,
 };
 
+#define STAC92HD83XXX_NUM_CAPS 2
+static unsigned long stac92hd83xxx_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
+       HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_OUTPUT),
+};
+#define stac92hd83xxx_capsws   stac92hd83xxx_capvols
+
 static hda_nid_t stac92hd71bxx_pwr_nids[3] = {
        0x0a, 0x0d, 0x0f
 };
@@ -394,6 +413,13 @@ static hda_nid_t stac92hd71bxx_slave_dig_outs[2] = {
        0x22, 0
 };
 
+#define STAC92HD71BXX_NUM_CAPS         2
+static unsigned long stac92hd71bxx_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT),
+       HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
+};
+#define stac92hd71bxx_capsws   stac92hd71bxx_capvols
+
 static hda_nid_t stac925x_adc_nids[1] = {
         0x03,
 };
@@ -415,6 +441,13 @@ static hda_nid_t stac925x_dmux_nids[1] = {
        0x14,
 };
 
+static unsigned long stac925x_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
+};
+static unsigned long stac925x_capsws[] = {
+       HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+};
+
 static hda_nid_t stac922x_adc_nids[2] = {
         0x06, 0x07,
 };
@@ -423,6 +456,13 @@ static hda_nid_t stac922x_mux_nids[2] = {
         0x12, 0x13,
 };
 
+#define STAC922X_NUM_CAPS      2
+static unsigned long stac922x_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT),
+       HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT),
+};
+#define stac922x_capsws                stac922x_capvols
+
 static hda_nid_t stac927x_slave_dig_outs[2] = {
        0x1f, 0,
 };
@@ -452,6 +492,18 @@ static hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = {
        0x13, 0x14, 0
 };
 
+#define STAC927X_NUM_CAPS      3
+static unsigned long stac927x_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT),
+       HDA_COMPOSE_AMP_VAL(0x19, 3, 0, HDA_INPUT),
+       HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_INPUT),
+};
+static unsigned long stac927x_capsws[] = {
+       HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+       HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT),
+       HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
+};
+
 static const char *stac927x_spdif_labels[5] = {
        "Digital Playback", "ADAT", "Analog Mux 1",
        "Analog Mux 2", "Analog Mux 3"
@@ -478,6 +530,16 @@ static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = {
         0x17, 0x18, 0
 };
 
+#define STAC9205_NUM_CAPS      2
+static unsigned long stac9205_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_INPUT),
+       HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_INPUT),
+};
+static unsigned long stac9205_capsws[] = {
+       HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
+       HDA_COMPOSE_AMP_VAL(0x1e, 3, 0, HDA_OUTPUT),
+};
+
 static hda_nid_t stac9200_pin_nids[8] = {
        0x08, 0x09, 0x0d, 0x0e, 
        0x0f, 0x10, 0x11, 0x12,
@@ -639,7 +701,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
 static unsigned int stac92xx_vref_set(struct hda_codec *codec,
                                        hda_nid_t nid, unsigned int new_vref)
 {
-       unsigned int error;
+       int error;
        unsigned int pincfg;
        pincfg = snd_hda_codec_read(codec, nid, 0,
                                AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
@@ -1069,12 +1131,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
        HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT),
        HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT),
 
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT),
-
        { } /* end */
 };
 
@@ -1094,12 +1150,6 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = {
 };
 
 static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT),
-
        HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT),
 
@@ -1118,12 +1168,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
 };
 
 static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT),
-
        HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT),
        HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT),
 
@@ -1143,12 +1187,6 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {
 
 
 static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT),
-
        HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT),
        HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT),
 
@@ -1169,17 +1207,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
 };
 
 static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT),
-       /* analog pc-beep replaced with digital beep support */
-       /*
-       HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT),
-       HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT),
-       */
-
        HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT),
        HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT),
 
@@ -1198,29 +1225,9 @@ static struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
        STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2)
 };
 
-static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT),
-       { } /* end */
-};
-
 static struct snd_kcontrol_new stac925x_mixer[] = {
        HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
-       HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT),
-       { } /* end */
-};
-
-static struct snd_kcontrol_new stac9205_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT),
        { } /* end */
 };
 
@@ -1229,29 +1236,6 @@ static struct snd_kcontrol_new stac9205_loopback[] = {
        {}
 };
 
-/* This needs to be generated dynamically based on sequence */
-static struct snd_kcontrol_new stac922x_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT),
-       { } /* end */
-};
-
-
-static struct snd_kcontrol_new stac927x_mixer[] = {
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT),
-
-       HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT),
-       HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT),
-       { } /* end */
-};
-
 static struct snd_kcontrol_new stac927x_loopback[] = {
        STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
        {}
@@ -1309,9 +1293,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
        int err;
        int i;
 
-       err = snd_hda_add_new_ctls(codec, spec->mixer);
-       if (err < 0)
-               return err;
+       if (spec->mixer) {
+               err = snd_hda_add_new_ctls(codec, spec->mixer);
+               if (err < 0)
+                       return err;
+       }
 
        for (i = 0; i < spec->num_mixers; i++) {
                err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
@@ -1590,8 +1576,6 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
        /* SigmaTel reference board */
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
                      "DFI LanParty", STAC_REF),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30,
-                     "SigmaTel",STAC_9205_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
                      "DFI LanParty", STAC_REF),
        /* Dell laptops have BIOS problem */
@@ -2344,6 +2328,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
        /* SigmaTel reference board */
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
                      "DFI LanParty", STAC_9205_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30,
+                     "SigmaTel", STAC_9205_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
                      "DFI LanParty", STAC_9205_REF),
        /* Dell */
@@ -2378,6 +2364,7 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
                      "Dell Vostro 1500", STAC_9205_DELL_M42),
        /* Gateway */
+       SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD),
        SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD),
        {} /* terminator */
 };
@@ -2633,8 +2620,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
-                                  unsigned char type);
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid);
 
 static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
@@ -2648,7 +2634,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
        /* check to be sure that the ports are upto date with
         * switch changes
         */
-       stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
+       stac_issue_unsol_event(codec, nid);
 
        return 1;
 }
@@ -2703,7 +2689,7 @@ static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int new_vref = 0;
-       unsigned int error;
+       int error;
        hda_nid_t nid = kcontrol->private_value;
 
        if (ucontrol->value.enumerated.item[0] == 0)
@@ -2781,7 +2767,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
         * appropriately according to the pin direction
         */
        if (spec->hp_detect)
-               stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
+               stac_issue_unsol_event(codec, nid);
 
         return 1;
 }
@@ -3057,7 +3043,7 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
                                           HDA_MAX_CONNECTIONS);
        for (j = 0; j < conn_len; j++) {
                wcaps = get_wcaps(codec, conn[j]);
-               wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+               wtype = get_wcaps_type(wcaps);
                /* we check only analog outputs */
                if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL))
                        continue;
@@ -3316,6 +3302,21 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
        return 0;
 }
 
+static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol,
+                                   unsigned long sw, int idx)
+{
+       int err;
+       err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx,
+                                      "Captuer Volume", vol);
+       if (err < 0)
+               return err;
+       err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_MUTE, idx,
+                                      "Captuer Switch", sw);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
 /* add playback controls from the parsed DAC table */
 static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
                                               const struct auto_pin_cfg *cfg)
@@ -3389,7 +3390,7 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec)
                                spec->mono_nid,
                                con_lst,
                                HDA_MAX_NUM_INPUTS);
-       if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
+       if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
                return -EINVAL;
 
        for (i = 0; i < num_cons; i++) {
@@ -3535,7 +3536,7 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec)
                                spec->smux_nids[0],
                                con_lst,
                                HDA_MAX_NUM_INPUTS);
-       if (!num_cons)
+       if (num_cons <= 0)
                return -EINVAL;
 
        if (!labels)
@@ -3702,7 +3703,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
 {
        struct sigmatel_spec *spec = codec->spec;
        int hp_swap = 0;
-       int err;
+       int i, err;
 
        if ((err = snd_hda_parse_pin_def_config(codec,
                                                &spec->autocfg,
@@ -3742,11 +3743,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
                if (snd_hda_get_connections(codec,
                                spec->autocfg.mono_out_pin, conn_list, 1) &&
                                snd_hda_get_connections(codec, conn_list[0],
-                               conn_list, 1)) {
+                               conn_list, 1) > 0) {
 
                                int wcaps = get_wcaps(codec, conn_list[0]);
-                               int wid_type = (wcaps & AC_WCAP_TYPE)
-                                       >> AC_WCAP_TYPE_SHIFT;
+                               int wid_type = get_wcaps_type(wcaps);
                                /* LR swap check, some stac925x have a mux that
                                 * changes the DACs output path instead of the
                                 * mono-mux path.
@@ -3837,6 +3837,13 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
                spec->autocfg.line_outs = 0;
        }
 
+       for (i = 0; i < spec->num_caps; i++) {
+               err = stac92xx_add_capvol_ctls(codec, spec->capvols[i],
+                                              spec->capsws[i], i);
+               if (err < 0)
+                       return err;
+       }
+
        err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
@@ -4035,7 +4042,7 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
                           AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
 }
 
-#ifdef CONFIG_SND_JACK
+#ifdef CONFIG_SND_HDA_INPUT_JACK
 static void stac92xx_free_jack_priv(struct snd_jack *jack)
 {
        struct sigmatel_jack *jacks = jack->private_data;
@@ -4047,7 +4054,7 @@ static void stac92xx_free_jack_priv(struct snd_jack *jack)
 static int stac92xx_add_jack(struct hda_codec *codec,
                hda_nid_t nid, int type)
 {
-#ifdef CONFIG_SND_JACK
+#ifdef CONFIG_SND_HDA_INPUT_JACK
        struct sigmatel_spec *spec = codec->spec;
        struct sigmatel_jack *jack;
        int def_conf = snd_hda_codec_get_pincfg(codec, nid);
@@ -4065,7 +4072,7 @@ static int stac92xx_add_jack(struct hda_codec *codec,
        jack->nid = nid;
        jack->type = type;
 
-       sprintf(name, "%s at %s %s Jack",
+       snprintf(name, sizeof(name), "%s at %s %s Jack",
                snd_hda_get_jack_type(def_conf),
                snd_hda_get_jack_connectivity(def_conf),
                snd_hda_get_jack_location(def_conf));
@@ -4099,14 +4106,14 @@ static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
 }
 
 static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
-                                            hda_nid_t nid, unsigned char type)
+                                            hda_nid_t nid)
 {
        struct sigmatel_spec *spec = codec->spec;
        struct sigmatel_event *event = spec->events.list;
        int i;
 
        for (i = 0; i < spec->events.used; i++, event++) {
-               if (event->nid == nid && event->type == type)
+               if (event->nid == nid)
                        return event;
        }
        return NULL;
@@ -4126,24 +4133,32 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
        return NULL;
 }
 
-static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
-                             unsigned int type)
+/* check if given nid is a valid pin and no other events are assigned
+ * to it.  If OK, assign the event, set the unsol flag, and returns 1.
+ * Otherwise, returns zero.
+ */
+static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
+                            unsigned int type)
 {
        struct sigmatel_event *event;
        int tag;
 
        if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
-               return;
-       event = stac_get_event(codec, nid, type);
-       if (event)
+               return 0;
+       event = stac_get_event(codec, nid);
+       if (event) {
+               if (event->type != type)
+                       return 0;
                tag = event->tag;
-       else
+       } else {
                tag = stac_add_event(codec->spec, nid, type, 0);
-       if (tag < 0)
-               return;
+               if (tag < 0)
+                       return 0;
+       }
        snd_hda_codec_write_cache(codec, nid, 0,
                                  AC_VERB_SET_UNSOLICITED_ENABLE,
                                  AC_USRSP_EN | tag);
+       return 1;
 }
 
 static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
@@ -4242,8 +4257,7 @@ static int stac92xx_init(struct hda_codec *codec)
                stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
                                AC_PINCTL_OUT_EN);
                /* fake event to set up pins */
-               stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
-                                      STAC_HP_EVENT);
+               stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]);
        } else {
                stac92xx_auto_init_multi_out(codec);
                stac92xx_auto_init_hp_out(codec);
@@ -4276,10 +4290,9 @@ static int stac92xx_init(struct hda_codec *codec)
                        }
                        conf = snd_hda_codec_get_pincfg(codec, nid);
                        if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
-                               enable_pin_detect(codec, nid,
-                                                 STAC_INSERT_EVENT);
-                               stac_issue_unsol_event(codec, nid,
-                                                      STAC_INSERT_EVENT);
+                               if (enable_pin_detect(codec, nid,
+                                                     STAC_INSERT_EVENT))
+                                       stac_issue_unsol_event(codec, nid);
                        }
                }
        }
@@ -4324,10 +4337,8 @@ static int stac92xx_init(struct hda_codec *codec)
                                stac_toggle_power_map(codec, nid, 1);
                        continue;
                }
-               if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) {
-                       enable_pin_detect(codec, nid, STAC_PWR_EVENT);
-                       stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
-               }
+               if (enable_pin_detect(codec, nid, STAC_PWR_EVENT))
+                       stac_issue_unsol_event(codec, nid);
        }
        if (spec->dac_list)
                stac92xx_power_down(codec);
@@ -4336,7 +4347,7 @@ static int stac92xx_init(struct hda_codec *codec)
 
 static void stac92xx_free_jacks(struct hda_codec *codec)
 {
-#ifdef CONFIG_SND_JACK
+#ifdef CONFIG_SND_HDA_INPUT_JACK
        /* free jack instances manually when clearing/reconfiguring */
        struct sigmatel_spec *spec = codec->spec;
        if (!codec->bus->shutdown && spec->jacks.list) {
@@ -4590,10 +4601,9 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
        }
 }
 
-static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
-                                  unsigned char type)
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
 {
-       struct sigmatel_event *event = stac_get_event(codec, nid, type);
+       struct sigmatel_event *event = stac_get_event(codec, nid);
        if (!event)
                return;
        codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
@@ -4704,8 +4714,7 @@ static int stac92xx_resume(struct hda_codec *codec)
        snd_hda_codec_resume_cache(codec);
        /* fake event to set up pins again to override cached values */
        if (spec->hp_detect)
-               stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
-                                      STAC_HP_EVENT);
+               stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]);
        return 0;
 }
 
@@ -4745,6 +4754,19 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
 static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
 {
        struct sigmatel_spec *spec = codec->spec;
+       int i;
+       hda_nid_t nid;
+
+       /* reset each pin before powering down DAC/ADC to avoid click noise */
+       nid = codec->start_nid;
+       for (i = 0; i < codec->num_nodes; i++, nid++) {
+               unsigned int wcaps = get_wcaps(codec, nid);
+               unsigned int wid_type = get_wcaps_type(wcaps);
+               if (wid_type == AC_WID_PIN)
+                       snd_hda_codec_read(codec, nid, 0,
+                               AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
+       }
+
        if (spec->eapd_mask)
                stac_gpio_set(codec, spec->gpio_mask,
                                spec->gpio_dir, spec->gpio_data &
@@ -4781,7 +4803,8 @@ static int patch_stac9200(struct hda_codec *codec)
                                                        stac9200_models,
                                                        stac9200_cfg_tbl);
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac9200_brd_tbl[spec->board_config]);
@@ -4853,8 +4876,8 @@ static int patch_stac925x(struct hda_codec *codec)
                                                        stac925x_cfg_tbl);
  again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
-                                     "using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac925x_brd_tbl[spec->board_config]);
@@ -4884,6 +4907,9 @@ static int patch_stac925x(struct hda_codec *codec)
 
        spec->init = stac925x_core_init;
        spec->mixer = stac925x_mixer;
+       spec->num_caps = 1;
+       spec->capvols = stac925x_capvols;
+       spec->capsws = stac925x_capsws;
 
        err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
        if (!err) {
@@ -4936,8 +4962,8 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
                                                        stac92hd73xx_cfg_tbl);
 again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for"
-                       " STAC92HD73XX, using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac92hd73xx_brd_tbl[spec->board_config]);
@@ -4987,6 +5013,10 @@ again:
        memcpy(&spec->private_dimux, &stac92hd73xx_dmux,
                        sizeof(stac92hd73xx_dmux));
 
+       spec->num_caps = STAC92HD73XX_NUM_CAPS;
+       spec->capvols = stac92hd73xx_capvols;
+       spec->capsws = stac92hd73xx_capsws;
+
        switch (spec->board_config) {
        case STAC_DELL_EQ:
                spec->init = dell_eq_core_init;
@@ -5106,14 +5136,18 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        spec->num_dmics = STAC92HD83XXX_NUM_DMICS;
        spec->dinput_mux = &stac92hd83xxx_dmux;
        spec->pin_nids = stac92hd83xxx_pin_nids;
+       spec->num_caps = STAC92HD83XXX_NUM_CAPS;
+       spec->capvols = stac92hd83xxx_capvols;
+       spec->capsws = stac92hd83xxx_capsws;
+
        spec->board_config = snd_hda_check_board_config(codec,
                                                        STAC_92HD83XXX_MODELS,
                                                        stac92hd83xxx_models,
                                                        stac92hd83xxx_cfg_tbl);
 again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for"
-                       " STAC92HD83XXX, using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac92hd83xxx_brd_tbl[spec->board_config]);
@@ -5155,6 +5189,8 @@ again:
 
        num_dacs = snd_hda_get_connections(codec, nid,
                                conn, STAC92HD83_DAC_COUNT + 1) - 1;
+       if (num_dacs < 0)
+               num_dacs = STAC92HD83_DAC_COUNT;
 
        /* set port X to select the last DAC
         */
@@ -5276,8 +5312,8 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
                                                        stac92hd71bxx_cfg_tbl);
 again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for"
-                       " STAC92HD71BXX, using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac92hd71bxx_brd_tbl[spec->board_config]);
@@ -5292,6 +5328,10 @@ again:
        spec->dmic_nids = stac92hd71bxx_dmic_nids;
        spec->dmux_nids = stac92hd71bxx_dmux_nids;
 
+       spec->num_caps = STAC92HD71BXX_NUM_CAPS;
+       spec->capvols = stac92hd71bxx_capvols;
+       spec->capsws = stac92hd71bxx_capsws;
+
        switch (codec->vendor_id) {
        case 0x111d76b6: /* 4 Port without Analog Mixer */
        case 0x111d76b7:
@@ -5301,7 +5341,6 @@ again:
        case 0x111d76b5:
                memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer,
                       sizeof(stac92hd71bxx_dmux_nomixer));
-               spec->mixer = stac92hd71bxx_mixer;
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
@@ -5338,8 +5377,8 @@ again:
 
                /* no output amps */
                spec->num_pwrs = 0;
-               spec->mixer = stac92hd71bxx_analog_mixer;
-               spec->dinput_mux = &spec->private_dimux;
+               if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1)
+                       spec->mixer = stac92hd71bxx_analog_mixer;
 
                /* disable VSW */
                spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
@@ -5350,8 +5389,11 @@ again:
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS - 1);
-               spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
-               ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
+               if (spec->num_dmics) {
+                       spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+                       spec->dinput_mux = &spec->private_dimux;
+                       ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
+               }
                break;
        case 0x111d7603: /* 6 Port with Analog Mixer */
                if ((codec->revision_id & 0xf) == 1)
@@ -5363,15 +5405,18 @@ again:
        default:
                memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer,
                       sizeof(stac92hd71bxx_dmux_amixer));
-               spec->dinput_mux = &spec->private_dimux;
-               spec->mixer = stac92hd71bxx_analog_mixer;
+               if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1)
+                       spec->mixer = stac92hd71bxx_analog_mixer;
                spec->init = stac92hd71bxx_analog_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
                spec->num_dmics = stac92hd71bxx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS);
-               spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
-               ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
+               if (spec->num_dmics) {
+                       spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+                       spec->dinput_mux = &spec->private_dimux;
+                       ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1;
+               }
        }
 
        if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
@@ -5532,8 +5577,8 @@ static int patch_stac922x(struct hda_codec *codec)
 
  again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
-                       "using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac922x_brd_tbl[spec->board_config]);
@@ -5546,7 +5591,10 @@ static int patch_stac922x(struct hda_codec *codec)
        spec->num_pwrs = 0;
 
        spec->init = stac922x_core_init;
-       spec->mixer = stac922x_mixer;
+
+       spec->num_caps = STAC922X_NUM_CAPS;
+       spec->capvols = stac922x_capvols;
+       spec->capsws = stac922x_capsws;
 
        spec->multiout.dac_nids = spec->dac_nids;
        
@@ -5595,8 +5643,8 @@ static int patch_stac927x(struct hda_codec *codec)
                                                        stac927x_cfg_tbl);
  again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for"
-                           "STAC927x, using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                stac927x_brd_tbl[spec->board_config]);
@@ -5621,7 +5669,6 @@ static int patch_stac927x(struct hda_codec *codec)
                spec->num_dmics = 0;
 
                spec->init = d965_core_init;
-               spec->mixer = stac927x_mixer;
                break;
        case STAC_DELL_BIOS:
                switch (codec->subsystem_id) {
@@ -5646,7 +5693,6 @@ static int patch_stac927x(struct hda_codec *codec)
                spec->num_dmics = STAC927X_NUM_DMICS;
 
                spec->init = d965_core_init;
-               spec->mixer = stac927x_mixer;
                spec->dmux_nids = stac927x_dmux_nids;
                spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids);
                break;
@@ -5659,9 +5705,12 @@ static int patch_stac927x(struct hda_codec *codec)
                spec->num_dmics = 0;
 
                spec->init = stac927x_core_init;
-               spec->mixer = stac927x_mixer;
        }
 
+       spec->num_caps = STAC927X_NUM_CAPS;
+       spec->capvols = stac927x_capvols;
+       spec->capsws = stac927x_capsws;
+
        spec->num_pwrs = 0;
        spec->aloopback_ctl = stac927x_loopback;
        spec->aloopback_mask = 0x40;
@@ -5723,7 +5772,8 @@ static int patch_stac9205(struct hda_codec *codec)
                                                        stac9205_cfg_tbl);
  again:
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac9205_brd_tbl[spec->board_config]);
@@ -5742,9 +5792,12 @@ static int patch_stac9205(struct hda_codec *codec)
        spec->num_pwrs = 0;
 
        spec->init = stac9205_core_init;
-       spec->mixer = stac9205_mixer;
        spec->aloopback_ctl = stac9205_loopback;
 
+       spec->num_caps = STAC9205_NUM_CAPS;
+       spec->capvols = stac9205_capvols;
+       spec->capsws = stac9205_capsws;
+
        spec->aloopback_mask = 0x40;
        spec->aloopback_shift = 0;
        /* Turn on/off EAPD per HP plugging */
@@ -5819,12 +5872,6 @@ static struct hda_verb stac9872_core_init[] = {
        {}
 };
 
-static struct snd_kcontrol_new stac9872_mixer[] = {
-       HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
-       HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
-       { } /* end */
-};
-
 static hda_nid_t stac9872_pin_nids[] = {
        0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x11, 0x13, 0x14,
@@ -5838,6 +5885,11 @@ static hda_nid_t stac9872_mux_nids[] = {
        0x15
 };
 
+static unsigned long stac9872_capvols[] = {
+       HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
+};
+#define stac9872_capsws                stac9872_capvols
+
 static unsigned int stac9872_vaio_pin_configs[9] = {
        0x03211020, 0x411111f0, 0x411111f0, 0x03a15030,
        0x411111f0, 0x90170110, 0x411111f0, 0x411111f0,
@@ -5854,6 +5906,8 @@ static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
 };
 
 static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+       SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
+                          "Sony VAIO F/S", STAC_9872_VAIO),
        {} /* terminator */
 };
 
@@ -5866,26 +5920,28 @@ static int patch_stac9872(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
        codec->spec = spec;
+       spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
+       spec->pin_nids = stac9872_pin_nids;
 
        spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
                                                        stac9872_models,
                                                        stac9872_cfg_tbl);
        if (spec->board_config < 0)
-               snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, "
-                           "using BIOS defaults\n");
+               snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+                           codec->chip_name);
        else
                stac92xx_set_config_regs(codec,
                                         stac9872_brd_tbl[spec->board_config]);
 
-       spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
-       spec->pin_nids = stac9872_pin_nids;
        spec->multiout.dac_nids = spec->dac_nids;
        spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids);
        spec->adc_nids = stac9872_adc_nids;
        spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids);
        spec->mux_nids = stac9872_mux_nids;
-       spec->mixer = stac9872_mixer;
        spec->init = stac9872_core_init;
+       spec->num_caps = 1;
+       spec->capvols = stac9872_capvols;
+       spec->capsws = stac9872_capsws;
 
        err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
        if (err < 0) {