Merge branch 'fix/acer-alc889-fix' into fix/hda
authorTakashi Iwai <tiwai@suse.de>
Mon, 13 Feb 2012 14:34:31 +0000 (15:34 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 13 Feb 2012 14:34:31 +0000 (15:34 +0100)
Conflicts:
sound/pci/hda/patch_realtek.c

Merged back the fix for Acer Aspire 6935 with ALC889 codec.
The fix commit was based on 3.2 kernel so that it can be applied to
stable kernel cleanly.

1  2 
sound/pci/hda/patch_realtek.c

index 9350f3c3bdf89445ece8a6f88a439703aa5a48cf,c4bde7108328a3fabb402e4251d7f090b50051e0..1358987c49d8ccf12367687608a63051a8bdc50e
@@@ -33,7 -33,6 +33,7 @@@
  #include "hda_codec.h"
  #include "hda_local.h"
  #include "hda_beep.h"
 +#include "hda_jack.h"
  
  /* unsol event tags */
  #define ALC_FRONT_EVENT               0x01
@@@ -177,7 -176,6 +177,7 @@@ struct alc_spec 
        unsigned int detect_lo:1;       /* Line-out detection enabled */
        unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
        unsigned int automute_lo_possible:1;      /* there are line outs and HP */
 +      unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
  
        /* other flags */
        unsigned int no_analog :1; /* digital I/O only */
        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;
@@@ -286,8 -283,6 +286,8 @@@ static inline hda_nid_t get_capsrc(stru
                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)
                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];
@@@ -467,6 -449,46 +467,6 @@@ static void alc_fix_pll_init(struct hda
        alc_fix_pll(codec);
  }
  
 -/*
 - * Jack-reporting via input-jack layer
 - */
 -
 -/* initialization of jacks; currently checks only a few known pins */
 -static int alc_init_jacks(struct hda_codec *codec)
 -{
 -#ifdef CONFIG_SND_HDA_INPUT_JACK
 -      struct alc_spec *spec = codec->spec;
 -      int err;
 -      unsigned int hp_nid = spec->autocfg.hp_pins[0];
 -      unsigned int mic_nid = spec->ext_mic_pin;
 -      unsigned int dock_nid = spec->dock_mic_pin;
 -
 -      if (hp_nid) {
 -              err = snd_hda_input_jack_add(codec, hp_nid,
 -                                           SND_JACK_HEADPHONE, NULL);
 -              if (err < 0)
 -                      return err;
 -              snd_hda_input_jack_report(codec, hp_nid);
 -      }
 -
 -      if (mic_nid) {
 -              err = snd_hda_input_jack_add(codec, mic_nid,
 -                                           SND_JACK_MICROPHONE, NULL);
 -              if (err < 0)
 -                      return err;
 -              snd_hda_input_jack_report(codec, mic_nid);
 -      }
 -      if (dock_nid) {
 -              err = snd_hda_input_jack_add(codec, dock_nid,
 -                                           SND_JACK_MICROPHONE, NULL);
 -              if (err < 0)
 -                      return err;
 -              snd_hda_input_jack_report(codec, dock_nid);
 -      }
 -#endif /* CONFIG_SND_HDA_INPUT_JACK */
 -      return 0;
 -}
 -
  /*
   * Jack detections for HP auto-mute and mic-switch
   */
@@@ -480,6 -502,7 +480,6 @@@ static bool detect_jacks(struct hda_cod
                hda_nid_t nid = pins[i];
                if (!nid)
                        break;
 -              snd_hda_input_jack_report(codec, nid);
                present |= snd_hda_jack_detect(codec, nid);
        }
        return present;
