]> git.karo-electronics.de Git - linux-beck.git/blobdiff - sound/pci/hda/patch_realtek.c
Merge branch 'fix/hda' into topic/hda
[linux-beck.git] / sound / pci / hda / patch_realtek.c
index 1d07e8fa243360d25236a4942ab5e363d69d1558..8a74c1e8eedb00da49aec145722185d61b2f8bc7 100644 (file)
@@ -183,6 +183,7 @@ struct alc_spec {
        unsigned int single_input_src:1;
        unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
        unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
+       unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
 
        /* auto-mute control */
        int automute_mode;
@@ -283,6 +284,8 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx)
                spec->capsrc_nids[idx] : spec->adc_nids[idx];
 }
 
+static void call_update_outputs(struct hda_codec *codec);
+
 /* select the given imux item; either unmute exclusively or select the route */
 static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
                          unsigned int idx, bool force)
@@ -306,6 +309,19 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
                return 0;
        spec->cur_mux[adc_idx] = idx;
 
+       /* for shared I/O, change the pin-control accordingly */
+       if (spec->shared_mic_hp) {
+               /* NOTE: this assumes that there are only two inputs, the
+                * first is the real internal mic and the second is HP jack.
+                */
+               snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   spec->cur_mux[adc_idx] ?
+                                   PIN_VREF80 : PIN_HP);
+               spec->automute_speaker = !spec->cur_mux[adc_idx];
+               call_update_outputs(codec);
+       }
+
        if (spec->dyn_adc_switch) {
                alc_dyn_adc_pcm_resetup(codec, idx);
                adc_idx = spec->dyn_adc_idx[idx];
@@ -554,7 +570,8 @@ static void update_outputs(struct hda_codec *codec)
         * 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),
+       if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
+               do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
                    spec->autocfg.hp_pins, spec->master_mute, true);
 
        if (!spec->automute_speaker)
@@ -1133,6 +1150,9 @@ static void alc_init_auto_mic(struct hda_codec *codec)
        hda_nid_t fixed, ext, dock;
        int i;
 
+       if (spec->shared_mic_hp)
+               return; /* no auto-mic for the shared I/O */
+
        spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
 
        fixed = ext = dock = 0;
@@ -1524,6 +1544,7 @@ static void alc_pick_fixup(struct hda_codec *codec,
                           const struct alc_fixup *fixlist)
 {
        struct alc_spec *spec = codec->spec;
+       const struct snd_pci_quirk *q;
        int id = -1;
        const char *name = NULL;
 
@@ -1538,14 +1559,27 @@ static void alc_pick_fixup(struct hda_codec *codec,
                }
        }
        if (id < 0) {
-               quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
-               if (quirk) {
-                       id = quirk->value;
+               q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+               if (q) {
+                       id = q->value;
 #ifdef CONFIG_SND_DEBUG_VERBOSE
-                       name = quirk->name;
+                       name = q->name;
 #endif
                }
        }
+       if (id < 0) {
+               for (q = quirk; q->subvendor; q++) {
+                       unsigned int vendorid =
+                               q->subdevice | (q->subvendor << 16);
+                       if (vendorid == codec->subsystem_id) {
+                               id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+                               name = q->name;
+#endif
+                               break;
+                       }
+               }
+       }
 
        spec->fixup_id = id;
        if (id >= 0) {
@@ -2685,6 +2719,9 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
        int max_nums = ARRAY_SIZE(spec->private_adc_nids);
        int i, nums = 0;
 
+       if (spec->shared_mic_hp)
+               max_nums = 1; /* no multi streams with the shared HP/mic */
+
        nid = codec->start_nid;
        for (i = 0; i < codec->num_nodes; i++, nid++) {
                hda_nid_t src;
@@ -2747,6 +2784,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
                        continue;
 
                label = hda_get_autocfg_input_label(codec, cfg, i);
+               if (spec->shared_mic_hp && !strcmp(label, "Misc"))
+                       label = "Headphone Mic";
                if (prev_label && !strcmp(label, prev_label))
                        type_idx++;
                else
@@ -2781,6 +2820,39 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
        return 0;
 }
 
+/* create a shared input with the headphone out */
+static int alc_auto_create_shared_input(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       unsigned int defcfg;
+       hda_nid_t nid;
+
+       /* only one internal input pin? */
+       if (cfg->num_inputs != 1)
+               return 0;
+       defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
+       if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
+               return 0;
+
+       if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+               nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
+       else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
+               nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
+       else
+               return 0; /* both not available */
+
+       if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
+               return 0; /* no input */
+
+       cfg->inputs[1].pin = nid;
+       cfg->inputs[1].type = AUTO_PIN_MIC;
+       cfg->num_inputs = 2;
+       spec->shared_mic_hp = 1;
+       snd_printdd("realtek: Enable shared I/O jack on NID 0x%x\n", nid);
+       return 0;
+}
+
 static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
                               unsigned int pin_type)
 {
@@ -2919,6 +2991,23 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
        return 0;
 }
 
+/* check whether the DAC is reachable from the pin */
+static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
+                                     hda_nid_t pin, hda_nid_t dac)
+{
+       hda_nid_t srcs[5];
+       int i, num;
+
+       pin = alc_go_down_to_selector(codec, pin);
+       num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
+       for (i = 0; i < num; i++) {
+               hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
+               if (nid == dac)
+                       return true;
+       }
+       return false;
+}
+
 static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
 {
        hda_nid_t sel = alc_go_down_to_selector(codec, pin);
@@ -2949,13 +3038,15 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
 }
 
 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
