Merge branch 'for-linus' into topic/virmidi
authorTakashi Iwai <tiwai@suse.de>
Sun, 29 Jul 2018 20:38:54 +0000 (22:38 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sun, 29 Jul 2018 20:39:29 +0000 (22:39 +0200)
Pull the latest ALSA sequencer fixes for the further development of
virmidi.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
1  2 
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c

@@@ -37,6 -37,8 +37,6 @@@
  struct conexant_spec {
        struct hda_gen_spec gen;
  
 -      unsigned int beep_amp;
 -
        /* extra EAPD pins */
        unsigned int num_eapds;
        hda_nid_t eapds[4];
  
  
  #ifdef CONFIG_SND_HDA_INPUT_BEEP
 -static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
 -                              int idx, int dir)
 -{
 -      spec->gen.beep_nid = nid;
 -      spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
 -}
 -/* additional beep mixers; the actual parameters are overwritten at build */
 +/* additional beep mixers; private_value will be overwritten */
  static const struct snd_kcontrol_new cxt_beep_mixer[] = {
        HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
        HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
 -      { } /* end */
  };
  
 -/* create beep controls if needed */
 -static int add_beep_ctls(struct hda_codec *codec)
 +static int set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
 +                      int idx, int dir)
  {
 -      struct conexant_spec *spec = codec->spec;
 -      int err;
 +      struct snd_kcontrol_new *knew;
 +      unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
 +      int i;
  
 -      if (spec->beep_amp) {
 -              const struct snd_kcontrol_new *knew;
 -              for (knew = cxt_beep_mixer; knew->name; knew++) {
 -                      struct snd_kcontrol *kctl;
 -                      kctl = snd_ctl_new1(knew, codec);
 -                      if (!kctl)
 -                              return -ENOMEM;
 -                      kctl->private_value = spec->beep_amp;
 -                      err = snd_hda_ctl_add(codec, 0, kctl);
 -                      if (err < 0)
 -                              return err;
 -              }
 +      spec->gen.beep_nid = nid;
 +      for (i = 0; i < ARRAY_SIZE(cxt_beep_mixer); i++) {
 +              knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
 +                                          &cxt_beep_mixer[i]);
 +              if (!knew)
 +                      return -ENOMEM;
 +              knew->private_value = beep_amp;
        }
        return 0;
  }
 -#else
 -#define set_beep_amp(spec, nid, idx, dir) /* NOP */
 -#define add_beep_ctls(codec)  0
 -#endif
 -
 -/*
 - * Automatic parser for CX20641 & co
 - */
  
 -#ifdef CONFIG_SND_HDA_INPUT_BEEP
 -static void cx_auto_parse_beep(struct hda_codec *codec)
 +static int cx_auto_parse_beep(struct hda_codec *codec)
  {
        struct conexant_spec *spec = codec->spec;
        hda_nid_t nid;
  
        for_each_hda_codec_node(nid, codec)
 -              if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
 -                      set_beep_amp(spec, nid, 0, HDA_OUTPUT);
 -                      break;
 -              }
 +              if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
 +                      return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
 +      return 0;
  }
  #else
 -#define cx_auto_parse_beep(codec)
 +#define cx_auto_parse_beep(codec)     0
  #endif
  
 +/*
 + * Automatic parser for CX20641 & co
 + */
 +
  /* parse EAPDs */
  static void cx_auto_parse_eapd(struct hda_codec *codec)
  {
@@@ -160,6 -179,21 +160,6 @@@ static void cx_auto_vmaster_hook_mute_l
                            enabled ? 0x00 : 0x02);
  }
  
 -static int cx_auto_build_controls(struct hda_codec *codec)
 -{
 -      int err;
 -
 -      err = snd_hda_gen_build_controls(codec);
 -      if (err < 0)
 -              return err;
 -
 -      err = add_beep_ctls(codec);
 -      if (err < 0)
 -              return err;
 -
 -      return 0;
 -}
 -
  static int cx_auto_init(struct hda_codec *codec)
  {
        struct conexant_spec *spec = codec->spec;
@@@ -177,6 -211,7 +177,7 @@@ static void cx_auto_reboot_notify(struc
        struct conexant_spec *spec = codec->spec;
  
        switch (codec->core.vendor_id) {
+       case 0x14f12008: /* CX8200 */
        case 0x14f150f2: /* CX20722 */
        case 0x14f150f4: /* CX20724 */
                break;
                return;
        }
  
-       /* Turn the CX20722 codec into D3 to avoid spurious noises
+       /* Turn the problematic codec into D3 to avoid spurious noises
           from the internal speaker during (and after) reboot */
        cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
  
        snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
        snd_hda_codec_write(codec, codec->core.afg, 0,
                            AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+       msleep(10);
  }
  
  static void cx_auto_free(struct hda_codec *codec)
  }
  
  static const struct hda_codec_ops cx_auto_patch_ops = {
 -      .build_controls = cx_auto_build_controls,
 +      .build_controls = snd_hda_gen_build_controls,
        .build_pcms = snd_hda_gen_build_pcms,
        .init = cx_auto_init,
        .reboot_notify = cx_auto_reboot_notify,
@@@ -309,7 -345,6 +311,7 @@@ static void cxt_fixup_headphone_mic(str
                snd_hdac_regmap_add_vendor_verb(&codec->core, 0x410);
                break;
        case HDA_FIXUP_ACT_PROBE:
 +              WARN_ON(spec->gen.cap_sync_hook);
                spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
                spec->gen.automute_hook = cxt_update_headset_mode;
                break;
@@@ -341,7 -376,7 +343,7 @@@ static void cxt_fixup_headset_mic(struc
   * control. */
  
  #define update_mic_pin(codec, nid, val)                                       \
 -      snd_hda_codec_update_cache(codec, nid, 0,                       \
 +      snd_hda_codec_write_cache(codec, nid, 0,                        \
                                   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
  
  static const struct hda_input_mux olpc_xo_dc_bias = {
@@@ -662,12 -697,16 +664,12 @@@ static void cxt_fixup_gpio_mute_hook(vo
  }
  
  /* turn on/off mic-mute LED via GPIO per capture hook */
 -static void cxt_fixup_gpio_mic_mute_hook(struct hda_codec *codec,
 -                                       struct snd_kcontrol *kcontrol,
 -                                       struct snd_ctl_elem_value *ucontrol)
 +static void cxt_gpio_micmute_update(struct hda_codec *codec)
  {
        struct conexant_spec *spec = codec->spec;
  
 -      if (ucontrol)
 -              cxt_update_gpio_led(codec, spec->gpio_mic_led_mask,
 -                                  ucontrol->value.integer.value[0] ||
 -                                  ucontrol->value.integer.value[1]);
 +      cxt_update_gpio_led(codec, spec->gpio_mic_led_mask,
 +                          spec->gen.micmute_led.led_value);
  }
  
  
@@@ -684,11 -723,11 +686,11 @@@ static void cxt_fixup_mute_led_gpio(str
  
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook;
 -              spec->gen.cap_sync_hook = cxt_fixup_gpio_mic_mute_hook;
                spec->gpio_led = 0;
                spec->mute_led_polarity = 0;
                spec->gpio_mute_led_mask = 0x01;
                spec->gpio_mic_led_mask = 0x02;
 +              snd_hda_gen_add_micmute_led(codec, cxt_gpio_micmute_update);
        }
        snd_hda_add_verbs(codec, gpio_init);
        if (spec->gpio_led)
@@@ -1000,6 -1039,7 +1002,6 @@@ static int patch_conexant_auto(struct h
        codec->spec = spec;
        codec->patch_ops = cx_auto_patch_ops;
  
 -      cx_auto_parse_beep(codec);
        cx_auto_parse_eapd(codec);
        spec->gen.own_eapd_ctl = 1;
        if (spec->dynamic_eapd)
        if (err < 0)
                goto error;
  
 +      err = cx_auto_parse_beep(codec);
 +      if (err < 0)
 +              goto error;
 +
        /* Some laptops with Conexant chips show stalls in S3 resume,
         * which falls into the single-cmd mode.
         * Better to make reset, then.
  
  /* extra amp-initialization sequence types */
  enum {
 +      ALC_INIT_UNDEFINED,
        ALC_INIT_NONE,
        ALC_INIT_DEFAULT,
 -      ALC_INIT_GPIO1,
 -      ALC_INIT_GPIO2,
 -      ALC_INIT_GPIO3,
  };
  
  enum {
@@@ -83,20 -85,19 +83,20 @@@ struct alc_spec 
        struct hda_gen_spec gen; /* must be at head */
  
        /* codec parameterization */
 -      const struct snd_kcontrol_new *mixers[5];       /* mixer arrays */
 -      unsigned int num_mixers;
 -      unsigned int beep_amp;  /* beep amp value, set via set_beep_amp() */
 -
        struct alc_customize_define cdefine;
        unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
  
 +      /* GPIO bits */
 +      unsigned int gpio_mask;
 +      unsigned int gpio_dir;
 +      unsigned int gpio_data;
 +      bool gpio_write_delay;  /* add a delay before writing gpio_data */
 +
        /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
        int mute_led_polarity;
        hda_nid_t mute_led_nid;
        hda_nid_t cap_mute_led_nid;
  
 -      unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
        unsigned int gpio_mute_led_mask;
        unsigned int gpio_mic_led_mask;
  
@@@ -204,87 -205,41 +204,87 @@@ static void alc_process_coef_fw(struct 
  }
  
  /*
 - * Append the given mixer and verb elements for the later use
 - * The mixer array is referred in build_controls(), and init_verbs are
 - * called in init().
 + * GPIO setup tables, used in initialization
   */
 -static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
 +
 +/* Enable GPIO mask and set output */
 +static void alc_setup_gpio(struct hda_codec *codec, unsigned int mask)
 +{
 +      struct alc_spec *spec = codec->spec;
 +
 +      spec->gpio_mask |= mask;
 +      spec->gpio_dir |= mask;
 +      spec->gpio_data |= mask;
 +}
 +
 +static void alc_write_gpio_data(struct hda_codec *codec)
  {
 -      if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
 +      struct alc_spec *spec = codec->spec;
 +
 +      snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
 +                          spec->gpio_data);
 +}
 +
 +static void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask,
 +                               bool on)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      unsigned int oldval = spec->gpio_data;
 +
 +      if (on)
 +              spec->gpio_data |= mask;
 +      else
 +              spec->gpio_data &= ~mask;
 +      if (oldval != spec->gpio_data)
 +              alc_write_gpio_data(codec);
 +}
 +
 +static void alc_write_gpio(struct hda_codec *codec)
 +{
 +      struct alc_spec *spec = codec->spec;
 +
 +      if (!spec->gpio_mask)
                return;
 -      spec->mixers[spec->num_mixers++] = mix;
 +
 +      snd_hda_codec_write(codec, codec->core.afg, 0,
 +                          AC_VERB_SET_GPIO_MASK, spec->gpio_mask);
 +      snd_hda_codec_write(codec, codec->core.afg, 0,
 +                          AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir);
 +      if (spec->gpio_write_delay)
 +              msleep(1);
 +      alc_write_gpio_data(codec);
  }
  
 -/*
 - * GPIO setup tables, used in initialization
 - */
 -/* Enable GPIO mask and set output */
 -static const struct hda_verb alc_gpio1_init_verbs[] = {
 -      {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
 -      {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
 -      {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
 -      { }
 -};
 +static void alc_fixup_gpio(struct hda_codec *codec, int action,
 +                         unsigned int mask)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              alc_setup_gpio(codec, mask);
 +}
  
 -static const struct hda_verb alc_gpio2_init_verbs[] = {
 -      {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
 -      {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
 -      {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
 -      { }
 -};
 +static void alc_fixup_gpio1(struct hda_codec *codec,
 +                          const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_gpio(codec, action, 0x01);
 +}
  
 -static const struct hda_verb alc_gpio3_init_verbs[] = {
 -      {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
 -      {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
 -      {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
 -      { }
 -};
 +static void alc_fixup_gpio2(struct hda_codec *codec,
 +                          const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_gpio(codec, action, 0x02);
 +}
 +
 +static void alc_fixup_gpio3(struct hda_codec *codec,
 +                          const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_gpio(codec, action, 0x03);
 +}
 +
 +static void alc_fixup_gpio4(struct hda_codec *codec,
 +                          const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_gpio(codec, action, 0x04);
 +}
  
  /*
   * Fix hardware PLL issue
@@@ -492,8 -447,16 +492,8 @@@ static void alc_auto_init_amp(struct hd
  {
        alc_fill_eapd_coef(codec);
        alc_auto_setup_eapd(codec, true);
 +      alc_write_gpio(codec);
        switch (type) {
 -      case ALC_INIT_GPIO1:
 -              snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
 -              break;
 -      case ALC_INIT_GPIO2:
 -              snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
 -              break;
 -      case ALC_INIT_GPIO3:
 -              snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
 -              break;
        case ALC_INIT_DEFAULT:
                switch (codec->core.vendor_id) {
                case 0x10ec0260:
@@@ -693,22 -656,20 +693,22 @@@ do_sku
         * 7~6 : Reserved
        */
        tmp = (ass & 0x38) >> 3;        /* external Amp control */
 -      switch (tmp) {
 -      case 1:
 -              spec->init_amp = ALC_INIT_GPIO1;
 -              break;
 -      case 3:
 -              spec->init_amp = ALC_INIT_GPIO2;
 -              break;
 -      case 7:
 -              spec->init_amp = ALC_INIT_GPIO3;
 -              break;
 -      case 5:
 -      default:
 -              spec->init_amp = ALC_INIT_DEFAULT;
 -              break;
 +      if (spec->init_amp == ALC_INIT_UNDEFINED) {
 +              switch (tmp) {
 +              case 1:
 +                      alc_setup_gpio(codec, 0x01);
 +                      break;
 +              case 3:
 +                      alc_setup_gpio(codec, 0x02);
 +                      break;
 +              case 7:
 +                      alc_setup_gpio(codec, 0x03);
 +                      break;
 +              case 5:
 +              default:
 +                      spec->init_amp = ALC_INIT_DEFAULT;
 +                      break;
 +              }
        }
  
        /* is laptop or Desktop and enable the function "Mute internal speaker
@@@ -761,14 -722,47 +761,14 @@@ static void alc_fixup_inv_dmic(struct h
  }
  
  
 -#ifdef CONFIG_SND_HDA_INPUT_BEEP
 -/* additional beep mixers; the actual parameters are overwritten at build */
 -static const struct snd_kcontrol_new alc_beep_mixer[] = {
 -      HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
 -      HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
 -      { } /* end */
 -};
 -#endif
 -
  static int alc_build_controls(struct hda_codec *codec)
  {
 -      struct alc_spec *spec = codec->spec;
 -      int i, err;
 +      int err;
  
        err = snd_hda_gen_build_controls(codec);
        if (err < 0)
                return err;
  
 -      for (i = 0; i < spec->num_mixers; i++) {
 -              err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
 -              if (err < 0)
 -                      return err;
 -      }
 -
 -#ifdef CONFIG_SND_HDA_INPUT_BEEP
 -      /* create beep controls if needed */
 -      if (spec->beep_amp) {
 -              const struct snd_kcontrol_new *knew;
 -              for (knew = alc_beep_mixer; knew->name; knew++) {
 -                      struct snd_kcontrol *kctl;
 -                      kctl = snd_ctl_new1(knew, codec);
 -                      if (!kctl)
 -                              return -ENOMEM;
 -                      kctl->private_value = spec->beep_amp;
 -                      err = snd_hda_ctl_add(codec, 0, kctl);
 -                      if (err < 0)
 -                              return err;
 -              }
 -      }
 -#endif
 -
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
        return 0;
  }
@@@ -979,30 -973,8 +979,30 @@@ static int alc_codec_rename_from_preset
   * Digital-beep handlers
   */
  #ifdef CONFIG_SND_HDA_INPUT_BEEP
 -#define set_beep_amp(spec, nid, idx, dir) \
 -      ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
 +
 +/* additional beep mixers; private_value will be overwritten */
 +static const struct snd_kcontrol_new alc_beep_mixer[] = {
 +      HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
 +      HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
 +};
 +
 +/* set up and create beep controls */
 +static int set_beep_amp(struct alc_spec *spec, hda_nid_t nid,
 +                      int idx, int dir)
 +{
 +      struct snd_kcontrol_new *knew;
 +      unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(alc_beep_mixer); i++) {
 +              knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
 +                                          &alc_beep_mixer[i]);
 +              if (!knew)
 +                      return -ENOMEM;
 +              knew->private_value = beep_amp;
 +      }
 +      return 0;
 +}
  
  static const struct snd_pci_quirk beep_white_list[] = {
        SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
@@@ -1027,7 -999,7 +1027,7 @@@ static inline int has_cdefine_beep(stru
        return spec->cdefine.enable_pcbeep;
  }
  #else
 -#define set_beep_amp(spec, nid, idx, dir) /* NOP */
 +#define set_beep_amp(spec, nid, idx, dir)     0
  #define has_cdefine_beep(codec)               0
  #endif
  
@@@ -1132,12 -1104,12 +1132,12 @@@ static void alc880_fixup_vol_knob(struc
  
  static const struct hda_fixup alc880_fixups[] = {
        [ALC880_FIXUP_GPIO1] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio1_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio1,
        },
        [ALC880_FIXUP_GPIO2] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio2_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio2,
        },
        [ALC880_FIXUP_MEDION_RIM] = {
                .type = HDA_FIXUP_VERBS,
@@@ -1529,11 -1501,8 +1529,11 @@@ static int patch_alc880(struct hda_code
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog)
 -              set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +      if (!spec->gen.no_analog) {
 +              err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -1575,8 -1544,8 +1575,8 @@@ enum 
  static void alc260_gpio1_automute(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
 -                          spec->gen.hp_jack_present);
 +
 +      alc_update_gpio_data(codec, 0x01, spec->gen.hp_jack_present);
  }
  
  static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
                spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
                snd_hda_jack_detect_enable_callback(codec, 0x0f,
                                                    snd_hda_gen_hp_automute);
 -              snd_hda_add_verbs(codec, alc_gpio1_init_verbs);
 +              alc_setup_gpio(codec, 0x01);
        }
  }
  
@@@ -1620,6 -1589,8 +1620,6 @@@ static void alc260_fixup_kn1(struct hda
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
                snd_hda_apply_pincfgs(codec, pincfgs);
 -              break;
 -      case HDA_FIXUP_ACT_PROBE:
                spec->init_amp = ALC_INIT_NONE;
                break;
        }
@@@ -1629,7 -1600,7 +1629,7 @@@ static void alc260_fixup_fsc_s7020(stru
                                   const struct hda_fixup *fix, int action)
  {
        struct alc_spec *spec = codec->spec;
 -      if (action == HDA_FIXUP_ACT_PROBE)
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
                spec->init_amp = ALC_INIT_NONE;
  }
  
@@@ -1667,8 -1638,8 +1667,8 @@@ static const struct hda_fixup alc260_fi
                },
        },
        [ALC260_FIXUP_GPIO1] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio1_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio1,
        },
        [ALC260_FIXUP_GPIO1_TOGGLE] = {
                .type = HDA_FIXUP_FUNC,
@@@ -1780,11 -1751,8 +1780,11 @@@ static int patch_alc260(struct hda_code
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog)
 -              set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
 +      if (!spec->gen.no_analog) {
 +              err = set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -1856,14 -1824,47 +1856,14 @@@ static void alc889_fixup_coef(struct hd
        alc_update_coef_idx(codec, 7, 0, 0x2030);
  }
  
 -/* 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->core.afg, 0,
 -                                     AC_VERB_GET_GPIO_DATA, 0);
 -
 -      if (!muted)
 -              gpiostate |= (1 << pin);
 -      else
 -              gpiostate &= ~(1 << pin);
 -
 -      gpiomask = snd_hda_codec_read(codec, codec->core.afg, 0,
 -                                    AC_VERB_GET_GPIO_MASK, 0);
 -      gpiomask |= (1 << pin);
 -
 -      gpiodir = snd_hda_codec_read(codec, codec->core.afg, 0,
 -                                   AC_VERB_GET_GPIO_DIRECTION, 0);
 -      gpiodir |= (1 << pin);
 -
 -
 -      snd_hda_codec_write(codec, codec->core.afg, 0,
 -                          AC_VERB_SET_GPIO_MASK, gpiomask);
 -      snd_hda_codec_write(codec, codec->core.afg, 0,
 -                          AC_VERB_SET_GPIO_DIRECTION, gpiodir);
 -
 -      msleep(1);
 -
 -      snd_hda_codec_write(codec, codec->core.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 hda_fixup *fix, int action)
  {
 -      if (action != HDA_FIXUP_ACT_INIT)
 -              return;
 -      alc882_gpio_mute(codec, 0, 0);
 -      alc882_gpio_mute(codec, 1, 0);
 +      struct alc_spec *spec = codec->spec;
 +
 +      spec->gpio_write_delay = true;
 +      alc_fixup_gpio3(codec, fix, action);
  }
  
  /* Fix the connection of some pins for ALC889:
@@@ -2142,20 -2143,20 +2142,20 @@@ static const struct hda_fixup alc882_fi
                }
        },
        [ALC882_FIXUP_GPIO1] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio1_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio1,
        },
        [ALC882_FIXUP_GPIO2] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio2_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio2,
        },
        [ALC882_FIXUP_GPIO3] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio3_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio3,
        },
        [ALC882_FIXUP_ASUS_W2JC] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = alc_gpio1_init_verbs,
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc_fixup_gpio1,
                .chained = true,
                .chain_id = ALC882_FIXUP_EAPD,
        },
@@@ -2365,6 -2366,7 +2365,7 @@@ static const struct snd_pci_quirk alc88
        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(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
  };
  
  static const struct hda_model_fixup alc882_fixup_models[] = {
 +      {.id = ALC882_FIXUP_ABIT_AW9D_MAX, .name = "abit-aw9d"},
 +      {.id = ALC882_FIXUP_LENOVO_Y530, .name = "lenovo-y530"},
 +      {.id = ALC882_FIXUP_ACER_ASPIRE_7736, .name = "acer-aspire-7736"},
 +      {.id = ALC882_FIXUP_ASUS_W90V, .name = "asus-w90v"},
 +      {.id = ALC889_FIXUP_CD, .name = "cd"},
 +      {.id = ALC889_FIXUP_FRONT_HP_NO_PRESENCE, .name = "no-front-hp"},
 +      {.id = ALC889_FIXUP_VAIO_TT, .name = "vaio-tt"},
 +      {.id = ALC888_FIXUP_EEE1601, .name = "eee1601"},
 +      {.id = ALC882_FIXUP_EAPD, .name = "alc882-eapd"},
 +      {.id = ALC883_FIXUP_EAPD, .name = "alc883-eapd"},
 +      {.id = ALC882_FIXUP_GPIO1, .name = "gpio1"},
 +      {.id = ALC882_FIXUP_GPIO2, .name = "gpio2"},
 +      {.id = ALC882_FIXUP_GPIO3, .name = "gpio3"},
 +      {.id = ALC889_FIXUP_COEF, .name = "alc889-coef"},
 +      {.id = ALC882_FIXUP_ASUS_W2JC, .name = "asus-w2jc"},
        {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
        {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
        {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
 +      {.id = ALC885_FIXUP_MACPRO_GPIO, .name = "macpro-gpio"},
 +      {.id = ALC889_FIXUP_DAC_ROUTE, .name = "dac-route"},
 +      {.id = ALC889_FIXUP_MBP_VREF, .name = "mbp-vref"},
 +      {.id = ALC889_FIXUP_IMAC91_VREF, .name = "imac91-vref"},
 +      {.id = ALC889_FIXUP_MBA11_VREF, .name = "mba11-vref"},
 +      {.id = ALC889_FIXUP_MBA21_VREF, .name = "mba21-vref"},
 +      {.id = ALC889_FIXUP_MP11_VREF, .name = "mp11-vref"},
 +      {.id = ALC889_FIXUP_MP41_VREF, .name = "mp41-vref"},
        {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
        {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
 +      {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"},
        {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
 +      {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
        {}
  };
  
@@@ -2458,11 -2435,8 +2459,11 @@@ static int patch_alc882(struct hda_code
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog && spec->gen.beep_nid)
 -              set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +      if (!spec->gen.no_analog && spec->gen.beep_nid) {
 +              err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -2583,14 -2557,6 +2584,14 @@@ static const struct snd_pci_quirk alc26
  
  static const struct hda_model_fixup alc262_fixup_models[] = {
        {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
 +      {.id = ALC262_FIXUP_FSC_H270, .name = "fsc-h270"},
 +      {.id = ALC262_FIXUP_FSC_S7110, .name = "fsc-s7110"},
 +      {.id = ALC262_FIXUP_HP_Z200, .name = "hp-z200"},
 +      {.id = ALC262_FIXUP_TYAN, .name = "tyan"},
 +      {.id = ALC262_FIXUP_LENOVO_3000, .name = "lenovo-3000"},
 +      {.id = ALC262_FIXUP_BENQ, .name = "benq"},
 +      {.id = ALC262_FIXUP_BENQ_T31, .name = "benq-t31"},
 +      {.id = ALC262_FIXUP_INTEL_BAYLEYBAY, .name = "bayleybay"},
        {}
  };
  
@@@ -2632,11 -2598,8 +2633,11 @@@ static int patch_alc262(struct hda_code
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog && spec->gen.beep_nid)
 -              set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +      if (!spec->gen.no_analog && spec->gen.beep_nid) {
 +              err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -2682,6 -2645,7 +2683,6 @@@ static const struct snd_kcontrol_new al
                .put = alc268_beep_switch_put,
                .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT)
        },
 -      { }
  };
  
  /* set PCBEEP vol = 0, mute connections */
@@@ -2722,7 -2686,6 +2723,7 @@@ static const struct hda_fixup alc268_fi
  static const struct hda_model_fixup alc268_fixup_models[] = {
        {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
        {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
 +      {.id = ALC268_FIXUP_SPDIF, .name = "spdif"},
        {}
  };
  
@@@ -2750,7 -2713,7 +2751,7 @@@ static int alc268_parse_auto_config(str
  static int patch_alc268(struct hda_codec *codec)
  {
        struct alc_spec *spec;
 -      int err;
 +      int i, err;
  
        /* ALC268 has no aa-loopback mixer */
        err = alc_alloc_spec(codec, 0);
  
        if (err > 0 && !spec->gen.no_analog &&
            spec->gen.autocfg.speaker_pins[0] != 0x1d) {
 -              add_mixer(spec, alc268_beep_mixer);
 +              for (i = 0; i < ARRAY_SIZE(alc268_beep_mixer); i++) {
 +                      if (!snd_hda_gen_add_kctl(&spec->gen, NULL,
 +                                                &alc268_beep_mixer[i])) {
 +                              err = -ENOMEM;
 +                              goto error;
 +                      }
 +              }
                snd_hda_add_verbs(codec, alc268_beep_init_verbs);
                if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
                        /* override the amp caps for beep generator */
@@@ -3497,8 -3454,9 +3498,8 @@@ static int alc269_resume(struct hda_cod
         * suspend, and won't restore the data after resume, so we restore it
         * in the driver.
         */
 -      if (spec->gpio_led)
 -              snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DATA,
 -                          spec->gpio_led);
 +      if (spec->gpio_data)
 +              alc_write_gpio_data(codec);
  
        if (spec->has_alc5505_dsp)
                alc5505_dsp_resume(codec);
@@@ -3738,10 -3696,18 +3739,10 @@@ static void alc_update_gpio_led(struct 
                                bool enabled)
  {
        struct alc_spec *spec = codec->spec;
 -      unsigned int oldval = spec->gpio_led;
  
        if (spec->mute_led_polarity)
                enabled = !enabled;
 -
 -      if (enabled)
 -              spec->gpio_led &= ~mask;
 -      else
 -              spec->gpio_led |= mask;
 -      if (spec->gpio_led != oldval)
 -              snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
 -                                  spec->gpio_led);
 +      alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */
  }
  
  /* turn on/off mute LED via GPIO per vmaster hook */
@@@ -3754,79 -3720,104 +3755,79 @@@ static void alc_fixup_gpio_mute_hook(vo
  }
  
  /* turn on/off mic-mute LED via GPIO per capture hook */
 -static void alc_fixup_gpio_mic_mute_hook(struct hda_codec *codec,
 -                                       struct snd_kcontrol *kcontrol,
 -                                       struct snd_ctl_elem_value *ucontrol)
 +static void alc_gpio_micmute_update(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
  
 -      if (ucontrol)
 -              alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
 -                                  ucontrol->value.integer.value[0] ||
 -                                  ucontrol->value.integer.value[1]);
 +      alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
 +                          spec->gen.micmute_led.led_value);
  }
  
 -static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
 -                              const struct hda_fixup *fix, int action)
 +/* setup mute and mic-mute GPIO bits, add hooks appropriately */
 +static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
 +                                int action,
 +                                unsigned int mute_mask,
 +                                unsigned int micmute_mask)
  {
        struct alc_spec *spec = codec->spec;
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
 -              {}
 -      };
  
 -      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +      alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
 +
 +      if (action != HDA_FIXUP_ACT_PRE_PROBE)
 +              return;
 +      if (mute_mask) {
 +              spec->gpio_mute_led_mask = mute_mask;
                spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 -              spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
 -              spec->gpio_led = 0;
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mute_led_mask = 0x08;
 -              spec->gpio_mic_led_mask = 0x10;
 -              snd_hda_add_verbs(codec, gpio_init);
 +      }
 +      if (micmute_mask) {
 +              spec->gpio_mic_led_mask = micmute_mask;
 +              snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update);
        }
  }
  
 -static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
 +static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
  {
 -      struct alc_spec *spec = codec->spec;
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x22 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x22 },
 -              {}
 -      };
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10);
 +}
  
 -      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 -              spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 -              spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
 -              spec->gpio_led = 0;
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mute_led_mask = 0x02;
 -              spec->gpio_mic_led_mask = 0x20;
 -              snd_hda_add_verbs(codec, gpio_init);
 -      }
 +static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20);
  }
  
  /* turn on/off mic-mute LED per capture hook */
 -static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
 -                                             struct snd_kcontrol *kcontrol,
 -                                             struct snd_ctl_elem_value *ucontrol)
 +static void alc_cap_micmute_update(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      unsigned int pinval, enable, disable;
 +      unsigned int pinval;
  
 +      if (!spec->cap_mute_led_nid)
 +              return;
        pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
        pinval &= ~AC_PINCTL_VREFEN;
 -      enable  = pinval | AC_PINCTL_VREF_80;
 -      disable = pinval | AC_PINCTL_VREF_HIZ;
 -
 -      if (!ucontrol)
 -              return;
 -
 -      if (ucontrol->value.integer.value[0] ||
 -          ucontrol->value.integer.value[1])
 -              pinval = disable;
 +      if (spec->gen.micmute_led.led_value)
 +              pinval |= AC_PINCTL_VREF_80;
        else
 -              pinval = enable;
 -
 -      if (spec->cap_mute_led_nid)
 -              snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
 +              pinval |= AC_PINCTL_VREF_HIZ;
 +      snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
  }
  
  static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
  {
        struct alc_spec *spec = codec->spec;
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 },
 -              {}
 -      };
  
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 -              spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 -              spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
 -              spec->gpio_led = 0;
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mute_led_mask = 0x08;
 +              /* Like hp_gpio_mic1_led, but also needs GPIO4 low to
 +               * enable headphone amp
 +               */
 +              spec->gpio_mask |= 0x10;
 +              spec->gpio_dir |= 0x10;
                spec->cap_mute_led_nid = 0x18;
 -              snd_hda_add_verbs(codec, gpio_init);
 +              snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
                codec->power_filter = led_power_filter;
        }
  }
  static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
  {
 -      /* Like hp_gpio_mic1_led, but also needs GPIO4 low to enable headphone amp */
        struct alc_spec *spec = codec->spec;
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
 -              {}
 -      };
  
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 -              spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 -              spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
 -              spec->gpio_led = 0;
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mute_led_mask = 0x08;
                spec->cap_mute_led_nid = 0x18;
 -              snd_hda_add_verbs(codec, gpio_init);
 +              snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
                codec->power_filter = led_power_filter;
        }
  }