@@@ -496,24 -519,13 +496,24 @@@ static void do_automute(struct hda_code
  
        for (i = 0; i < num_pins; i++) {
                hda_nid_t nid = pins[i];
 +              unsigned int val;
                if (!nid)
                        break;
                switch (spec->automute_mode) {
                case ALC_AUTOMUTE_PIN:
 +                      /* don't reset VREF value in case it's controlling
 +                       * the amp (see alc861_fixup_asus_amp_vref_0f())
 +                       */
 +                      if (spec->keep_vref_in_automute) {
 +                              val = snd_hda_codec_read(codec, nid, 0,
 +                                      AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 +                              val &= ~PIN_HP;
 +                      } else
 +                              val = 0;
 +                      val |= pin_bits;
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_PIN_WIDGET_CONTROL,
 -                                          pin_bits);
 +                                          val);
                        break;
                case ALC_AUTOMUTE_AMP:
                        snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@@ -542,8 -554,7 +542,8 @@@ static void update_outputs(struct hda_c
         * 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)
@@@ -630,12 -641,20 +630,12 @@@ static void alc_mic_automute(struct hda
                alc_mux_select(codec, 0, spec->dock_mic_idx, false);
        else
                alc_mux_select(codec, 0, spec->int_mic_idx, false);
 -
 -      snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
 -      if (spec->dock_mic_idx >= 0)
 -              snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
  }
  
 -/* unsolicited event for HP jack sensing */
 -static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 +/* handle the specified unsol action (ALC_XXX_EVENT) */
 +static void alc_exec_unsol_event(struct hda_codec *codec, int action)
  {
 -      if (codec->vendor_id == 0x10ec0880)
 -              res >>= 28;
 -      else
 -              res >>= 26;
 -      switch (res) {
 +      switch (action) {
        case ALC_HP_EVENT:
                alc_hp_automute(codec);
                break;
                alc_mic_automute(codec);
                break;
        }
 +      snd_hda_jack_report_sync(codec);
 +}
 +
 +/* unsolicited event for HP jack sensing */
 +static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 +{
 +      if (codec->vendor_id == 0x10ec0880)
 +              res >>= 28;
 +      else
 +              res >>= 26;
 +      res = snd_hda_jack_get_action(codec, res);
 +      alc_exec_unsol_event(codec, res);
  }
  
  /* call init functions of standard auto-mute helpers */
@@@ -947,7 -954,9 +947,7 @@@ static void alc_init_automute(struct hd
                        continue;
                snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
                            nid);
 -              snd_hda_codec_write_cache(codec, nid, 0,
 -                                AC_VERB_SET_UNSOLICITED_ENABLE,
 -                                AC_USRSP_EN | ALC_HP_EVENT);
 +              snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT);
                spec->detect_hp = 1;
        }
  
                                        continue;
                                snd_printdd("realtek: Enable Line-Out "
                                            "auto-muting on NID 0x%x\n", nid);
 -                              snd_hda_codec_write_cache(codec, nid, 0,
 -                                              AC_VERB_SET_UNSOLICITED_ENABLE,
 -                                              AC_USRSP_EN | ALC_FRONT_EVENT);
 +                              snd_hda_jack_detect_enable(codec, nid,
 +                                                         ALC_FRONT_EVENT);
                                spec->detect_lo = 1;
                }
                spec->automute_lo_possible = spec->detect_hp;
@@@ -1099,10 -1109,13 +1099,10 @@@ static bool alc_auto_mic_check_imux(str
                return false; /* no corresponding imux */
        }
  
 -      snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
 -                                AC_VERB_SET_UNSOLICITED_ENABLE,
 -                                AC_USRSP_EN | ALC_MIC_EVENT);
 +      snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT);
        if (spec->dock_mic_pin)
 -              snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
 -                                AC_VERB_SET_UNSOLICITED_ENABLE,
 -                                AC_USRSP_EN | ALC_MIC_EVENT);
 +              snd_hda_jack_detect_enable(codec, spec->dock_mic_pin,
 +                                         ALC_MIC_EVENT);
  
        spec->auto_mic_valid_imux = 1;
        spec->auto_mic = 1;
@@@ -1120,9 -1133,6 +1120,9 @@@ static void alc_init_auto_mic(struct hd
        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;
@@@ -1514,7 -1524,6 +1514,7 @@@ static void alc_pick_fixup(struct hda_c
                           const struct alc_fixup *fixlist)
  {
        struct alc_spec *spec = codec->spec;
 +      const struct snd_pci_quirk *q;
        int id = -1;
        const char *name = NULL;
  
                }
        }
        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) {
@@@ -1855,8 -1851,6 +1855,8 @@@ static const char * const alc_slave_vol
        "Speaker Playback Volume",
        "Mono Playback Volume",
        "Line-Out Playback Volume",
 +      "CLFE Playback Volume",
 +      "Bass Speaker Playback Volume",
        "PCM Playback Volume",
        NULL,
  };