-                                  unsigned int location);
+                                  unsigned int location, int offset);
 
 /* fill in the dac_nids table from the parsed pin configuration */
 static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
+       unsigned int location, defcfg;
+       int num_pins;
        bool redone = false;
        int i;
 
@@ -3010,13 +3101,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
 
        if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
                /* try to fill multi-io first */
-               unsigned int location, defcfg;
-               int num_pins;
-
                defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
                location = get_defcfg_location(defcfg);
 
-               num_pins = alc_auto_fill_multi_ios(codec, location);
+               num_pins = alc_auto_fill_multi_ios(codec, location, 0);
                if (num_pins > 0) {
                        spec->multi_ios = num_pins;
                        spec->ext_channel_count = 2;
@@ -3050,6 +3138,21 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
                }
        }
 
+       if (!spec->multi_ios &&
+           cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
+           cfg->hp_outs) {
+               /* try multi-ios with HP + inputs */
+               defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
+               location = get_defcfg_location(defcfg);
+
+               num_pins = alc_auto_fill_multi_ios(codec, location, 1);
+               if (num_pins > 0) {
+                       spec->multi_ios = num_pins;
+                       spec->ext_channel_count = 2;
+                       spec->multiout.num_dacs = num_pins + 1;
+               }
+       }
+
        return 0;
 }
 
@@ -3081,8 +3184,15 @@ static int alc_auto_add_vol_ctl(struct hda_codec *codec,
                                 val);
 }
 
-#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
-       alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
+static int alc_auto_add_stereo_vol(struct hda_codec *codec,
+                                  const char *pfx, int cidx,
+                                  hda_nid_t nid)
+{
+       int chs = 1;
+       if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
+               chs = 3;
+       return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs);
+}
 
 /* create a mute-switch for the given mixer widget;
  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
@@ -3114,8 +3224,14 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
        return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
 }
 
-#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid)  \
-       alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
+static int alc_auto_add_stereo_sw(struct hda_codec *codec, const char *pfx,
+                                 int cidx, hda_nid_t nid)
+{
+       int chs = 1;
+       if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
+               chs = 3;
+       return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs);
+}
 
 static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
                                           hda_nid_t pin, hda_nid_t dac)
@@ -3441,17 +3557,19 @@ static void alc_auto_init_extra_out(struct hda_codec *codec)
  * multi-io helper
  */
 static int alc_auto_fill_multi_ios(struct hda_codec *codec,
-                                  unsigned int location)
+                                  unsigned int location,
+                                  int offset)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
        hda_nid_t prime_dac = spec->private_dac_nids[0];