@@@ -3889,29 -3890,38 +3890,29 @@@ static int alc_register_micmute_input_d
        return 0;
  }
  
 +/* GPIO1 = set according to SKU external amp
 + * GPIO2 = mic mute hotkey
 + * GPIO3 = mute LED
 + * GPIO4 = mic mute LED
 + */
  static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
                                             const struct hda_fixup *fix, int action)
  {
 -      /* GPIO1 = set according to SKU external amp
 -         GPIO2 = mic mute hotkey
 -         GPIO3 = mute LED
 -         GPIO4 = mic mute LED */
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x1e },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x1a },
 -              { 0x01, AC_VERB_SET_GPIO_DATA, 0x02 },
 -              {}
 -      };
 -
        struct alc_spec *spec = codec->spec;
  
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->init_amp = ALC_INIT_DEFAULT;
                if (alc_register_micmute_input_device(codec) != 0)
                        return;
  
 -              snd_hda_add_verbs(codec, gpio_init);
 +              spec->gpio_mask |= 0x06;
 +              spec->gpio_dir |= 0x02;
 +              spec->gpio_data |= 0x02;
                snd_hda_codec_write_cache(codec, codec->core.afg, 0,
                                          AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04);
                snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
                                                    gpio2_mic_hotkey_event);
 -
 -              spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 -              spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
 -              spec->gpio_led = 0;
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mute_led_mask = 0x08;
 -              spec->gpio_mic_led_mask = 0x10;
                return;
        }
  
                return;
  
        switch (action) {
 -      case HDA_FIXUP_ACT_PROBE:
 -              spec->init_amp = ALC_INIT_DEFAULT;
 -              break;
        case HDA_FIXUP_ACT_FREE:
                input_unregister_device(spec->kb_dev);
                spec->kb_dev = NULL;
        }
  }
  
 +/* Line2 = mic mute hotkey
 + * GPIO2 = mic mute LED
 + */
  static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec,
                                             const struct hda_fixup *fix, int action)
  {
 -      /* Line2 = mic mute hotkey
 -         GPIO2 = mic mute LED */
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
 -              {}
 -      };
 -
        struct alc_spec *spec = codec->spec;
  
 +      alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->init_amp = ALC_INIT_DEFAULT;
                if (alc_register_micmute_input_device(codec) != 0)
                        return;
  
 -              snd_hda_add_verbs(codec, gpio_init);
                snd_hda_jack_detect_enable_callback(codec, 0x1b,
                                                    gpio2_mic_hotkey_event);
 -
 -              spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
 -              spec->gpio_led = 0;
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mic_led_mask = 0x04;
                return;
        }
  
                return;
  
        switch (action) {
 -      case HDA_FIXUP_ACT_PROBE:
 -              spec->init_amp = ALC_INIT_DEFAULT;
 -              break;
        case HDA_FIXUP_ACT_FREE:
                input_unregister_device(spec->kb_dev);
                spec->kb_dev = NULL;
@@@ -3963,10 -3988,14 +3964,10 @@@ static void alc269_fixup_hp_line1_mic1_
  {
        struct alc_spec *spec = codec->spec;
  
 +      alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 -              spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
 -              spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
 -              spec->mute_led_polarity = 0;
 -              spec->mute_led_nid = 0x1a;
                spec->cap_mute_led_nid = 0x18;
 -              spec->gen.vmaster_mute_enum = 1;
 -              codec->power_filter = led_power_filter;
 +              snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
        }
  }
  