@@@ -1872,8 -1866,6 +1872,8 @@@ static const char * const alc_slave_sws
        "Mono Playback Switch",
        "IEC958 Playback Switch",
        "Line-Out Playback Switch",
 +      "CLFE Playback Switch",
 +      "Bass Speaker Playback Switch",
        "PCM Playback Switch",
        NULL,
  };
@@@ -1902,7 -1894,7 +1902,7 @@@ static const struct snd_kcontrol_new al
  };
  #endif
  
 -static int alc_build_controls(struct hda_codec *codec)
 +static int __alc_build_controls(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
        struct snd_kcontrol *kctl = NULL;
        return 0;
  }
  
 +static int alc_build_controls(struct hda_codec *codec)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      int err = __alc_build_controls(codec);
 +      if (err < 0)
 +              return err;
 +      return snd_hda_jack_add_kctls(codec, &spec->autocfg);
 +}
 +
  
  /*
   * Common callbacks
@@@ -2084,8 -2067,6 +2084,8 @@@ static int alc_init(struct hda_codec *c
  
        alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
  
 +      snd_hda_jack_report_sync(codec);
 +
        hda_call_check_power_status(codec, 0x01);
        return 0;
  }
@@@ -2322,7 -2303,7 +2322,7 @@@ static int alc_build_pcms(struct hda_co
                 "%s Analog", codec->chip_name);
        info->name = spec->stream_name_analog;
  
 -      if (spec->multiout.dac_nids > 0) {
 +      if (spec->multiout.num_dacs > 0) {
                p = spec->stream_analog_playback;
                if (!p)
                        p = &alc_pcm_analog_playback;
@@@ -2469,6 -2450,7 +2469,6 @@@ static void alc_free(struct hda_codec *
                return;
  
        alc_shutup(codec);
 -      snd_hda_input_jack_free(codec);
        alc_free_kctls(codec);
        alc_free_bind_ctls(codec);
        kfree(spec);
@@@ -2703,9 -2685,6 +2703,9 @@@ static int alc_auto_fill_adc_caps(struc
        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;
@@@ -2768,8 -2747,6 +2768,8 @@@ static int alc_auto_create_input_ctls(s
                        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
        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)
  {
@@@ -2975,23 -2919,6 +2975,23 @@@ static hda_nid_t alc_auto_look_for_dac(
        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);
@@@ -3022,17 -2949,13 +3022,17 @@@ static int alc_auto_fill_extra_dacs(str
  }
  
  static int alc_auto_fill_multi_ios(struct hda_codec *codec,
 -                                 unsigned int location);
 +                                 unsigned int location, int offset);
 +static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
 +                                        hda_nid_t pin, hda_nid_t dac);
  
  /* 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;
  
  
        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;
                }
        }
  
 +      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;
 +              }
 +      }
 +
 +      if (cfg->line_out_pins[0])
 +              spec->vmaster_nid =
 +                      alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
 +                                               spec->multiout.dac_nids[0]);
        return 0;
  }
  
@@@ -3174,15 -3081,8 +3174,15 @@@ static int alc_auto_add_vol_ctl(struct 
                                 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
@@@ -3214,14 -3114,8 +3214,14 @@@ static int alc_auto_add_sw_ctl(struct h
        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)
@@@ -3257,7 -3151,7 +3257,7 @@@ static int alc_auto_create_multi_out_ct
        int i, err, noutputs;
  
        noutputs = cfg->line_outs;
 -      if (spec->multi_ios > 0)
 +      if (spec->multi_ios > 0 && cfg->line_outs < 3)
                noutputs += spec->multi_ios;
  
        for (i = 0; i < noutputs; i++) {
@@@ -3547,19 -3441,17 +3547,19 @@@ static void alc_auto_init_extra_out(str
   * 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;
                        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;
                        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;
        }
@@@ -3814,8 -3700,6 +3814,8 @@@ static int alc_auto_add_mic_boost(struc
                        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
@@@ -4018,9 -3902,6 +4018,9 @@@ static int alc_parse_auto_config(struc
        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);
@@@ -4069,37 -3950,6 +4069,37 @@@ static const struct hda_amp_list alc880
  };
  #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
   */