-       int type, i, num_pins = 0;
+       int type, i, dacs, num_pins = 0;
 
+       dacs = spec->multiout.num_dacs;
        for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
                for (i = 0; i < cfg->num_inputs; i++) {
                        hda_nid_t nid = cfg->inputs[i].pin;
-                       hda_nid_t dac;
+                       hda_nid_t dac = 0;
                        unsigned int defcfg, caps;
                        if (cfg->inputs[i].type != type)
                                continue;
@@ -3463,7 +3581,13 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
                        caps = snd_hda_query_pin_caps(codec, nid);
                        if (!(caps & AC_PINCAP_OUT))
                                continue;
-                       dac = alc_auto_look_for_dac(codec, nid);
+                       if (offset && offset + num_pins < dacs) {
+                               dac = spec->private_dac_nids[offset + num_pins];
+                               if (!alc_auto_is_dac_reachable(codec, nid, dac))
+                                       dac = 0;
+                       }
+                       if (!dac)
+                               dac = alc_auto_look_for_dac(codec, nid);
                        if (!dac)
                                continue;
                        spec->multi_io[num_pins].pin = nid;
@@ -3472,11 +3596,11 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
                        spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
                }
        }
-       spec->multiout.num_dacs = 1;
+       spec->multiout.num_dacs = dacs;
        if (num_pins < 2) {
                /* clear up again */
-               memset(spec->private_dac_nids, 0,
-                      sizeof(spec->private_dac_nids));
+               memset(spec->private_dac_nids + dacs, 0,
+                      sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
                spec->private_dac_nids[0] = prime_dac;
                return 0;
        }
@@ -3700,6 +3824,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
                        char boost_label[32];
 
                        label = hda_get_autocfg_input_label(codec, cfg, i);
+                       if (spec->shared_mic_hp && !strcmp(label, "Misc"))
+                               label = "Headphone Mic";
                        if (prev_label && !strcmp(label, prev_label))
                                type_idx++;
                        else
@@ -3902,6 +4028,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
        if (err < 0)
                return err;
        err = alc_auto_create_speaker_out(codec);
+       if (err < 0)
+               return err;
+       err = alc_auto_create_shared_input(codec);
        if (err < 0)
                return err;
        err = alc_auto_create_input_ctls(codec);
@@ -3950,6 +4079,37 @@ static const struct hda_amp_list alc880_loopbacks[] = {
 };
 #endif
 
+/*
+ * ALC880 fix-ups
+ */
+enum {
+       ALC880_FIXUP_GPIO2,
+       ALC880_FIXUP_MEDION_RIM,
+};
+
+static const struct alc_fixup alc880_fixups[] = {
+       [ALC880_FIXUP_GPIO2] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = alc_gpio2_init_verbs,
+       },
+       [ALC880_FIXUP_MEDION_RIM] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF,  0x3060 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC880_FIXUP_GPIO2,
+       },
+};
+
+static const struct snd_pci_quirk alc880_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
+       {}
+};
+
+
 /*
  * board setups
  */
@@ -3995,6 +4155,11 @@ static int patch_alc880(struct hda_codec *codec)
                board_config = ALC_MODEL_AUTO;
        }
 
+       if (board_config == ALC_MODEL_AUTO) {
+               alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups);
+               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+       }
+
        if (board_config == ALC_MODEL_AUTO) {
                /* automatic parse from the BIOS config */
                err = alc880_parse_auto_config(codec);
@@ -4029,6 +4194,8 @@ static int patch_alc880(struct hda_codec *codec)
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
        }
 
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+
        spec->vmaster_nid = 0x0c;
 
        codec->patch_ops = alc_patch_ops;