@@@ -4814,7 -4843,6 +4815,7 @@@ static void alc_probe_headset_mode(stru
                        spec->headphone_mic_pin = cfg->inputs[i].pin;
        }
  
 +      WARN_ON(spec->gen.cap_sync_hook);
        spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
        spec->gen.automute_hook = alc_update_headset_mode;
        spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
@@@ -4906,10 -4934,13 +4907,10 @@@ static void alc288_update_headset_jack_
                                       struct hda_jack_callback *jack)
  {
        struct alc_spec *spec = codec->spec;
 -      int present;
  
        alc_update_headset_jack_cb(codec, jack);
        /* Headset Mic enable or disable, only for Dell Dino */
 -      present = spec->gen.hp_jack_present ? 0x40 : 0;
 -      snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
 -                              present);
 +      alc_update_gpio_data(codec, 0x40, spec->gen.hp_jack_present);
  }
  
  static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec,
        alc_fixup_headset_mode(codec, fix, action);
        if (action == HDA_FIXUP_ACT_PROBE) {
                struct alc_spec *spec = codec->spec;
 +              /* toggled via hp_automute_hook */
 +              spec->gpio_mask |= 0x40;
 +              spec->gpio_dir |= 0x40;
                spec->gen.hp_automute_hook = alc288_update_headset_jack_cb;
        }
  }