@@@ -4145,11 -3995,6 +4145,11 @@@ static int patch_alc880(struct hda_code
                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);
  #endif
        }
  
 -      if (board_config != ALC_MODEL_AUTO)
 +      if (board_config != ALC_MODEL_AUTO) {
 +              spec->vmaster_nid = 0x0c;
                setup_preset(codec, &alc880_presets[board_config]);
 +      }
  
        if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
        }
  
 -      spec->vmaster_nid = 0x0c;
 +      alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC_MODEL_AUTO)
                spec->init_hook = alc_auto_init_std;
 +      else
 +              codec->patch_ops.build_controls = __alc_build_controls;
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc880_loopbacks;
@@@ -4296,10 -4137,8 +4296,10 @@@ static int patch_alc260(struct hda_code
  #endif
        }
  
 -      if (board_config != ALC_MODEL_AUTO)
 +      if (board_config != ALC_MODEL_AUTO) {
                setup_preset(codec, &alc260_presets[board_config]);
 +              spec->vmaster_nid = 0x08;
 +      }
  
        if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
  
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
 -      spec->vmaster_nid = 0x08;
 -
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC_MODEL_AUTO)
                spec->init_hook = alc_auto_init_std;
 +      else
 +              codec->patch_ops.build_controls = __alc_build_controls;
        spec->shutup = alc_eapd_shutup;
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
   * 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,
+       ALC889_FIXUP_DAC_ROUTE,
  };
  
 +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);
 +}
 +
+ /* Fix the connection of some pins for ALC889:
+  * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
+  * work correctly (bko#42740)
+  */
+ static void alc889_fixup_dac_route(struct hda_codec *codec,
+                                  const struct alc_fixup *fix, int action)
+ {
+       if (action == ALC_FIXUP_ACT_PRE_PROBE) {
+               hda_nid_t conn1[2] = { 0x0c, 0x0d };
+               hda_nid_t conn2[2] = { 0x0e, 0x0f };
+               snd_hda_override_conn_list(codec, 0x14, 2, conn1);
+               snd_hda_override_conn_list(codec, 0x15, 2, conn1);
+               snd_hda_override_conn_list(codec, 0x18, 2, conn2);
+               snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
+       }
+ }
  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 */
                        { }
                }
        },
 -      [PINFIX_LENOVO_Y530] = {
 +      [ALC882_FIXUP_LENOVO_Y530] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x15, 0x99130112 }, /* rear int speakers */
                        { }
                }
        },
 -      [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,
 +      },
+       [ALC889_FIXUP_DAC_ROUTE] = {
+               .type = ALC_FIXUP_FUNC,
+               .v.func = alc889_fixup_dac_route,
+       },
  };
  
  static const struct snd_pci_quirk alc882_fixup_tbl[] = {
 -      SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
 +      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, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
 -      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, 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),
        {}
  };
  
@@@ -4667,7 -4318,8 +4690,7 @@@ static int patch_alc882(struct hda_code
                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);
                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)
 +      if (board_config != ALC_MODEL_AUTO) {
                setup_preset(codec, &alc882_presets[board_config]);
 +              spec->vmaster_nid = 0x0c;
 +      }
  
        if (!spec->no_analog && !spec->adc_nids) {
                alc_auto_fill_adc_caps(codec);
  
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
 -      spec->vmaster_nid = 0x0c;
 -
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC_MODEL_AUTO)
                spec->init_hook = alc_auto_init_std;
 +      else
 +              codec->patch_ops.build_controls = __alc_build_controls;
  
 -      alc_init_jacks(codec);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc882_loopbacks;
@@@ -4748,16 -4407,12 +4771,16 @@@ static int alc262_parse_auto_config(str
   * Pin config fixes
   */
  enum {
 -      PINFIX_FSC_H270,
 -      PINFIX_HP_Z200,
 +      ALC262_FIXUP_FSC_H270,
 +      ALC262_FIXUP_HP_Z200,
 +      ALC262_FIXUP_TYAN,
 +      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 */
                        { }
                }
        },
 -      [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_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(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),
        {}
  };
  
  
  /*
   */
 -#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);
  
        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);
  
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
 -      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);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc262_loopbacks;