@@ -4196,15 +4363,78 @@ static int patch_alc260(struct hda_codec *codec)
  * Pin config fixes
  */
 enum {
-       PINFIX_ABIT_AW9D_MAX,
-       PINFIX_LENOVO_Y530,
-       PINFIX_PB_M5210,
-       PINFIX_ACER_ASPIRE_7736,
-       PINFIX_ASUS_W90V,
+       ALC882_FIXUP_ABIT_AW9D_MAX,
+       ALC882_FIXUP_LENOVO_Y530,
+       ALC882_FIXUP_PB_M5210,
+       ALC882_FIXUP_ACER_ASPIRE_7736,
+       ALC882_FIXUP_ASUS_W90V,
+       ALC889_FIXUP_VAIO_TT,
+       ALC888_FIXUP_EEE1601,
+       ALC882_FIXUP_EAPD,
+       ALC883_FIXUP_EAPD,
+       ALC883_FIXUP_ACER_EAPD,
+       ALC882_FIXUP_GPIO3,
+       ALC889_FIXUP_COEF,
+       ALC882_FIXUP_ASUS_W2JC,
+       ALC882_FIXUP_ACER_ASPIRE_4930G,
+       ALC882_FIXUP_ACER_ASPIRE_8930G,
+       ALC882_FIXUP_ASPIRE_8930G_VERBS,
+       ALC885_FIXUP_MACPRO_GPIO,
 };
 
+static void alc889_fixup_coef(struct hda_codec *codec,
+                             const struct alc_fixup *fix, int action)
+{
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       alc889_coef_init(codec);
+}
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
+{
+       unsigned int gpiostate, gpiomask, gpiodir;
+
+       gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
+                                      AC_VERB_GET_GPIO_DATA, 0);
+
+       if (!muted)
+               gpiostate |= (1 << pin);
+       else
+               gpiostate &= ~(1 << pin);
+
+       gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
+                                     AC_VERB_GET_GPIO_MASK, 0);
+       gpiomask |= (1 << pin);
+
+       gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
+                                    AC_VERB_GET_GPIO_DIRECTION, 0);
+       gpiodir |= (1 << pin);
+
+
+       snd_hda_codec_write(codec, codec->afg, 0,
+                           AC_VERB_SET_GPIO_MASK, gpiomask);
+       snd_hda_codec_write(codec, codec->afg, 0,
+                           AC_VERB_SET_GPIO_DIRECTION, gpiodir);
+
+       msleep(1);
+
+       snd_hda_codec_write(codec, codec->afg, 0,
+                           AC_VERB_SET_GPIO_DATA, gpiostate);
+}
+
+/* set up GPIO at initialization */
+static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
+                                    const struct alc_fixup *fix, int action)
+{
+       if (action != ALC_FIXUP_ACT_INIT)
+               return;
+       alc882_gpio_mute(codec, 0, 0);
+       alc882_gpio_mute(codec, 1, 0);
+}
+
 static const struct alc_fixup alc882_fixups[] = {
-       [PINFIX_ABIT_AW9D_MAX] = {
+       [ALC882_FIXUP_ABIT_AW9D_MAX] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x15, 0x01080104 }, /* side */
@@ -4213,7 +4443,7 @@ static const struct alc_fixup alc882_fixups[] = {
                        { }
                }
        },
-       [PINFIX_LENOVO_Y530] = {
+       [ALC882_FIXUP_LENOVO_Y530] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x15, 0x99130112 }, /* rear int speakers */
@@ -4221,32 +4451,180 @@ static const struct alc_fixup alc882_fixups[] = {
                        { }
                }
        },