@@@ -4941,7 -4969,7 +4942,7 @@@ static void alc_no_shutup(struct hda_co
  static void alc_fixup_no_shutup(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
  {
 -      if (action == HDA_FIXUP_ACT_PROBE) {
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                struct alc_spec *spec = codec->spec;
                spec->shutup = alc_no_shutup;
        }
@@@ -5023,9 -5051,10 +5024,9 @@@ static void alc_fixup_dell_xps13(struc
                 * it causes a click noise at start up
                 */
                snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
 +              spec->shutup = alc_shutup_dell_xps13;
                break;
        case HDA_FIXUP_ACT_PROBE:
 -              spec->shutup = alc_shutup_dell_xps13;
 -
                /* Make the internal mic the default input source. */
                for (i = 0; i < imux->num_items; i++) {
                        if (spec->gen.imux_pins[i] == 0x12) {
@@@ -5202,6 -5231,13 +5203,6 @@@ static void alc282_fixup_asus_tx300(str
                                    const struct hda_fixup *fix, int action)
  {
        struct alc_spec *spec = codec->spec;
 -      /* TX300 needs to set up GPIO2 for the speaker amp */
 -      static const struct hda_verb gpio2_verbs[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
 -              { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 },
 -              {}
 -      };
        static const struct hda_pintbl dock_pins[] = {
                { 0x1b, 0x21114000 }, /* dock speaker pin */
                {}
  
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
 -              snd_hda_add_verbs(codec, gpio2_verbs);
 +              spec->init_amp = ALC_INIT_DEFAULT;
 +              /* TX300 needs to set up GPIO2 for the speaker amp */
 +              alc_setup_gpio(codec, 0x04);
                snd_hda_apply_pincfgs(codec, dock_pins);
                spec->gen.auto_mute_via_amp = 1;
                spec->gen.automute_hook = asus_tx300_automute;
                snd_hda_jack_detect_enable_callback(codec, 0x1b,
                                                    snd_hda_gen_hp_automute);
                break;
 +      case HDA_FIXUP_ACT_PROBE:
 +              spec->init_amp = ALC_INIT_DEFAULT;
 +              break;
        case HDA_FIXUP_ACT_BUILD:
                /* this is a bit tricky; give more sane names for the main
                 * (tablet) speaker and the dock speaker, respectively
@@@ -5294,26 -5325,30 +5295,26 @@@ static void alc280_fixup_hp_9480m(struc
                                  int action)
  {
        struct alc_spec *spec = codec->spec;
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
 -              {}
 -      };
  
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 -              /* Set the hooks to turn the headphone amp on/off
 -               * as needed
 -               */
 -              spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 +              /* amp at GPIO4; toggled via alc280_hp_gpio4_automute_hook() */
 +              spec->gpio_mask |= 0x10;
 +              spec->gpio_dir |= 0x10;
                spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook;
 +      }
 +}
  
 -              /* The GPIOs are currently off */
 -              spec->gpio_led = 0;
 -
 -              /* GPIO3 is connected to the output mute LED,
 -               * high is on, low is off
 -               */
 -              spec->mute_led_polarity = 0;
 -              spec->gpio_mute_led_mask = 0x08;
 +static void alc275_fixup_gpio4_off(struct hda_codec *codec,
 +                                 const struct hda_fixup *fix,
 +                                 int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -              /* Initialize GPIO configuration */
 -              snd_hda_add_verbs(codec, gpio_init);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->gpio_mask |= 0x04;
 +              spec->gpio_dir |= 0x04;
 +              /* set data bit low */
        }
  }
  
@@@ -5457,6 -5492,7 +5458,6 @@@ enum 
        ALC280_FIXUP_HP_9480M,
        ALC288_FIXUP_DELL_HEADSET_MODE,
        ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
 -      ALC288_FIXUP_DELL_XPS_13_GPIO6,
        ALC288_FIXUP_DELL_XPS_13,
        ALC288_FIXUP_DISABLE_AAMIX,
        ALC292_FIXUP_DELL_E7X,
@@@ -5504,8 -5540,13 +5505,8 @@@ static const struct hda_fixup alc269_fi
                }
        },
        [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
 -                      {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
 -                      {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
 -                      { }
 -              },
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc275_fixup_gpio4_off,
                .chained = true,
                .chain_id = ALC269_FIXUP_SONY_VAIO
        },
                .chained = true,
                .chain_id = ALC288_FIXUP_DELL_HEADSET_MODE
        },
 -      [ALC288_FIXUP_DELL_XPS_13_GPIO6] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      {0x01, AC_VERB_SET_GPIO_MASK, 0x40},
 -                      {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x40},
 -                      {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
 -                      { }
 -              },
 -              .chained = true,
 -              .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE
 -      },
        [ALC288_FIXUP_DISABLE_AAMIX] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_disable_aamix,
                .chained = true,
 -              .chain_id = ALC288_FIXUP_DELL_XPS_13_GPIO6
 +              .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE
        },
        [ALC288_FIXUP_DELL_XPS_13] = {
                .type = HDA_FIXUP_FUNC,
                .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
        },
        [ALC256_FIXUP_ASUS_AIO_GPIO2] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      /* Set up GPIO2 for the speaker amp */
 -                      { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
 -                      { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
 -                      { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 },
 -                      {}
 -              },
 +              .type = HDA_FIXUP_FUNC,
 +              /* Set up GPIO2 for the speaker amp */
 +              .v.func = alc_fixup_gpio4,
        },
        [ALC233_FIXUP_ASUS_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
@@@ -6656,95 -6713,13 +6657,95 @@@ static const struct hda_model_fixup alc
        {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic1-led"},
        {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
        {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
 +      {.id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, .name = "dell-headset3"},
 +      {.id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, .name = "dell-headset4"},
        {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
        {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
        {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
        {.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
        {.id = ALC292_FIXUP_TPT460, .name = "tpt460"},
 +      {.id = ALC298_FIXUP_TPT470_DOCK, .name = "tpt470-dock"},
        {.id = ALC233_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
        {.id = ALC700_FIXUP_INTEL_REFERENCE, .name = "alc700-ref"},
 +      {.id = ALC269_FIXUP_SONY_VAIO, .name = "vaio"},
 +      {.id = ALC269_FIXUP_DELL_M101Z, .name = "dell-m101z"},
 +      {.id = ALC269_FIXUP_ASUS_G73JW, .name = "asus-g73jw"},
 +      {.id = ALC269_FIXUP_LENOVO_EAPD, .name = "lenovo-eapd"},
 +      {.id = ALC275_FIXUP_SONY_HWEQ, .name = "sony-hweq"},
 +      {.id = ALC269_FIXUP_PCM_44K, .name = "pcm44k"},
 +      {.id = ALC269_FIXUP_LIFEBOOK, .name = "lifebook"},
 +      {.id = ALC269_FIXUP_LIFEBOOK_EXTMIC, .name = "lifebook-extmic"},
 +      {.id = ALC269_FIXUP_LIFEBOOK_HP_PIN, .name = "lifebook-hp-pin"},
 +      {.id = ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC, .name = "lifebook-u7x7"},
 +      {.id = ALC269VB_FIXUP_AMIC, .name = "alc269vb-amic"},
 +      {.id = ALC269VB_FIXUP_DMIC, .name = "alc269vb-dmic"},
 +      {.id = ALC269_FIXUP_HP_MUTE_LED_MIC1, .name = "hp-mute-led-mic1"},
 +      {.id = ALC269_FIXUP_HP_MUTE_LED_MIC2, .name = "hp-mute-led-mic2"},
 +      {.id = ALC269_FIXUP_HP_MUTE_LED_MIC3, .name = "hp-mute-led-mic3"},
 +      {.id = ALC269_FIXUP_HP_GPIO_MIC1_LED, .name = "hp-gpio-mic1"},
 +      {.id = ALC269_FIXUP_HP_LINE1_MIC1_LED, .name = "hp-line1-mic1"},
 +      {.id = ALC269_FIXUP_NO_SHUTUP, .name = "noshutup"},
 +      {.id = ALC286_FIXUP_SONY_MIC_NO_PRESENCE, .name = "sony-nomic"},
 +      {.id = ALC269_FIXUP_ASPIRE_HEADSET_MIC, .name = "aspire-headset-mic"},
 +      {.id = ALC269_FIXUP_ASUS_X101, .name = "asus-x101"},
 +      {.id = ALC271_FIXUP_HP_GATE_MIC_JACK, .name = "acer-ao7xx"},
 +      {.id = ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572, .name = "acer-aspire-e1"},
 +      {.id = ALC269_FIXUP_ACER_AC700, .name = "acer-ac700"},
 +      {.id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST, .name = "limit-mic-boost"},
 +      {.id = ALC269VB_FIXUP_ASUS_ZENBOOK, .name = "asus-zenbook"},
 +      {.id = ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A, .name = "asus-zenbook-ux31a"},
 +      {.id = ALC269VB_FIXUP_ORDISSIMO_EVE2, .name = "ordissimo"},
 +      {.id = ALC282_FIXUP_ASUS_TX300, .name = "asus-tx300"},
 +      {.id = ALC283_FIXUP_INT_MIC, .name = "alc283-int-mic"},
 +      {.id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK, .name = "mono-speakers"},
 +      {.id = ALC290_FIXUP_SUBWOOFER_HSJACK, .name = "alc290-subwoofer"},
 +      {.id = ALC269_FIXUP_THINKPAD_ACPI, .name = "thinkpad"},
 +      {.id = ALC269_FIXUP_DMIC_THINKPAD_ACPI, .name = "dmic-thinkpad"},
 +      {.id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE, .name = "alc255-acer"},
 +      {.id = ALC255_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc255-asus"},
 +      {.id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"},
 +      {.id = ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "alc255-dell2"},
 +      {.id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc293-dell1"},
 +      {.id = ALC283_FIXUP_HEADSET_MIC, .name = "alc283-headset"},
 +      {.id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, .name = "alc255-dell-mute"},
 +      {.id = ALC282_FIXUP_ASPIRE_V5_PINS, .name = "aspire-v5"},
 +      {.id = ALC280_FIXUP_HP_GPIO4, .name = "hp-gpio4"},
 +      {.id = ALC286_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
 +      {.id = ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY, .name = "hp-gpio2-hotkey"},
 +      {.id = ALC280_FIXUP_HP_DOCK_PINS, .name = "hp-dock-pins"},
 +      {.id = ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED, .name = "hp-dock-gpio-mic"},
 +      {.id = ALC280_FIXUP_HP_9480M, .name = "hp-9480m"},
 +      {.id = ALC288_FIXUP_DELL_HEADSET_MODE, .name = "alc288-dell-headset"},
 +      {.id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc288-dell1"},
 +      {.id = ALC288_FIXUP_DELL_XPS_13, .name = "alc288-dell-xps13"},
 +      {.id = ALC292_FIXUP_DELL_E7X, .name = "dell-e7x"},
 +      {.id = ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK, .name = "alc293-dell"},
 +      {.id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc298-dell1"},
 +      {.id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, .name = "alc298-dell-aio"},
 +      {.id = ALC275_FIXUP_DELL_XPS, .name = "alc275-dell-xps"},
 +      {.id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, .name = "alc256-dell-xps13"},
 +      {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"},
 +      {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"},
 +      {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"},
 +      {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"},
 +      {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"},
 +      {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"},
 +      {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"},
 +      {.id = ALC298_FIXUP_SPK_VOLUME, .name = "alc298-spk-volume"},
 +      {.id = ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER, .name = "dell-inspiron-7559"},
 +      {.id = ALC269_FIXUP_ATIV_BOOK_8, .name = "ativ-book"},
 +      {.id = ALC221_FIXUP_HP_MIC_NO_PRESENCE, .name = "alc221-hp-mic"},
 +      {.id = ALC256_FIXUP_ASUS_HEADSET_MODE, .name = "alc256-asus-headset"},
 +      {.id = ALC256_FIXUP_ASUS_MIC, .name = "alc256-asus-mic"},
 +      {.id = ALC256_FIXUP_ASUS_AIO_GPIO2, .name = "alc256-asus-aio"},
 +      {.id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc233-asus"},
 +      {.id = ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE, .name = "alc233-eapd"},
 +      {.id = ALC294_FIXUP_LENOVO_MIC_LOCATION, .name = "alc294-lenovo-mic"},
 +      {.id = ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE, .name = "alc225-wyse"},
 +      {.id = ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, .name = "alc274-dell-aio"},
 +      {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"},
 +      {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"},
 +      {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"},
        {}
  };
  #define ALC225_STANDARD_PINS \
@@@ -7008,7 -6983,7 +7009,7 @@@ static const struct snd_hda_pin_quirk a
                {0x12, 0x90a60130},
                {0x19, 0x03a11020},
                {0x21, 0x0321101f}),
 -      SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL_XPS_13_GPIO6,
 +      SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x12, 0x90a60120},
                {0x14, 0x90170110},
                {0x21, 0x0321101f}),
@@@ -7165,6 -7140,18 +7166,6 @@@ static int patch_alc269(struct hda_code
        spec->shutup = alc_default_shutup;
        spec->init_hook = alc_default_init;
  
 -      snd_hda_pick_fixup(codec, alc269_fixup_models,
 -                     alc269_fixup_tbl, alc269_fixups);
 -      snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
 -      snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
 -                         alc269_fixups);
 -      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 -
 -      alc_auto_parse_customize_define(codec);
 -
 -      if (has_cdefine_beep(codec))
 -              spec->gen.beep_nid = 0x01;
 -
        switch (codec->core.vendor_id) {
        case 0x10ec0269:
                spec->codec_variant = ALC269_TYPE_ALC269VA;
                spec->init_hook = alc5505_dsp_init;
        }
  
 +      snd_hda_pick_fixup(codec, alc269_fixup_models,
 +                     alc269_fixup_tbl, alc269_fixups);
 +      snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
 +      snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
 +                         alc269_fixups);
 +      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 +
 +      alc_auto_parse_customize_define(codec);
 +
 +      if (has_cdefine_beep(codec))
 +              spec->gen.beep_nid = 0x01;
 +
        /* automatic parse from the BIOS config */
        err = alc269_parse_auto_config(codec);
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid)
 -              set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT);
 +      if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) {
 +              err = set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -7434,11 -7406,8 +7435,11 @@@ static int patch_alc861(struct hda_code
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog)
 -              set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
 +      if (!spec->gen.no_analog) {
 +              err = set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -7478,21 -7447,16 +7479,21 @@@ static void alc861vd_fixup_dallas(struc
        }
  }
  
 +/* reset GPIO1 */
 +static void alc660vd_fixup_asus_gpio1(struct hda_codec *codec,
 +                                    const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
 +
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              spec->gpio_mask |= 0x02;
 +      alc_fixup_gpio(codec, action, 0x01);
 +}
 +
  static const struct hda_fixup alc861vd_fixups[] = {
        [ALC660VD_FIX_ASUS_GPIO1] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      /* reset GPIO1 */
 -                      {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
 -                      {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
 -                      {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
 -                      { }
 -              }
 +              .type = HDA_FIXUP_FUNC,
 +              .v.func = alc660vd_fixup_asus_gpio1,
        },
        [ALC861VD_FIX_DALLAS] = {
                .type = HDA_FIXUP_FUNC,
@@@ -7531,11 -7495,8 +7532,11 @@@ static int patch_alc861vd(struct hda_co
        if (err < 0)
                goto error;
  
 -      if (!spec->gen.no_analog)
 -              set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +      if (!spec->gen.no_analog) {
 +              err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +              if (err < 0)
 +                      goto error;
 +      }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
  
@@@ -7616,7 -7577,7 +7617,7 @@@ static unsigned int gpio_led_power_filt
                                          unsigned int power_state)
  {
        struct alc_spec *spec = codec->spec;
 -      if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_led)
 +      if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_data)
                return AC_PWRST_D0;
        return power_state;
  }
@@@ -7625,10 -7586,18 +7626,10 @@@ static void alc662_fixup_led_gpio1(stru
                                   const struct hda_fixup *fix, int action)
  {
        struct alc_spec *spec = codec->spec;
 -      static const struct hda_verb gpio_init[] = {
 -              { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 },
 -              { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 },
 -              {}
 -      };
  
 +      alc_fixup_hp_gpio_led(codec, action, 0x01, 0);
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 -              spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
 -              spec->gpio_led = 0;
                spec->mute_led_polarity = 1;
 -              spec->gpio_mute_led_mask = 0x01;
 -              snd_hda_add_verbs(codec, gpio_init);
                codec->power_filter = gpio_led_power_filter;
        }
  }
@@@ -8141,10 -8110,7 +8142,10 @@@ static const struct snd_pci_quirk alc66
  };
  
  static const struct hda_model_fixup alc662_fixup_models[] = {
 +      {.id = ALC662_FIXUP_ASPIRE, .name = "aspire"},
 +      {.id = ALC662_FIXUP_IDEAPAD, .name = "ideapad"},
        {.id = ALC272_FIXUP_MARIO, .name = "mario"},
 +      {.id = ALC662_FIXUP_HP_RP5800, .name = "hp-rp5800"},
        {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
        {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
        {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
        {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
        {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
        {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
 +      {.id = ALC662_FIXUP_ZOTAC_Z68, .name = "zotac-z68"},
        {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
 +      {.id = ALC662_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc662-headset-multi"},
        {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
 +      {.id = ALC662_FIXUP_HEADSET_MODE, .name = "alc662-headset"},
 +      {.id = ALC668_FIXUP_HEADSET_MODE, .name = "alc668-headset"},
 +      {.id = ALC662_FIXUP_BASS_16, .name = "bass16"},
 +      {.id = ALC662_FIXUP_BASS_1A, .name = "bass1a"},
 +      {.id = ALC668_FIXUP_AUTO_MUTE, .name = "automute"},
 +      {.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"},
 +      {.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"},
 +      {.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"},
 +      {.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"},
 +      {.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"},
 +      {.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"},
 +      {.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"},
 +      {.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"},
        {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
        {}
  };
@@@ -8263,20 -8214,18 +8264,20 @@@ static int patch_alc662(struct hda_code
        if (!spec->gen.no_analog && spec->gen.beep_nid) {
                switch (codec->core.vendor_id) {
                case 0x10ec0662:
 -                      set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 +                      err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
                        break;
                case 0x10ec0272:
                case 0x10ec0663:
                case 0x10ec0665:
                case 0x10ec0668:
 -                      set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
 +                      err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
                        break;
                case 0x10ec0273:
 -                      set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
 +                      err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
                        break;
                }
 +              if (err < 0)
 +                      goto error;
        }
  
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);