@@@ -4991,10 -4641,14 +5014,10 @@@ static int patch_alc268(struct hda_code
        if (!spec->no_analog && !spec->cap_mixer)
                set_capture_mixer(codec);
  
 -      spec->vmaster_nid = 0x02;
 -
        codec->patch_ops = alc_patch_ops;
        spec->init_hook = alc_auto_init_std;
        spec->shutup = alc_eapd_shutup;
  
 -      alc_init_jacks(codec);
 -
        return 0;
  
   error:
@@@ -5336,7 -4990,7 +5359,7 @@@ static const struct alc_fixup alc269_fi
                        { }
                },
        },
 -      [ALC269_FIXUP_DMIC] = {
 +      [ALC269VB_FIXUP_DMIC] = {
                .type = ALC_FIXUP_PINS,
                .v.pins = (const struct alc_pincfg[]) {
                        { 0x12, 0x99a3092f }, /* int-mic */
@@@ -5380,6 -5034,7 +5403,6 @@@ static const struct snd_pci_quirk alc26
        SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
                      ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
 -      SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
        SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
@@@ -5542,6 -5197,8 +5565,6 @@@ static int patch_alc269(struct hda_code
  
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
 -      spec->vmaster_nid = 0x02;
 -
        codec->patch_ops = alc_patch_ops;
  #ifdef CONFIG_PM
        codec->patch_ops.resume = alc269_resume;
        spec->init_hook = alc_auto_init_std;
        spec->shutup = alc269_shutup;
  
 -      alc_init_jacks(codec);
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc269_loopbacks;
@@@ -5588,28 -5246,8 +5611,28 @@@ static const struct hda_amp_list alc861
  /* Pin config fixes */
  enum {
        PINFIX_FSC_AMILO_PI1505,
 +      PINFIX_ASUS_A6RP,
  };
  
 +/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
 +static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
 +                      const struct alc_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      unsigned int val;
 +
 +      if (action != ALC_FIXUP_ACT_INIT)
 +              return;
 +      val = snd_hda_codec_read(codec, 0x0f, 0,
 +                               AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 +      if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
 +              val |= AC_PINCTL_IN_EN;
 +      val |= AC_PINCTL_VREF_50;
 +      snd_hda_codec_write(codec, 0x0f, 0,
 +                          AC_VERB_SET_PIN_WIDGET_CONTROL, val);
 +      spec->keep_vref_in_automute = 1;
 +}
 +
  static const struct alc_fixup alc861_fixups[] = {
        [PINFIX_FSC_AMILO_PI1505] = {
                .type = ALC_FIXUP_PINS,
                        { }
                }
        },
 +      [PINFIX_ASUS_A6RP] = {
 +              .type = ALC_FIXUP_FUNC,
 +              .v.func = alc861_fixup_asus_amp_vref_0f,
 +      },
  };
  
  static const struct snd_pci_quirk alc861_fixup_tbl[] = {
 +      SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
 +      SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),   
 +      SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
        SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
        {}
  };
@@@ -5672,6 -5303,8 +5695,6 @@@ static int patch_alc861(struct hda_code
                set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
        }
  
 -      spec->vmaster_nid = 0x03;
 -
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        codec->patch_ops = alc_patch_ops;
@@@ -5796,6 -5429,8 +5819,6 @@@ static int patch_alc861vd(struct hda_co
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
        }
  
 -      spec->vmaster_nid = 0x02;
 -
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        codec->patch_ops = alc_patch_ops;
@@@ -6178,6 -5813,7 +6201,6 @@@ static int patch_alc662(struct hda_code
                        break;
                }
        }
 -      spec->vmaster_nid = 0x02;
  
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
  
        spec->init_hook = alc_auto_init_std;
        spec->shutup = alc_eapd_shutup;
  
 -      alc_init_jacks(codec);
 -
  #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc662_loopbacks;
@@@ -6231,6 -5869,8 +6254,6 @@@ static int patch_alc680(struct hda_code
        if (!spec->no_analog && !spec->cap_mixer)
                set_capture_mixer(codec);
  
 -      spec->vmaster_nid = 0x02;
 -
        codec->patch_ops = alc_patch_ops;
        spec->init_hook = alc_auto_init_std;