-       [PINFIX_PB_M5210] = {
+       [ALC882_FIXUP_PB_M5210] = {
                .type = ALC_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
                        { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
                        {}
                }
        },
-       [PINFIX_ACER_ASPIRE_7736] = {
+       [ALC882_FIXUP_ACER_ASPIRE_7736] = {
                .type = ALC_FIXUP_SKU,
                .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
-       [PINFIX_ASUS_W90V] = {
+       [ALC882_FIXUP_ASUS_W90V] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x16, 0x99130110 }, /* fix sequence for CLFE */
                        { }
                }
        },
+       [ALC889_FIXUP_VAIO_TT] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x90170111 }, /* hidden surround speaker */
+                       { }
+               }
+       },
+       [ALC888_FIXUP_EEE1601] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
+                       { 0x20, AC_VERB_SET_PROC_COEF,  0x0838 },
+                       { }
+               }
+       },
+       [ALC882_FIXUP_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* change to EAPD mode */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
+                       { }
+               }
+       },
+       [ALC883_FIXUP_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* change to EAPD mode */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
+                       { }
+               }
+       },
+       [ALC883_FIXUP_ACER_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* eanable EAPD on Acer laptops */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+                       { }
+               }
+       },
+       [ALC882_FIXUP_GPIO3] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = alc_gpio3_init_verbs,
+       },
+       [ALC882_FIXUP_ASUS_W2JC] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = alc_gpio1_init_verbs,
+               .chained = true,
+               .chain_id = ALC882_FIXUP_EAPD,
+       },
+       [ALC889_FIXUP_COEF] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc889_fixup_coef,
+       },
+       [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x16, 0x99130111 }, /* CLFE speaker */
+                       { 0x17, 0x99130112 }, /* surround speaker */
+                       { }
+               }
+       },
+       [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x16, 0x99130111 }, /* CLFE speaker */
+                       { 0x1b, 0x99130112 }, /* surround speaker */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
+       },
+       [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
+               /* additional init verbs for Acer Aspire 8930G */
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Enable all DACs */
+                       /* DAC DISABLE/MUTE 1? */
+                       /*  setting bits 1-5 disables DAC nids 0x02-0x06
+                        *  apparently. Init=0x38 */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
+                       /* DAC DISABLE/MUTE 2? */
+                       /*  some bit here disables the other DACs.
+                        *  Init=0x4900 */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
+                       /* DMIC fix
+                        * This laptop has a stereo digital microphone.
+                        * The mics are only 1cm apart which makes the stereo
+                        * useless. However, either the mic or the ALC889
+                        * makes the signal become a difference/sum signal
+                        * instead of standard stereo, which is annoying.
+                        * So instead we flip this bit which makes the
+                        * codec replicate the sum signal to both channels,
+                        * turning it into a normal mono mic.
+                        */
+                       /* DMIC_CONTROL? Init value = 0x0001 */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+                       { }
+               }
+       },
+       [ALC885_FIXUP_MACPRO_GPIO] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc885_fixup_macpro_gpio,
+       },
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
-       SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
-       SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", PINFIX_ASUS_W90V),
-       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),
+       SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
+       SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
+       SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
+       SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
+       SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
+       SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
+       SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
+                     ALC882_FIXUP_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
+                     ALC882_FIXUP_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
+                     ALC882_FIXUP_ACER_ASPIRE_8930G),
+       SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
+                     ALC882_FIXUP_ACER_ASPIRE_8930G),
+       SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
+                     ALC882_FIXUP_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
+                     ALC882_FIXUP_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
+                     ALC882_FIXUP_ACER_ASPIRE_4930G),
+       SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
+       SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
+       SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
+       SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
+       SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
+       SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
+
+       /* All Apple entries are in codec SSIDs */
+       SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
+
+       SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
+       SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+       SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
+       SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
        {}
 };
 
@@ -4295,8 +4673,7 @@ static int patch_alc882(struct hda_codec *codec)
                goto error;
 
        board_config = alc_board_config(codec, ALC882_MODEL_LAST,
-                                       alc882_models, alc882_cfg_tbl);
-
+                                       alc882_models, NULL);
        if (board_config < 0)
                board_config = alc_board_codec_sid_config(codec,
                        ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
@@ -4319,14 +4696,6 @@ static int patch_alc882(struct hda_codec *codec)
                err = alc882_parse_auto_config(codec);
                if (err < 0)
                        goto error;
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-               else if (!err) {
-                       printk(KERN_INFO
-                              "hda_codec: Cannot set up configuration "
-                              "from BIOS.  Using base mode...\n");
-                       board_config = ALC882_3ST_DIG;
-               }
-#endif
        }
 
        if (board_config != ALC_MODEL_AUTO)
