]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Merge branch 'for-linus' into for-next
authorTakashi Iwai <tiwai@suse.de>
Tue, 22 Jul 2025 18:02:13 +0000 (20:02 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 22 Jul 2025 18:02:20 +0000 (20:02 +0200)
Signed-off-by: Takashi Iwai <tiwai@suse.de>
1  2 
sound/hda/codecs/realtek/alc269.c

index 88fc835c7088047fdb682c39936b308e18500d39,2627e2f49316c921e438b5395657a861b5574296..05019fa73297429e5e9ffdc297f4727720e7a693
@@@ -1298,1025 -2215,1480 +1298,1025 @@@ static void alc269_fixup_hp_mute_led_mi
        }
  }
  
 -static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
 -                                   const struct hda_fixup *fix,
 -                                   int action)
 +static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x18);
 +}
 +
 +static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      static const hda_nid_t conn1[] = { 0x0c };
 +      alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x19);
 +}
  
 -      if (action != HDA_FIXUP_ACT_PRE_PROBE)
 -              return;
 +static void alc269_fixup_hp_mute_led_mic3(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1b);
 +}
  
 -      alc_update_coef_idx(codec, 0x7, 0, 0x3c3);
 -      /* We therefore want to make sure 0x14 (front headphone) and
 -       * 0x1b (speakers) use the stereo DAC 0x02
 -       */
 -      snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
 -      snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
 +static void alc236_fixup_hp_gpio_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_hp_gpio_led(codec, action, 0x02, 0x01);
  }
  
 -static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
 -                              const struct hda_fixup *fix, int action);
 +static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10);
 +}
  
 -static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec,
 -                                   const struct hda_fixup *fix,
 -                                   int action)
 +static void alc285_fixup_hp_gpio_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      alc1220_fixup_clevo_p950(codec, fix, action);
 -      alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
 +      alc_fixup_hp_gpio_led(codec, action, 0x04, 0x01);
  }
  
 -static void alc887_asus_hp_automute_hook(struct hda_codec *codec,
 -                                       struct hda_jack_callback *jack)
 +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);
 +}
 +
 +static void alc287_fixup_hp_gpio_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc_fixup_hp_gpio_led(codec, action, 0x10, 0);
 +}
 +
 +static void alc245_fixup_hp_gpio_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
        struct alc_spec *spec = codec->spec;
 -      unsigned int vref;
  
 -      snd_hda_gen_hp_automute(codec, jack);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              spec->micmute_led_polarity = 1;
 +      alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
 +}
  
 -      if (spec->gen.hp_jack_present)
 -              vref = AC_PINCTL_VREF_80;
 -      else
 -              vref = AC_PINCTL_VREF_HIZ;
 -      snd_hda_set_pin_ctl(codec, 0x19, PIN_HP | vref);
 +/* turn on/off mic-mute LED per capture hook via VREF change */
 +static int vref_micmute_led_set(struct led_classdev *led_cdev,
 +                              enum led_brightness brightness)
 +{
 +      struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 +      struct alc_spec *spec = codec->spec;
 +
 +      alc_update_vref_led(codec, spec->cap_mute_led_nid,
 +                          spec->micmute_led_polarity, brightness);
 +      return 0;
  }
  
 -static void alc887_fixup_asus_jack(struct hda_codec *codec,
 -                                   const struct hda_fixup *fix, int action)
 +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;
 -      if (action != HDA_FIXUP_ACT_PROBE)
 -              return;
 -      snd_hda_set_pin_ctl_cache(codec, 0x1b, PIN_HP);
 -      spec->gen.hp_automute_hook = alc887_asus_hp_automute_hook;
 +
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              /* 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_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
 +              codec->power_filter = led_power_filter;
 +      }
  }
  
 -static const struct hda_fixup alc882_fixups[] = {
 -      [ALC882_FIXUP_ABIT_AW9D_MAX] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x15, 0x01080104 }, /* side */
 -                      { 0x16, 0x01011012 }, /* rear */
 -                      { 0x17, 0x01016011 }, /* clfe */
 -                      { }
 -              }
 -      },
 -      [ALC882_FIXUP_LENOVO_Y530] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x15, 0x99130112 }, /* rear int speakers */
 -                      { 0x16, 0x99130111 }, /* subwoofer */
 -                      { }
 -              }
 -      },
 -      [ALC882_FIXUP_PB_M5210] = {
 -              .type = HDA_FIXUP_PINCTLS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x19, PIN_VREF50 },
 -                      {}
 -              }
 -      },
 -      [ALC882_FIXUP_ACER_ASPIRE_7736] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_sku_ignore,
 -      },
 -      [ALC882_FIXUP_ASUS_W90V] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x16, 0x99130110 }, /* fix sequence for CLFE */
 -                      { }
 -              }
 -      },
 -      [ALC889_FIXUP_CD] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x1c, 0x993301f0 }, /* CD */
 -                      { }
 -              }
 -      },
 -      [ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
 -                      { }
 -              },
 -              .chained = true,
 -              .chain_id = ALC889_FIXUP_CD,
 -      },
 -      [ALC889_FIXUP_VAIO_TT] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x17, 0x90170111 }, /* hidden surround speaker */
 -                      { }
 -              }
 -      },
 -      [ALC888_FIXUP_EEE1601] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
 -                      { 0x20, AC_VERB_SET_PROC_COEF,  0x0838 },
 -                      { }
 -              }
 -      },
 -      [ALC886_FIXUP_EAPD] = {
 -              .type = HDA_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, 0x0068 },
 -                      { }
 -              }
 -      },
 -      [ALC882_FIXUP_EAPD] = {
 -              .type = HDA_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 = HDA_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 = HDA_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_GPIO1] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_gpio1,
 -      },
 -      [ALC882_FIXUP_GPIO2] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_gpio2,
 -      },
 -      [ALC882_FIXUP_GPIO3] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_gpio3,
 -      },
 -      [ALC882_FIXUP_ASUS_W2JC] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_gpio1,
 -              .chained = true,
 -              .chain_id = ALC882_FIXUP_EAPD,
 -      },
 -      [ALC889_FIXUP_COEF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_coef,
 -      },
 -      [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x16, 0x99130111 }, /* CLFE speaker */
 -                      { 0x17, 0x99130112 }, /* surround speaker */
 -                      { }
 -              },
 -              .chained = true,
 -              .chain_id = ALC882_FIXUP_GPIO1,
 -      },
 -      [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 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 = HDA_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 },
 -                      { }
 -              },
 -              .chained = true,
 -              .chain_id = ALC882_FIXUP_GPIO1,
 -      },
 -      [ALC885_FIXUP_MACPRO_GPIO] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc885_fixup_macpro_gpio,
 -      },
 -      [ALC889_FIXUP_DAC_ROUTE] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_dac_route,
 -      },
 -      [ALC889_FIXUP_MBP_VREF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_mbp_vref,
 -              .chained = true,
 -              .chain_id = ALC882_FIXUP_GPIO1,
 -      },
 -      [ALC889_FIXUP_IMAC91_VREF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_imac91_vref,
 -              .chained = true,
 -              .chain_id = ALC882_FIXUP_GPIO1,
 -      },
 -      [ALC889_FIXUP_MBA11_VREF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_mba11_vref,
 -              .chained = true,
 -              .chain_id = ALC889_FIXUP_MBP_VREF,
 -      },
 -      [ALC889_FIXUP_MBA21_VREF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_mba21_vref,
 -              .chained = true,
 -              .chain_id = ALC889_FIXUP_MBP_VREF,
 -      },
 -      [ALC889_FIXUP_MP11_VREF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_mba11_vref,
 -              .chained = true,
 -              .chain_id = ALC885_FIXUP_MACPRO_GPIO,
 -      },
 -      [ALC889_FIXUP_MP41_VREF] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc889_fixup_mbp_vref,
 -              .chained = true,
 -              .chain_id = ALC885_FIXUP_MACPRO_GPIO,
 -      },
 -      [ALC882_FIXUP_INV_DMIC] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_inv_dmic,
 -      },
 -      [ALC882_FIXUP_NO_PRIMARY_HP] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc882_fixup_no_primary_hp,
 -      },
 -      [ALC887_FIXUP_ASUS_BASS] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      {0x16, 0x99130130}, /* bass speaker */
 -                      {}
 -              },
 -              .chained = true,
 -              .chain_id = ALC887_FIXUP_BASS_CHMAP,
 -      },
 -      [ALC887_FIXUP_BASS_CHMAP] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_bass_chmap,
 -      },
 -      [ALC1220_FIXUP_GB_DUAL_CODECS] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc1220_fixup_gb_dual_codecs,
 -      },
 -      [ALC1220_FIXUP_GB_X570] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc1220_fixup_gb_x570,
 -      },
 -      [ALC1220_FIXUP_CLEVO_P950] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc1220_fixup_clevo_p950,
 -      },
 -      [ALC1220_FIXUP_CLEVO_PB51ED] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc1220_fixup_clevo_pb51ed,
 -      },
 -      [ALC1220_FIXUP_CLEVO_PB51ED_PINS] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
 -                      {}
 -              },
 -              .chained = true,
 -              .chain_id = ALC1220_FIXUP_CLEVO_PB51ED,
 -      },
 -      [ALC887_FIXUP_ASUS_AUDIO] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x15, 0x02a14150 }, /* use as headset mic, without its own jack detect */
 -                      { 0x19, 0x22219420 },
 -                      {}
 -              },
 -      },
 -      [ALC887_FIXUP_ASUS_HMIC] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc887_fixup_asus_jack,
 -              .chained = true,
 -              .chain_id = ALC887_FIXUP_ASUS_AUDIO,
 -      },
 -      [ALCS1200A_FIXUP_MIC_VREF] = {
 -              .type = HDA_FIXUP_PINCTLS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x18, PIN_VREF50 }, /* rear mic */
 -                      { 0x19, PIN_VREF50 }, /* front mic */
 -                      {}
 -              }
 -      },
 -      [ALC888VD_FIXUP_MIC_100VREF] = {
 -              .type = HDA_FIXUP_PINCTLS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x18, PIN_VREF100 }, /* headset mic */
 -                      {}
 -              }
 -      },
 -};
 -
 -static const struct hda_quirk alc882_fixup_tbl[] = {
 -      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, 0x0107, "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, 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, 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, 0x021e, "Acer Aspire 5739G",
 -                    ALC882_FIXUP_ACER_ASPIRE_4930G),
 -      SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
 -      SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
 -      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, 0x2390, "Asus D700SA", ALC887_FIXUP_ASUS_HMIC),
 -      SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
 -      SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
 -      SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
 -      SND_PCI_QUIRK(0x1043, 0x8797, "ASUS TUF B550M-PLUS", ALCS1200A_FIXUP_MIC_VREF),
 -      SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
 -      SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
 -      SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
 -      SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
 -      SND_PCI_QUIRK(0x104d, 0x9060, "Sony Vaio VPCL14M1R", ALC882_FIXUP_NO_PRIMARY_HP),
 -
 -      /* All Apple entries are in codec SSIDs */
 -      SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF),
 -      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, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
 -      SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBA11_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
 -      SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 4,1/5,1", ALC889_FIXUP_MP41_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
 -      SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
 -
 -      SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
 -      SND_PCI_QUIRK(0x10ec, 0x12d8, "iBase Elo Touch", ALC888VD_FIXUP_MIC_100VREF),
 -      SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
 -      SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
 -      SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
 -      SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570),
 -      SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_GB_X570),
 -      SND_PCI_QUIRK(0x1458, 0xa0d5, "Gigabyte X570S Aorus Master", ALC1220_FIXUP_GB_X570),
 -      SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
 -      SND_PCI_QUIRK(0x1462, 0xcc34, "MSI Godlike X570", ALC1220_FIXUP_GB_DUAL_CODECS),
 -      SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
 -      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, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x5802, "Clevo X58[05]WN[RST]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x66a2, "Clevo PE60RNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x66a6, "Clevo PE60SN[CDE]-[GS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
 -      SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x950a, "Clevo P955H[PR]", 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(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
 -      SND_PCI_QUIRK(0x1558, 0xd502, "Clevo PD50SNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
 -      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),
 -      {}
 -};
 -
 -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_GB_X570, .name = "gb-x570"},
 -      {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
 -      {}
 -};
 -
 -static const struct snd_hda_pin_quirk alc882_pin_fixup_tbl[] = {
 -      SND_HDA_PIN_QUIRK(0x10ec1220, 0x1043, "ASUS", ALC1220_FIXUP_CLEVO_P950,
 -              {0x14, 0x01014010},
 -              {0x15, 0x01011012},
 -              {0x16, 0x01016011},
 -              {0x18, 0x01a19040},
 -              {0x19, 0x02a19050},
 -              {0x1a, 0x0181304f},
 -              {0x1b, 0x0221401f},
 -              {0x1e, 0x01456130}),
 -      SND_HDA_PIN_QUIRK(0x10ec1220, 0x1462, "MS-7C35", ALC1220_FIXUP_CLEVO_P950,
 -              {0x14, 0x01015010},
 -              {0x15, 0x01011012},
 -              {0x16, 0x01011011},
 -              {0x18, 0x01a11040},
 -              {0x19, 0x02a19050},
 -              {0x1a, 0x0181104f},
 -              {0x1b, 0x0221401f},
 -              {0x1e, 0x01451130}),
 -      {}
 -};
 -
 -/*
 - * BIOS auto configuration
 - */
 -/* almost identical with ALC880 parser... */
 -static int alc882_parse_auto_config(struct hda_codec *codec)
 +static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
 +                                 const struct hda_fixup *fix, int action)
  {
 -      static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
 -      static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
 -      return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
 +      struct alc_spec *spec = codec->spec;
 +
 +      alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->cap_mute_led_nid = 0x18;
 +              snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
 +              codec->power_filter = led_power_filter;
 +      }
  }
  
 -/*
 +/* HP Spectre x360 14 model needs a unique workaround for enabling the amp;
 + * it needs to toggle the GPIO0 once on and off at each time (bko#210633)
   */
 -static int patch_alc882(struct hda_codec *codec)
 +static void alc245_fixup_hp_x360_amp(struct hda_codec *codec,
 +                                   const struct hda_fixup *fix, int action)
  {
 -      struct alc_spec *spec;
 -      int err;
 -
 -      err = alc_alloc_spec(codec, 0x0b);
 -      if (err < 0)
 -              return err;
 -
 -      spec = codec->spec;
 +      struct alc_spec *spec = codec->spec;
  
 -      switch (codec->core.vendor_id) {
 -      case 0x10ec0882:
 -      case 0x10ec0885:
 -      case 0x10ec0900:
 -      case 0x10ec0b00:
 -      case 0x10ec1220:
 +      switch (action) {
 +      case HDA_FIXUP_ACT_PRE_PROBE:
 +              spec->gpio_mask |= 0x01;
 +              spec->gpio_dir |= 0x01;
                break;
 -      default:
 -              /* ALC883 and variants */
 -              alc_fix_pll_init(codec, 0x20, 0x0a, 10);
 +      case HDA_FIXUP_ACT_INIT:
 +              /* need to toggle GPIO to enable the amp */
 +              alc_update_gpio_data(codec, 0x01, true);
 +              msleep(100);
 +              alc_update_gpio_data(codec, 0x01, false);
                break;
        }
 +}
  
 -      alc_pre_init(codec);
 -
 -      snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
 -                     alc882_fixups);
 -      snd_hda_pick_pin_fixup(codec, alc882_pin_fixup_tbl, alc882_fixups, true);
 -      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 = alc882_parse_auto_config(codec);
 -      if (err < 0)
 -              goto error;
 -
 -      if (!spec->gen.no_analog && spec->gen.beep_nid) {
 -              err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 -              if (err < 0)
 -                      goto error;
 +/* toggle GPIO2 at each time stream is started; we use PREPARE state instead */
 +static void alc274_hp_envy_pcm_hook(struct hda_pcm_stream *hinfo,
 +                                  struct hda_codec *codec,
 +                                  struct snd_pcm_substream *substream,
 +                                  int action)
 +{
 +      switch (action) {
 +      case HDA_GEN_PCM_ACT_PREPARE:
 +              alc_update_gpio_data(codec, 0x04, true);
 +              break;
 +      case HDA_GEN_PCM_ACT_CLEANUP:
 +              alc_update_gpio_data(codec, 0x04, false);
 +              break;
        }
 -
 -      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 -
 -      return 0;
 -
 - error:
 -      alc_free(codec);
 -      return err;
  }
  
 -
 -/*
 - * ALC262 support
 - */
 -static int alc262_parse_auto_config(struct hda_codec *codec)
 +static void alc274_fixup_hp_envy_gpio(struct hda_codec *codec,
 +                                    const struct hda_fixup *fix,
 +                                    int action)
  {
 -      static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
 -      static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
 -      return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
 -}
 +      struct alc_spec *spec = codec->spec;
  
 -/*
 - * Pin config fixes
 - */
 -enum {
 -      ALC262_FIXUP_FSC_H270,
 -      ALC262_FIXUP_FSC_S7110,
 -      ALC262_FIXUP_HP_Z200,
 -      ALC262_FIXUP_TYAN,
 -      ALC262_FIXUP_LENOVO_3000,
 -      ALC262_FIXUP_BENQ,
 -      ALC262_FIXUP_BENQ_T31,
 -      ALC262_FIXUP_INV_DMIC,
 -      ALC262_FIXUP_INTEL_BAYLEYBAY,
 -};
 +      if (action == HDA_FIXUP_ACT_PROBE) {
 +              spec->gpio_mask |= 0x04;
 +              spec->gpio_dir |= 0x04;
 +              spec->gen.pcm_playback_hook = alc274_hp_envy_pcm_hook;
 +      }
 +}
  
 -static const struct hda_fixup alc262_fixups[] = {
 -      [ALC262_FIXUP_FSC_H270] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x14, 0x99130110 }, /* speaker */
 -                      { 0x15, 0x0221142f }, /* front HP */
 -                      { 0x1b, 0x0121141f }, /* rear HP */
 -                      { }
 -              }
 -      },
 -      [ALC262_FIXUP_FSC_S7110] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x15, 0x90170110 }, /* speaker */
 -                      { }
 -              },
 -              .chained = true,
 -              .chain_id = ALC262_FIXUP_BENQ,
 -      },
 -      [ALC262_FIXUP_HP_Z200] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x16, 0x99130120 }, /* internal speaker */
 -                      { }
 -              }
 -      },
 -      [ALC262_FIXUP_TYAN] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x14, 0x1993e1f0 }, /* int AUX */
 -                      { }
 -              }
 -      },
 -      [ALC262_FIXUP_LENOVO_3000] = {
 -              .type = HDA_FIXUP_PINCTLS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x19, PIN_VREF50 },
 -                      {}
 -              },
 -              .chained = true,
 -              .chain_id = ALC262_FIXUP_BENQ,
 -      },
 -      [ALC262_FIXUP_BENQ] = {
 -              .type = HDA_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 = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
 -                      { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
 -                      {}
 -              }
 -      },
 -      [ALC262_FIXUP_INV_DMIC] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_inv_dmic,
 -      },
 -      [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_no_depop_delay,
 -      },
 -};
 +static void alc_update_coef_led(struct hda_codec *codec,
 +                              struct alc_coef_led *led,
 +                              bool polarity, bool on)
 +{
 +      if (polarity)
 +              on = !on;
 +      /* temporarily power up/down for setting COEF bit */
 +      alc_update_coef_idx(codec, led->idx, led->mask,
 +                          on ? led->on : led->off);
 +}
  
 -static const struct hda_quirk alc262_fixup_tbl[] = {
 -      SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
 -      SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
 -      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, 0x1141, "FSC ESPRIMO U9210", ALC262_FIXUP_FSC_H270),
 -      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),
 -      SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
 -      {}
 -};
 +/* update mute-LED according to the speaker mute state via COEF bit */
 +static int coef_mute_led_set(struct led_classdev *led_cdev,
 +                           enum led_brightness brightness)
 +{
 +      struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 +      struct alc_spec *spec = codec->spec;
  
 -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"},
 -      {}
 -};
 +      alc_update_coef_led(codec, &spec->mute_led_coef,
 +                          spec->mute_led_polarity, brightness);
 +      return 0;
 +}
  
 -/*
 - */
 -static int patch_alc262(struct hda_codec *codec)
 +static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 +                                        const struct hda_fixup *fix,
 +                                        int action)
  {
 -      struct alc_spec *spec;
 -      int err;
 -
 -      err = alc_alloc_spec(codec, 0x0b);
 -      if (err < 0)
 -              return err;
 +      struct alc_spec *spec = codec->spec;
  
 -      spec = codec->spec;
 -      spec->gen.shared_mic_vref_pin = 0x18;
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mute_led_polarity = 0;
 +              spec->mute_led_coef.idx = 0x0b;
 +              spec->mute_led_coef.mask = 1 << 3;
 +              spec->mute_led_coef.on = 1 << 3;
 +              spec->mute_led_coef.off = 0;
 +              snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 +      }
 +}
  
 -      spec->shutup = alc_eapd_shutup;
 +static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 +                                        const struct hda_fixup *fix,
 +                                        int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -#if 0
 -      /* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
 -       * under-run
 -       */
 -      alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x80);
 -#endif
 -      alc_fix_pll_init(codec, 0x20, 0x0a, 10);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mute_led_polarity = 0;
 +              spec->mute_led_coef.idx = 0x34;
 +              spec->mute_led_coef.mask = 1 << 5;
 +              spec->mute_led_coef.on = 0;
 +              spec->mute_led_coef.off = 1 << 5;
 +              snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 +      }
 +}
  
 -      alc_pre_init(codec);
 +static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec,
 +                                        const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
 -                     alc262_fixups);
 -      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mute_led_polarity = 0;
 +              spec->mute_led_coef.idx = 0x07;
 +              spec->mute_led_coef.mask = 1;
 +              spec->mute_led_coef.on = 1;
 +              spec->mute_led_coef.off = 0;
 +              snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 +      }
 +}
  
 -      alc_auto_parse_customize_define(codec);
 +static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 +                                        const struct hda_fixup *fix,
 +                                        int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      if (has_cdefine_beep(codec))
 -              spec->gen.beep_nid = 0x01;
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mute_led_polarity = 0;
 +              spec->mute_led_coef.idx = 0x0b;
 +              spec->mute_led_coef.mask = 3 << 2;
 +              spec->mute_led_coef.on = 2 << 2;
 +              spec->mute_led_coef.off = 1 << 2;
 +              snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 +      }
 +}
  
 -      /* automatic parse from the BIOS config */
 -      err = alc262_parse_auto_config(codec);
 -      if (err < 0)
 -              goto error;
 +static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec,
 +                                        const struct hda_fixup *fix,
 +                                        int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      if (!spec->gen.no_analog && spec->gen.beep_nid) {
 -              err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 -              if (err < 0)
 -                      goto error;
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mute_led_polarity = 0;
 +              spec->mute_led_coef.idx = 0x0b;
-               spec->mute_led_coef.mask = 1 << 3;
++              spec->mute_led_coef.mask = 3 << 2;
 +              spec->mute_led_coef.on = 1 << 3;
 +              spec->mute_led_coef.off = 0;
 +              snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
        }
 +}
  
 -      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 +/* turn on/off mic-mute LED per capture hook by coef bit */
 +static int coef_micmute_led_set(struct led_classdev *led_cdev,
 +                              enum led_brightness brightness)
 +{
 +      struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 +      struct alc_spec *spec = codec->spec;
  
 +      alc_update_coef_led(codec, &spec->mic_led_coef,
 +                          spec->micmute_led_polarity, brightness);
        return 0;
 -
 - error:
 -      alc_free(codec);
 -      return err;
  }
  
 -/*
 - *  ALC268
 - */
 -/* bind Beep switches of both NID 0x0f and 0x10 */
 -static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol,
 -                                struct snd_ctl_elem_value *ucontrol)
 +static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 -      unsigned long pval;
 -      int err;
 +      struct alc_spec *spec = codec->spec;
  
 -      mutex_lock(&codec->control_mutex);
 -      pval = kcontrol->private_value;
 -      kcontrol->private_value = (pval & ~0xff) | 0x0f;
 -      err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
 -      if (err >= 0) {
 -              kcontrol->private_value = (pval & ~0xff) | 0x10;
 -              err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mic_led_coef.idx = 0x19;
 +              spec->mic_led_coef.mask = 1 << 13;
 +              spec->mic_led_coef.on = 1 << 13;
 +              spec->mic_led_coef.off = 0;
 +              snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
        }
 -      kcontrol->private_value = pval;
 -      mutex_unlock(&codec->control_mutex);
 -      return err;
  }
  
 -static const struct snd_kcontrol_new alc268_beep_mixer[] = {
 -      HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
 -      {
 -              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 -              .name = "Beep Playback Switch",
 -              .subdevice = HDA_SUBDEV_AMP_FLAG,
 -              .info = snd_hda_mixer_amp_switch_info,
 -              .get = snd_hda_mixer_amp_switch_get,
 -              .put = alc268_beep_switch_put,
 -              .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT)
 -      },
 -};
 +static void alc285_fixup_hp_gpio_micmute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -/* set PCBEEP vol = 0, mute connections */
 -static const struct hda_verb alc268_beep_init_verbs[] = {
 -      {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 -      {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 -      { }
 -};
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              spec->micmute_led_polarity = 1;
 +      alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
 +}
  
 -enum {
 -      ALC268_FIXUP_INV_DMIC,
 -      ALC268_FIXUP_HP_EAPD,
 -      ALC268_FIXUP_SPDIF,
 -};
 +static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -static const struct hda_fixup alc268_fixups[] = {
 -      [ALC268_FIXUP_INV_DMIC] = {
 -              .type = HDA_FIXUP_FUNC,
 -              .v.func = alc_fixup_inv_dmic,
 -      },
 -      [ALC268_FIXUP_HP_EAPD] = {
 -              .type = HDA_FIXUP_VERBS,
 -              .v.verbs = (const struct hda_verb[]) {
 -                      {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
 -                      {}
 -              }
 -      },
 -      [ALC268_FIXUP_SPDIF] = {
 -              .type = HDA_FIXUP_PINS,
 -              .v.pins = (const struct hda_pintbl[]) {
 -                      { 0x1e, 0x014b1180 }, /* enable SPDIF out */
 -                      {}
 -              }
 -      },
 -};
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mic_led_coef.idx = 0x35;
 +              spec->mic_led_coef.mask = 3 << 2;
 +              spec->mic_led_coef.on = 2 << 2;
 +              spec->mic_led_coef.off = 1 << 2;
 +              snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
 +      }
 +}
  
 -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"},
 -      {}
 -};
 +static void alc295_fixup_hp_mute_led_coefbit11(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -static const struct hda_quirk alc268_fixup_tbl[] = {
 -      SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
 -      SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
 -      /* below is codec SSID since multiple Toshiba laptops have the
 -       * same PCI SSID 1179:ff00
 -       */
 -      SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
 -      {}
 -};
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->mute_led_polarity = 0;
 +              spec->mute_led_coef.idx = 0xb;
 +              spec->mute_led_coef.mask = 3 << 3;
 +              spec->mute_led_coef.on = 1 << 3;
 +              spec->mute_led_coef.off = 1 << 4;
 +              snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 +      }
 +}
  
 -/*
 - * BIOS auto configuration
 - */
 -static int alc268_parse_auto_config(struct hda_codec *codec)
 +static void alc285_fixup_hp_mute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
 -      return alc_parse_auto_config(codec, NULL, alc268_ssids);
 +      alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
 +      alc285_fixup_hp_coef_micmute_led(codec, fix, action);
  }
  
 -/*
 - */
 -static int patch_alc268(struct hda_codec *codec)
 -{
 -      struct alc_spec *spec;
 -      int i, err;
 -
 -      /* ALC268 has no aa-loopback mixer */
 -      err = alc_alloc_spec(codec, 0);
 -      if (err < 0)
 -              return err;
 +static void alc285_fixup_hp_spectre_x360_mute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
 +      alc285_fixup_hp_gpio_micmute_led(codec, fix, action);
 +}
  
 -      spec = codec->spec;
 -      if (has_cdefine_beep(codec))
 -              spec->gen.beep_nid = 0x01;
 +static void alc236_fixup_hp_mute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc236_fixup_hp_mute_led_coefbit(codec, fix, action);
 +      alc236_fixup_hp_coef_micmute_led(codec, fix, action);
 +}
  
 -      spec->shutup = alc_eapd_shutup;
 +static void alc236_fixup_hp_micmute_led_vref(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      alc_pre_init(codec);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->cap_mute_led_nid = 0x1a;
 +              snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
 +              codec->power_filter = led_power_filter;
 +      }
 +}
  
 -      snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
 -      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 +static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      alc236_fixup_hp_mute_led_coefbit(codec, fix, action);
 +      alc236_fixup_hp_micmute_led_vref(codec, fix, action);
 +}
  
 -      /* automatic parse from the BIOS config */
 -      err = alc268_parse_auto_config(codec);
 -      if (err < 0)
 -              goto error;
 +static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
 +                                                const unsigned short coefs[2])
 +{
 +      alc_write_coef_idx(codec, 0x23, coefs[0]);
 +      alc_write_coef_idx(codec, 0x25, coefs[1]);
 +      alc_write_coef_idx(codec, 0x26, 0xb011);
 +}
  
 -      if (err > 0 && !spec->gen.no_analog &&
 -          spec->gen.autocfg.speaker_pins[0] != 0x1d) {
 -              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 */
 -                      snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
 -                                        (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
 -                                        (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
 -                                        (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
 -                                        (0 << AC_AMPCAP_MUTE_SHIFT));
 -      }
 +struct alc298_samsung_amp_desc {
 +      unsigned char nid;
 +      unsigned short init_seq[2][2];
 +};
  
 -      snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 +static void alc298_fixup_samsung_amp(struct hda_codec *codec,
 +                                   const struct hda_fixup *fix, int action)
 +{
 +      int i, j;
 +      static const unsigned short init_seq[][2] = {
 +              { 0x19, 0x00 }, { 0x20, 0xc0 }, { 0x22, 0x44 }, { 0x23, 0x08 },
 +              { 0x24, 0x85 }, { 0x25, 0x41 }, { 0x35, 0x40 }, { 0x36, 0x01 },
 +              { 0x38, 0x81 }, { 0x3a, 0x03 }, { 0x3b, 0x81 }, { 0x40, 0x3e },
 +              { 0x41, 0x07 }, { 0x400, 0x1 }
 +      };
 +      static const struct alc298_samsung_amp_desc amps[] = {
 +              { 0x3a, { { 0x18, 0x1 }, { 0x26, 0x0 } } },
 +              { 0x39, { { 0x18, 0x2 }, { 0x26, 0x1 } } }
 +      };
  
 -      return 0;
 +      if (action != HDA_FIXUP_ACT_INIT)
 +              return;
  
 - error:
 -      alc_free(codec);
 -      return err;
 -}
 +      for (i = 0; i < ARRAY_SIZE(amps); i++) {
 +              alc_write_coef_idx(codec, 0x22, amps[i].nid);
  
 -/*
 - * ALC269
 - */
 +              for (j = 0; j < ARRAY_SIZE(amps[i].init_seq); j++)
 +                      alc298_samsung_write_coef_pack(codec, amps[i].init_seq[j]);
  
 -static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
 -      .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
 -};
 +              for (j = 0; j < ARRAY_SIZE(init_seq); j++)
 +                      alc298_samsung_write_coef_pack(codec, init_seq[j]);
 +      }
 +}
  
 -static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
 -      .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
 +struct alc298_samsung_v2_amp_desc {
 +      unsigned short nid;
 +      int init_seq_size;
 +      unsigned short init_seq[18][2];
  };
  
 -/* different alc269-variants */
 -enum {
 -      ALC269_TYPE_ALC269VA,
 -      ALC269_TYPE_ALC269VB,
 -      ALC269_TYPE_ALC269VC,
 -      ALC269_TYPE_ALC269VD,
 -      ALC269_TYPE_ALC280,
 -      ALC269_TYPE_ALC282,
 -      ALC269_TYPE_ALC283,
 -      ALC269_TYPE_ALC284,
 -      ALC269_TYPE_ALC293,
 -      ALC269_TYPE_ALC286,
 -      ALC269_TYPE_ALC298,
 -      ALC269_TYPE_ALC255,
 -      ALC269_TYPE_ALC256,
 -      ALC269_TYPE_ALC257,
 -      ALC269_TYPE_ALC215,
 -      ALC269_TYPE_ALC225,
 -      ALC269_TYPE_ALC245,
 -      ALC269_TYPE_ALC287,
 -      ALC269_TYPE_ALC294,
 -      ALC269_TYPE_ALC300,
 -      ALC269_TYPE_ALC623,
 -      ALC269_TYPE_ALC700,
 +static const struct alc298_samsung_v2_amp_desc
 +alc298_samsung_v2_amp_desc_tbl[] = {
 +      { 0x38, 18, {
 +              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
 +              { 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
 +              { 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
 +              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
 +              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
 +              { 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
 +      }},
 +      { 0x39, 18, {
 +              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
 +              { 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
 +              { 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
 +              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
 +              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x2399, 0x0003 },
 +              { 0x23a4, 0x00b5 }, { 0x23a5, 0x0001 }, { 0x23ba, 0x0094 }
 +      }},
 +      { 0x3c, 15, {
 +              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
 +              { 0x201b, 0x0001 }, { 0x201d, 0x0001 }, { 0x201f, 0x00fe },
 +              { 0x2021, 0x0000 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
 +              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
 +              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
 +      }},
 +      { 0x3d, 15, {
 +              { 0x23e1, 0x0000 }, { 0x2012, 0x006f }, { 0x2014, 0x0000 },
 +              { 0x201b, 0x0002 }, { 0x201d, 0x0002 }, { 0x201f, 0x00fd },
 +              { 0x2021, 0x0001 }, { 0x2022, 0x0010 }, { 0x203d, 0x0005 },
 +              { 0x203f, 0x0003 }, { 0x2050, 0x002c }, { 0x2076, 0x000e },
 +              { 0x207c, 0x004a }, { 0x2081, 0x0003 }, { 0x23ba, 0x008d }
 +      }}
  };
  
 -/*
 - * BIOS auto configuration
 - */
 -static int alc269_parse_auto_config(struct hda_codec *codec)
 +static void alc298_samsung_v2_enable_amps(struct hda_codec *codec)
  {
 -      static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
 -      static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
 -      static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
        struct alc_spec *spec = codec->spec;
 -      const hda_nid_t *ssids;
 +      static const unsigned short enable_seq[][2] = {
 +              { 0x203a, 0x0081 }, { 0x23ff, 0x0001 },
 +      };
 +      int i, j;
  
 -      switch (spec->codec_variant) {
 -      case ALC269_TYPE_ALC269VA:
 -      case ALC269_TYPE_ALC269VC:
 -      case ALC269_TYPE_ALC280:
 -      case ALC269_TYPE_ALC284:
 -      case ALC269_TYPE_ALC293:
 -              ssids = alc269va_ssids;
 -              break;
 -      case ALC269_TYPE_ALC269VB:
 -      case ALC269_TYPE_ALC269VD:
 -      case ALC269_TYPE_ALC282:
 -      case ALC269_TYPE_ALC283:
 -      case ALC269_TYPE_ALC286:
 -      case ALC269_TYPE_ALC298:
 -      case ALC269_TYPE_ALC255:
 -      case ALC269_TYPE_ALC256:
 -      case ALC269_TYPE_ALC257:
 -      case ALC269_TYPE_ALC215:
 -      case ALC269_TYPE_ALC225:
 -      case ALC269_TYPE_ALC245:
 -      case ALC269_TYPE_ALC287:
 -      case ALC269_TYPE_ALC294:
 -      case ALC269_TYPE_ALC300:
 -      case ALC269_TYPE_ALC623:
 -      case ALC269_TYPE_ALC700:
 -              ssids = alc269_ssids;
 -              break;
 -      default:
 -              ssids = alc269_ssids;
 -              break;
 +      for (i = 0; i < spec->num_speaker_amps; i++) {
 +              alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
 +              for (j = 0; j < ARRAY_SIZE(enable_seq); j++)
 +                      alc298_samsung_write_coef_pack(codec, enable_seq[j]);
 +              codec_dbg(codec, "alc298_samsung_v2: Enabled speaker amp 0x%02x\n",
 +                              alc298_samsung_v2_amp_desc_tbl[i].nid);
        }
 -
 -      return alc_parse_auto_config(codec, alc269_ignore, ssids);
  }
  
 -static const struct hda_jack_keymap alc_headset_btn_keymap[] = {
 -      { SND_JACK_BTN_0, KEY_PLAYPAUSE },
 -      { SND_JACK_BTN_1, KEY_VOICECOMMAND },
 -      { SND_JACK_BTN_2, KEY_VOLUMEUP },
 -      { SND_JACK_BTN_3, KEY_VOLUMEDOWN },
 -      {}
 -};
 -
 -static void alc_headset_btn_callback(struct hda_codec *codec,
 -                                   struct hda_jack_callback *jack)
 +static void alc298_samsung_v2_disable_amps(struct hda_codec *codec)
  {
 -      int report = 0;
 -
 -      if (jack->unsol_res & (7 << 13))
 -              report |= SND_JACK_BTN_0;
 -
 -      if (jack->unsol_res  & (1 << 16 | 3 << 8))
 -              report |= SND_JACK_BTN_1;
 -
 -      /* Volume up key */
 -      if (jack->unsol_res & (7 << 23))
 -              report |= SND_JACK_BTN_2;
 +      struct alc_spec *spec = codec->spec;
 +      static const unsigned short disable_seq[][2] = {
 +              { 0x23ff, 0x0000 }, { 0x203a, 0x0080 },
 +      };
 +      int i, j;
  
 -      /* Volume down key */
 -      if (jack->unsol_res & (7 << 10))
 -              report |= SND_JACK_BTN_3;
 +      for (i = 0; i < spec->num_speaker_amps; i++) {
 +              alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
 +              for (j = 0; j < ARRAY_SIZE(disable_seq); j++)
 +                      alc298_samsung_write_coef_pack(codec, disable_seq[j]);
 +              codec_dbg(codec, "alc298_samsung_v2: Disabled speaker amp 0x%02x\n",
 +                              alc298_samsung_v2_amp_desc_tbl[i].nid);
 +      }
 +}
  
 -      snd_hda_jack_set_button_state(codec, jack->nid, report);
 +static void alc298_samsung_v2_playback_hook(struct hda_pcm_stream *hinfo,
 +                              struct hda_codec *codec,
 +                              struct snd_pcm_substream *substream,
 +                              int action)
 +{
 +      /* Dynamically enable/disable speaker amps before and after playback */
 +      if (action == HDA_GEN_PCM_ACT_OPEN)
 +              alc298_samsung_v2_enable_amps(codec);
 +      if (action == HDA_GEN_PCM_ACT_CLOSE)
 +              alc298_samsung_v2_disable_amps(codec);
  }
  
 -static void alc_disable_headset_jack_key(struct hda_codec *codec)
 +static void alc298_samsung_v2_init_amps(struct hda_codec *codec,
 +                              int num_speaker_amps)
  {
        struct alc_spec *spec = codec->spec;
 +      int i, j;
  
 -      if (!spec->has_hs_key)
 -              return;
 +      /* Set spec's num_speaker_amps before doing anything else */
 +      spec->num_speaker_amps = num_speaker_amps;
  
 -      switch (codec->core.vendor_id) {
 -      case 0x10ec0215:
 -      case 0x10ec0225:
 -      case 0x10ec0285:
 -      case 0x10ec0287:
 -      case 0x10ec0295:
 -      case 0x10ec0289:
 -      case 0x10ec0299:
 -              alc_write_coef_idx(codec, 0x48, 0x0);
 -              alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
 -              alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0);
 -              break;
 -      case 0x10ec0230:
 -      case 0x10ec0236:
 -      case 0x10ec0256:
 -      case 0x10ec0257:
 -      case 0x19e58326:
 -              alc_write_coef_idx(codec, 0x48, 0x0);
 -              alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
 -              break;
 +      /* Disable speaker amps before init to prevent any physical damage */
 +      alc298_samsung_v2_disable_amps(codec);
 +
 +      /* Initialize the speaker amps */
 +      for (i = 0; i < spec->num_speaker_amps; i++) {
 +              alc_write_coef_idx(codec, 0x22, alc298_samsung_v2_amp_desc_tbl[i].nid);
 +              for (j = 0; j < alc298_samsung_v2_amp_desc_tbl[i].init_seq_size; j++) {
 +                      alc298_samsung_write_coef_pack(codec,
 +                                      alc298_samsung_v2_amp_desc_tbl[i].init_seq[j]);
 +              }
 +              alc_write_coef_idx(codec, 0x89, 0x0);
 +              codec_dbg(codec, "alc298_samsung_v2: Initialized speaker amp 0x%02x\n",
 +                              alc298_samsung_v2_amp_desc_tbl[i].nid);
        }
 +
 +      /* register hook to enable speaker amps only when they are needed */
 +      spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook;
  }
  
 -static void alc_enable_headset_jack_key(struct hda_codec *codec)
 +static void alc298_fixup_samsung_amp_v2_2_amps(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      struct alc_spec *spec = codec->spec;
 -
 -      if (!spec->has_hs_key)
 -              return;
 -
 -      switch (codec->core.vendor_id) {
 -      case 0x10ec0215:
 -      case 0x10ec0225:
 -      case 0x10ec0285:
 -      case 0x10ec0287:
 -      case 0x10ec0295:
 -      case 0x10ec0289:
 -      case 0x10ec0299:
 -              alc_write_coef_idx(codec, 0x48, 0xd011);
 -              alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
 -              alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
 -              break;
 -      case 0x10ec0230:
 -      case 0x10ec0236:
 -      case 0x10ec0256:
 -      case 0x10ec0257:
 -      case 0x19e58326:
 -              alc_write_coef_idx(codec, 0x48, 0xd011);
 -              alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
 -              break;
 -      }
 +      if (action == HDA_FIXUP_ACT_PROBE)
 +              alc298_samsung_v2_init_amps(codec, 2);
  }
  
 -static void alc_fixup_headset_jack(struct hda_codec *codec,
 -                                  const struct hda_fixup *fix, int action)
 +static void alc298_fixup_samsung_amp_v2_4_amps(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin;
 -
 -      switch (action) {
 -      case HDA_FIXUP_ACT_PRE_PROBE:
 -              spec->has_hs_key = 1;
 -              snd_hda_jack_detect_enable_callback(codec, 0x55,
 -                                                  alc_headset_btn_callback);
 -              break;
 -      case HDA_FIXUP_ACT_BUILD:
 -              hp_pin = alc_get_hp_pin(spec);
 -              if (!hp_pin || snd_hda_jack_bind_keymap(codec, 0x55,
 -                                                      alc_headset_btn_keymap,
 -                                                      hp_pin))
 -                      snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack",
 -                                            false, SND_JACK_HEADSET,
 -                                            alc_headset_btn_keymap);
 -
 -              alc_enable_headset_jack_key(codec);
 -              break;
 -      }
 +      if (action == HDA_FIXUP_ACT_PROBE)
 +              alc298_samsung_v2_init_amps(codec, 4);
  }
  
 -static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
 +static void gpio2_mic_hotkey_event(struct hda_codec *codec,
 +                                 struct hda_jack_callback *event)
  {
 -      alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0);
 +      struct alc_spec *spec = codec->spec;
 +
 +      /* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore
 +         send both key on and key off event for every interrupt. */
 +      input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 1);
 +      input_sync(spec->kb_dev);
 +      input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 0);
 +      input_sync(spec->kb_dev);
  }
  
 -static void alc269_shutup(struct hda_codec *codec)
 +static int alc_register_micmute_input_device(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 +      int i;
  
 -      if (spec->codec_variant == ALC269_TYPE_ALC269VB)
 -              alc269vb_toggle_power_output(codec, 0);
 -      if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
 -                      (alc_get_coef0(codec) & 0x00ff) == 0x018) {
 -              msleep(150);
 +      spec->kb_dev = input_allocate_device();
 +      if (!spec->kb_dev) {
 +              codec_err(codec, "Out of memory (input_allocate_device)\n");
 +              return -ENOMEM;
        }
 -      alc_shutup_pins(codec);
 -}
  
 -static const struct coef_fw alc282_coefs[] = {
 -      WRITE_COEF(0x03, 0x0002), /* Power Down Control */
 -      UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
 -      WRITE_COEF(0x07, 0x0200), /* DMIC control */
 -      UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
 -      UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
 -      WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */
 -      WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */
 -      WRITE_COEF(0x0e, 0x6e00), /* LDO1/2/3, DAC/ADC */
 -      UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */
 -      UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */
 -      WRITE_COEF(0x6f, 0x0), /* Class D test 4 */
 -      UPDATE_COEF(0x0c, 0xfe00, 0), /* IO power down directly */
 -      WRITE_COEF(0x34, 0xa0c0), /* ANC */
 -      UPDATE_COEF(0x16, 0x0008, 0), /* AGC MUX */
 -      UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */
 -      UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */
 -      WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */
 -      WRITE_COEF(0x63, 0x2902), /* PLL */
 -      WRITE_COEF(0x68, 0xa080), /* capless control 2 */
 -      WRITE_COEF(0x69, 0x3400), /* capless control 3 */
 -      WRITE_COEF(0x6a, 0x2f3e), /* capless control 4 */
 -      WRITE_COEF(0x6b, 0x0), /* capless control 5 */
 -      UPDATE_COEF(0x6d, 0x0fff, 0x0900), /* class D test 2 */
 -      WRITE_COEF(0x6e, 0x110a), /* class D test 3 */
 -      UPDATE_COEF(0x70, 0x00f8, 0x00d8), /* class D test 5 */
 -      WRITE_COEF(0x71, 0x0014), /* class D test 6 */
 -      WRITE_COEF(0x72, 0xc2ba), /* classD OCP */
 -      UPDATE_COEF(0x77, 0x0f80, 0), /* classD pure DC test */
 -      WRITE_COEF(0x6c, 0xfc06), /* Class D amp control */
 -      {}
 -};
 +      spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX] = KEY_MICMUTE;
  
 -static void alc282_restore_default_value(struct hda_codec *codec)
 -{
 -      alc_process_coef_fw(codec, alc282_coefs);
 +      spec->kb_dev->name = "Microphone Mute Button";
 +      spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
 +      spec->kb_dev->keycodesize = sizeof(spec->alc_mute_keycode_map[0]);
 +      spec->kb_dev->keycodemax = ARRAY_SIZE(spec->alc_mute_keycode_map);
 +      spec->kb_dev->keycode = spec->alc_mute_keycode_map;
 +      for (i = 0; i < ARRAY_SIZE(spec->alc_mute_keycode_map); i++)
 +              set_bit(spec->alc_mute_keycode_map[i], spec->kb_dev->keybit);
 +
 +      if (input_register_device(spec->kb_dev)) {
 +              codec_err(codec, "input_register_device failed\n");
 +              input_free_device(spec->kb_dev);
 +              spec->kb_dev = NULL;
 +              return -ENOMEM;
 +      }
 +
 +      return 0;
  }
  
 -static void alc282_init(struct hda_codec *codec)
 +/* 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)
  {
        struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin = alc_get_hp_pin(spec);
 -      bool hp_pin_sense;
 -      int coef78;
  
 -      alc282_restore_default_value(codec);
 +      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;
  
 -      if (!hp_pin)
 +              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);
                return;
 -      hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 -      coef78 = alc_read_coef_idx(codec, 0x78);
 +      }
  
 -      /* Index 0x78 Direct Drive HP AMP LPM Control 1 */
 -      /* Headphone capless set to high power mode */
 -      alc_write_coef_idx(codec, 0x78, 0x9004);
 +      if (!spec->kb_dev)
 +              return;
  
 -      if (hp_pin_sense)
 -              msleep(2);
 +      switch (action) {
 +      case HDA_FIXUP_ACT_FREE:
 +              input_unregister_device(spec->kb_dev);
 +              spec->kb_dev = NULL;
 +      }
 +}
  
 -      snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 +/* 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)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      if (hp_pin_sense)
 -              msleep(85);
 +      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_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 +              snd_hda_jack_detect_enable_callback(codec, 0x1b,
 +                                                  gpio2_mic_hotkey_event);
 +              return;
 +      }
  
 -      if (hp_pin_sense)
 -              msleep(100);
 +      if (!spec->kb_dev)
 +              return;
  
 -      /* Headphone capless set to normal mode */
 -      alc_write_coef_idx(codec, 0x78, coef78);
 +      switch (action) {
 +      case HDA_FIXUP_ACT_FREE:
 +              input_unregister_device(spec->kb_dev);
 +              spec->kb_dev = NULL;
 +      }
  }
  
 -static void alc282_shutup(struct hda_codec *codec)
 +static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
        struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin = alc_get_hp_pin(spec);
 -      bool hp_pin_sense;
 -      int coef78;
  
 -      if (!hp_pin) {
 -              alc269_shutup(codec);
 -              return;
 +      alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->cap_mute_led_nid = 0x18;
 +              snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
        }
 +}
  
 -      hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 -      coef78 = alc_read_coef_idx(codec, 0x78);
 -      alc_write_coef_idx(codec, 0x78, 0x9004);
 +static void alc233_fixup_lenovo_low_en_micmute_led(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      if (hp_pin_sense)
 -              msleep(2);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              spec->micmute_led_polarity = 1;
 +      alc233_fixup_lenovo_line2_mic_hotkey(codec, fix, action);
 +}
  
 -      snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 +static void alc255_set_default_jack_type(struct hda_codec *codec)
 +{
 +      /* Set to iphone type */
 +      static const struct coef_fw alc255fw[] = {
 +              WRITE_COEF(0x1b, 0x880b),
 +              WRITE_COEF(0x45, 0xd089),
 +              WRITE_COEF(0x1b, 0x080b),
 +              WRITE_COEF(0x46, 0x0004),
 +              WRITE_COEF(0x1b, 0x0c0b),
 +              {}
 +      };
 +      static const struct coef_fw alc256fw[] = {
 +              WRITE_COEF(0x1b, 0x884b),
 +              WRITE_COEF(0x45, 0xd089),
 +              WRITE_COEF(0x1b, 0x084b),
 +              WRITE_COEF(0x46, 0x0004),
 +              WRITE_COEF(0x1b, 0x0c4b),
 +              {}
 +      };
 +      switch (codec->core.vendor_id) {
 +      case 0x10ec0255:
 +              alc_process_coef_fw(codec, alc255fw);
 +              break;
 +      case 0x10ec0230:
 +      case 0x10ec0236:
 +      case 0x10ec0256:
 +      case 0x19e58326:
 +              alc_process_coef_fw(codec, alc256fw);
 +              break;
 +      }
 +      msleep(30);
 +}
  
 -      if (hp_pin_sense)
 -              msleep(85);
 +static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              alc255_set_default_jack_type(codec);
 +      }
 +      alc_fixup_headset_mode(codec, fix, action);
 +}
  
 -      if (!spec->no_shutup_pins)
 -              snd_hda_codec_write(codec, hp_pin, 0,
 -                                  AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
 +static void alc_fixup_headset_mode_alc255_no_hp_mic(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              struct alc_spec *spec = codec->spec;
 +              spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
 +              alc255_set_default_jack_type(codec);
 +      }
 +      else
 +              alc_fixup_headset_mode(codec, fix, action);
 +}
  
 -      if (hp_pin_sense)
 -              msleep(100);
 +static void alc288_update_headset_jack_cb(struct hda_codec *codec,
 +                                     struct hda_jack_callback *jack)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -      alc_auto_setup_eapd(codec, false);
 -      alc_shutup_pins(codec);
 -      alc_write_coef_idx(codec, 0x78, coef78);
 +      alc_update_headset_jack_cb(codec, jack);
 +      /* Headset Mic enable or disable, only for Dell Dino */
 +      alc_update_gpio_data(codec, 0x40, spec->gen.hp_jack_present);
  }
  
 -static const struct coef_fw alc283_coefs[] = {
 -      WRITE_COEF(0x03, 0x0002), /* Power Down Control */
 -      UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
 -      WRITE_COEF(0x07, 0x0200), /* DMIC control */
 -      UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
 -      UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
 -      WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */
 -      WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */
 -      WRITE_COEF(0x0e, 0x6fc0), /* LDO1/2/3, DAC/ADC */
 -      UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */
 -      UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */
 -      WRITE_COEF(0x3a, 0x0), /* Class D test 4 */
 -      UPDATE_COEF(0x0c, 0xfe00, 0x0), /* IO power down directly */
 -      WRITE_COEF(0x22, 0xa0c0), /* ANC */
 -      UPDATE_COEFEX(0x53, 0x01, 0x000f, 0x0008), /* AGC MUX */
 -      UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */
 -      UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */
 -      WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */
 -      WRITE_COEF(0x2e, 0x2902), /* PLL */
 -      WRITE_COEF(0x33, 0xa080), /* capless control 2 */
 -      WRITE_COEF(0x34, 0x3400), /* capless control 3 */
 -      WRITE_COEF(0x35, 0x2f3e), /* capless control 4 */
 -      WRITE_COEF(0x36, 0x0), /* capless control 5 */
 -      UPDATE_COEF(0x38, 0x0fff, 0x0900), /* class D test 2 */
 -      WRITE_COEF(0x39, 0x110a), /* class D test 3 */
 -      UPDATE_COEF(0x3b, 0x00f8, 0x00d8), /* class D test 5 */
 -      WRITE_COEF(0x3c, 0x0014), /* class D test 6 */
 -      WRITE_COEF(0x3d, 0xc2ba), /* classD OCP */
 -      UPDATE_COEF(0x42, 0x0f80, 0x0), /* classD pure DC test */
 -      WRITE_COEF(0x49, 0x0), /* test mode */
 -      UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */
 -      UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */
 -      WRITE_COEF(0x37, 0xfc06), /* Class D amp control */
 -      UPDATE_COEF(0x1b, 0x8000, 0), /* HP JD control */
 -      {}
 -};
 +static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
 +{
 +      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;
 +      }
 +}
  
 -static void alc283_restore_default_value(struct hda_codec *codec)
 +static void alc_fixup_no_shutup(struct hda_codec *codec,
 +                              const struct hda_fixup *fix, int action)
  {
 -      alc_process_coef_fw(codec, alc283_coefs);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              struct alc_spec *spec = codec->spec;
 +              spec->no_shutup_pins = 1;
 +      }
  }
  
 -static void alc283_init(struct hda_codec *codec)
 +/* fixup for Thinkpad docks: add dock pins, avoid HP parser fixup */
 +static void alc_fixup_tpt440_dock(struct hda_codec *codec,
 +                                const struct hda_fixup *fix, int action)
  {
 +      static const struct hda_pintbl pincfgs[] = {
 +              { 0x16, 0x21211010 }, /* dock headphone */
 +              { 0x19, 0x21a11010 }, /* dock mic */
 +              { }
 +      };
        struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin = alc_get_hp_pin(spec);
 -      bool hp_pin_sense;
 -
 -      alc283_restore_default_value(codec);
  
 -      if (!hp_pin)
 -              return;
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
 +              codec->power_save_node = 0; /* avoid click noises */
 +              snd_hda_apply_pincfgs(codec, pincfgs);
 +      }
 +}
  
 -      msleep(30);
 -      hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 +static void alc_fixup_tpt470_dock(struct hda_codec *codec,
 +                                const struct hda_fixup *fix, int action)
 +{
 +      static const struct hda_pintbl pincfgs[] = {
 +              { 0x17, 0x21211010 }, /* dock headphone */
 +              { 0x19, 0x21a11010 }, /* dock mic */
 +              { }
 +      };
 +      struct alc_spec *spec = codec->spec;
  
 -      /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
 -      /* Headphone capless set to high power mode */
 -      alc_write_coef_idx(codec, 0x43, 0x9004);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
 +              snd_hda_apply_pincfgs(codec, pincfgs);
 +      } else if (action == HDA_FIXUP_ACT_INIT) {
 +              /* Enable DOCK device */
 +              snd_hda_codec_write(codec, 0x17, 0,
 +                          AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
 +              /* Enable DOCK device */
 +              snd_hda_codec_write(codec, 0x19, 0,
 +                          AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0);
 +      }
 +}
  
 -      snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 +static void alc_fixup_tpt470_dacs(struct hda_codec *codec,
 +                                const struct hda_fixup *fix, int action)
 +{
 +      /* Assure the speaker pin to be coupled with DAC NID 0x03; otherwise
 +       * the speaker output becomes too low by some reason on Thinkpads with
 +       * ALC298 codec
 +       */
 +      static const hda_nid_t preferred_pairs[] = {
 +              0x14, 0x03, 0x17, 0x02, 0x21, 0x02,
 +              0
 +      };
 +      struct alc_spec *spec = codec->spec;
  
 -      if (hp_pin_sense)
 -              msleep(85);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              spec->gen.preferred_dacs = preferred_pairs;
 +}
  
 -      snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 +static void alc295_fixup_asus_dacs(struct hda_codec *codec,
 +                                 const struct hda_fixup *fix, int action)
 +{
 +      static const hda_nid_t preferred_pairs[] = {
 +              0x17, 0x02, 0x21, 0x03, 0
 +      };
 +      struct alc_spec *spec = codec->spec;
  
 -      if (hp_pin_sense)
 -              msleep(85);
 -      /* Index 0x46 Combo jack auto switch control 2 */
 -      /* 3k pull low control for Headset jack. */
 -      alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
 -      /* Headphone capless set to normal mode */
 -      alc_write_coef_idx(codec, 0x43, 0x9614);
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE)
 +              spec->gen.preferred_dacs = preferred_pairs;
  }
  
 -static void alc283_shutup(struct hda_codec *codec)
 +static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 +                                  const struct hda_fixup *fix,
 +                                  int action)
  {
        struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin = alc_get_hp_pin(spec);
 -      bool hp_pin_sense;
  
 -      if (!hp_pin) {
 -              alc269_shutup(codec);
 -              return;
 -      }
 +      if (action == HDA_FIXUP_ACT_PROBE) {
 +              int mic_pin = alc_find_ext_mic_pin(codec);
 +              int hp_pin = alc_get_hp_pin(spec);
  
 -      hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 +              if (snd_BUG_ON(!mic_pin || !hp_pin))
 +                      return;
 +              snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
 +      }
 +}
  
 -      alc_write_coef_idx(codec, 0x43, 0x9004);
 +static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
 +                                           const struct hda_fixup *fix,
 +                                           int action)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      struct auto_pin_cfg *cfg = &spec->gen.autocfg;
 +      int i;
  
 -      /*depop hp during suspend*/
 -      alc_write_coef_idx(codec, 0x06, 0x2100);
 -
 -      snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 -
 -      if (hp_pin_sense)
 -              msleep(100);
 +      /* The mic boosts on level 2 and 3 are too noisy
 +         on the internal mic input.
 +         Therefore limit the boost to 0 or 1. */
  
 -      if (!spec->no_shutup_pins)
 -              snd_hda_codec_write(codec, hp_pin, 0,
 -                                  AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
 +      if (action != HDA_FIXUP_ACT_PROBE)
 +              return;
  
 -      alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
 +      for (i = 0; i < cfg->num_inputs; i++) {
 +              hda_nid_t nid = cfg->inputs[i].pin;
 +              unsigned int defcfg;
 +              if (cfg->inputs[i].type != AUTO_PIN_MIC)
 +                      continue;
 +              defcfg = snd_hda_codec_get_pincfg(codec, nid);
 +              if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
 +                      continue;
  
 -      if (hp_pin_sense)
 -              msleep(100);
 -      alc_auto_setup_eapd(codec, false);
 -      alc_shutup_pins(codec);
 -      alc_write_coef_idx(codec, 0x43, 0x9614);
 +              snd_hda_override_amp_caps(codec, nid, HDA_INPUT,
 +                                        (0x00 << AC_AMPCAP_OFFSET_SHIFT) |
 +                                        (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) |
 +                                        (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) |
 +                                        (0 << AC_AMPCAP_MUTE_SHIFT));
 +      }
  }
  
 -static void alc256_init(struct hda_codec *codec)
 +static void alc283_hp_automute_hook(struct hda_codec *codec,
 +                                  struct hda_jack_callback *jack)
  {
        struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin = alc_get_hp_pin(spec);
 -      bool hp_pin_sense;
 -
 -      if (spec->ultra_low_power) {
 -              alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1);
 -              alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2);
 -              alc_update_coef_idx(codec, 0x08, 7<<4, 0);
 -              alc_update_coef_idx(codec, 0x3b, 1<<15, 0);
 -              alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
 -              msleep(30);
 -      }
 -
 -      if (!hp_pin)
 -              hp_pin = 0x21;
 +      int vref;
  
 -      msleep(30);
 +      msleep(200);
 +      snd_hda_gen_hp_automute(codec, jack);
  
 -      hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 +      vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
  
 -      if (hp_pin_sense) {
 -              msleep(2);
 -              alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
 +      msleep(600);
 +      snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
 +                          vref);
 +}
  
 -              snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 +static void alc283_fixup_chromebook(struct hda_codec *codec,
 +                                  const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -              msleep(75);
 +      switch (action) {
 +      case HDA_FIXUP_ACT_PRE_PROBE:
 +              snd_hda_override_wcaps(codec, 0x03, 0);
 +              /* Disable AA-loopback as it causes white noise */
 +              spec->gen.mixer_nid = 0;
 +              break;
 +      case HDA_FIXUP_ACT_INIT:
 +              /* MIC2-VREF control */
 +              /* Set to manual mode */
 +              alc_update_coef_idx(codec, 0x06, 0x000c, 0);
 +              /* Enable Line1 input control by verb */
 +              alc_update_coef_idx(codec, 0x1a, 0, 1 << 4);
 +              break;
 +      }
 +}
  
 -              snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
 +static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
 +                                  const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
  
 -              msleep(75);
 -              alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
 +      switch (action) {
 +      case HDA_FIXUP_ACT_PRE_PROBE:
 +              spec->gen.hp_automute_hook = alc283_hp_automute_hook;
 +              break;
 +      case HDA_FIXUP_ACT_INIT:
 +              /* MIC2-VREF control */
 +              /* Set to manual mode */
 +              alc_update_coef_idx(codec, 0x06, 0x000c, 0);
 +              break;
        }
 -      alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
 -      alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */
 -      alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
 -      /*
 -       * Expose headphone mic (or possibly Line In on some machines) instead
 -       * of PC Beep on 1Ah, and disable 1Ah loopback for all outputs. See
 -       * Documentation/sound/hd-audio/realtek-pc-beep.rst for details of
 -       * this register.
 -       */
 -      alc_write_coef_idx(codec, 0x36, 0x5757);
  }
  
 -static void alc256_shutup(struct hda_codec *codec)
 +/* mute tablet speaker pin (0x14) via dock plugging in addition */
 +static void asus_tx300_automute(struct hda_codec *codec)
  {
        struct alc_spec *spec = codec->spec;
 -      hda_nid_t hp_pin = alc_get_hp_pin(spec);
 -      bool hp_pin_sense;
 -
 -      if (!hp_pin)
 -              hp_pin = 0x21;
 +      snd_hda_gen_update_outputs(codec);
 +      if (snd_hda_jack_detect(codec, 0x1b))
 +              spec->gen.mute_bits |= (1ULL << 0x14);
 +}
  
 -      alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
 -      hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 +static void alc282_fixup_asus_tx300(struct hda_codec *codec,
 +                                  const struct hda_fixup *fix, int action)
 +{
 +      struct alc_spec *spec = codec->spec;
 +      static const struct hda_pintbl dock_pins[] = {
 +              { 0x1b, 0x21114000 }, /* dock speaker pin */
 +              {}
 +      };
  
 -      if (hp_pin_sense) {
 -              msleep(2);
 +      switch (action) {
 +      case HDA_FIXUP_ACT_PRE_PROBE:
 +              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
 +               */
 +              rename_ctl(codec, "Speaker Playback Switch",
 +                         "Dock Speaker Playback Switch");
 +              rename_ctl(codec, "Bass Speaker Playback Switch",
 +                         "Speaker Playback Switch");
 +              break;
 +      }
 +}
  
 -              snd_hda_codec_write(codec, hp_pin, 0,
 -                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 +static void alc290_fixup_mono_speakers(struct hda_codec *codec,
 +                                     const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              /* DAC node 0x03 is giving mono output. We therefore want to
 +                 make sure 0x14 (front speaker) and 0x15 (headphones) use the
 +                 stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
 +              static const hda_nid_t conn1[] = { 0x0c };
 +              snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
 +              snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn1), conn1);
 +      }
 +}
  
 -              msleep(75);
 +static void alc298_fixup_speaker_volume(struct hda_codec *codec,
 +                                      const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              /* The speaker is routed to the Node 0x06 by a mistake, as a result
 +                 we can't adjust the speaker's volume since this node does not has
 +                 Amp-out capability. we change the speaker's route to:
 +                 Node 0x02 (Audio Output) -> Node 0x0c (Audio Mixer) -> Node 0x17 (
 +                 Pin Complex), since Node 0x02 has Amp-out caps, we can adjust
 +                 speaker's volume now. */
  
 -      /* 3k pull low control for Headset jack. */
 -      /* NOTE: call this before clearing the pin, otherwise codec stalls */
 -      /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
 -       * when booting with headset plugged. So skip setting it for the codec alc257
 -       */
 -              if (spec->en_3kpull_low)
 -                      alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
 +              static const hda_nid_t conn1[] = { 0x0c };
 +              snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn1), conn1);
 +      }
 +}
  
 -              if (!spec->no_shutup_pins)
 -                      snd_hda_codec_write(codec, hp_pin, 0,
 -                                  AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
 +/* disable DAC3 (0x06) selection on NID 0x17 as it has no volume amp control */
 +static void alc295_fixup_disable_dac3(struct hda_codec *codec,
 +                                    const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              static const hda_nid_t conn[] = { 0x02, 0x03 };
 +              snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
 +      }
 +}
  
 -              msleep(75);
 +/* force NID 0x17 (Bass Speaker) to DAC1 to share it with the main speaker */
 +static void alc285_fixup_speaker2_to_dac1(struct hda_codec *codec,
 +                                        const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              static const hda_nid_t conn[] = { 0x02 };
 +              snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
        }
 +}
  
 -      alc_auto_setup_eapd(codec, false);
 -      alc_shutup_pins(codec);
 -      if (spec->ultra_low_power) {
 -              msleep(50);
 -              alc_update_coef_idx(codec, 0x03, 1<<1, 0);
 -              alc_update_coef_idx(codec, 0x08, 7<<4, 7<<4);
 -              alc_update_coef_idx(codec, 0x08, 3<<2, 0);
 -              alc_update_coef_idx(codec, 0x3b, 1<<15, 1<<15);
 -              alc_update_coef_idx(codec, 0x0e, 7<<6, 0);
 -              msleep(30);
 +/* disable DAC3 (0x06) selection on NID 0x15 - share Speaker/Bass Speaker DAC 0x03 */
 +static void alc294_fixup_bass_speaker_15(struct hda_codec *codec,
 +                                       const struct hda_fixup *fix, int action)
 +{
 +      if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 +              static const hda_nid_t conn[] = { 0x02, 0x03 };
 +              snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn);
 +              snd_hda_gen_add_micmute_led_cdev(codec, NULL);
        }
  }