@@ -4384,12 +4753,17 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
  * Pin config fixes
  */
 enum {
-       PINFIX_FSC_H270,
-       PINFIX_HP_Z200,
+       ALC262_FIXUP_FSC_H270,
+       ALC262_FIXUP_HP_Z200,
+       ALC262_FIXUP_TYAN,
+       ALC262_FIXUP_TOSHIBA_RX1,
+       ALC262_FIXUP_LENOVO_3000,
+       ALC262_FIXUP_BENQ,
+       ALC262_FIXUP_BENQ_T31,
 };
 
 static const struct alc_fixup alc262_fixups[] = {
-       [PINFIX_FSC_H270] = {
+       [ALC262_FIXUP_FSC_H270] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x14, 0x99130110 }, /* speaker */
@@ -4398,18 +4772,68 @@ static const struct alc_fixup alc262_fixups[] = {
                        { }
                }
        },
-       [PINFIX_HP_Z200] = {
+       [ALC262_FIXUP_HP_Z200] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x16, 0x99130120 }, /* internal speaker */
                        { }
                }
        },
+       [ALC262_FIXUP_TYAN] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x14, 0x1993e1f0 }, /* int AUX */
+                       { }
+               }
+       },
+       [ALC262_FIXUP_TOSHIBA_RX1] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x14, 0x90170110 }, /* speaker */
+                       { 0x15, 0x0421101f }, /* HP */
+                       { 0x1a, 0x40f000f0 }, /* N/A */
+                       { 0x1b, 0x40f000f0 }, /* N/A */
+                       { 0x1e, 0x40f000f0 }, /* N/A */
+               }
+       },
+       [ALC262_FIXUP_LENOVO_3000] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC262_FIXUP_BENQ,
+       },
+       [ALC262_FIXUP_BENQ] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
+                       {}
+               }
+       },
+       [ALC262_FIXUP_BENQ_T31] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+                       {}
+               }
+       },
 };
 
 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),
+       SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
+       SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
+       SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
+       SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
+       SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
+                     ALC262_FIXUP_TOSHIBA_RX1),
+       SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
+       SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
+       SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
+       SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
        {}
 };
 
@@ -4420,14 +4844,9 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
 
 /*
  */
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc262_quirks.c"
-#endif
-
 static int patch_alc262(struct hda_codec *codec)
 {
        struct alc_spec *spec;
-       int board_config;
        int err;
 
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -4454,37 +4873,13 @@ static int patch_alc262(struct hda_codec *codec)
 
        alc_fix_pll_init(codec, 0x20, 0x0a, 10);
 
-       board_config = alc_board_config(codec, ALC262_MODEL_LAST,
-                                       alc262_models, alc262_cfg_tbl);
-
-       if (board_config < 0) {
-               printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
-                      codec->chip_name);
-               board_config = ALC_MODEL_AUTO;
-       }
-
-       if (board_config == ALC_MODEL_AUTO) {
-               alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
-               alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
-       }
-
-       if (board_config == ALC_MODEL_AUTO) {
-               /* automatic parse from the BIOS config */
-               err = alc262_parse_auto_config(codec);
-               if (err < 0)
-                       goto error;
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-               else if (!err) {
-                       printk(KERN_INFO
-                              "hda_codec: Cannot set up configuration "
-                              "from BIOS.  Using base mode...\n");
-                       board_config = ALC262_BASIC;
-               }
-#endif
-       }
+       alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
+       alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
-       if (board_config != ALC_MODEL_AUTO)
-               setup_preset(codec, &alc262_presets[board_config]);
+       /* automatic parse from the BIOS config */
+       err = alc262_parse_auto_config(codec);
+       if (err < 0)
+               goto error;
 
        if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
@@ -4507,8 +4902,7 @@ static int patch_alc262(struct hda_codec *codec)
        spec->vmaster_nid = 0x0c;
 
        codec->patch_ops = alc_patch_ops;
-       if (board_config == ALC_MODEL_AUTO)
-               spec->init_hook = alc_auto_init_std;
+       spec->init_hook = alc_auto_init_std;
        spec->shutup = alc_eapd_shutup;
 
        alc_init_jacks(codec);