]> Pileus Git - ~andy/linux/blobdiff - sound/pci/hda/patch_realtek.c
ALSA: hda - add headset mic detect quirks for another Dell laptop
[~andy/linux] / sound / pci / hda / patch_realtek.c
index c5646941539a87df9505eece6241dd5e9230c4ff..56a8f187660333a51149910648d00b0a944e685b 100644 (file)
@@ -118,7 +118,8 @@ struct alc_spec {
 
        int init_amp;
        int codec_variant;      /* flag for other variants */
-       bool has_alc5505_dsp;
+       unsigned int has_alc5505_dsp:1;
+       unsigned int no_depop_delay:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -280,8 +281,11 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
  */
 static void alc_eapd_shutup(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
+
        alc_auto_setup_eapd(codec, false);
-       msleep(200);
+       if (!spec->no_depop_delay)
+               msleep(200);
        snd_hda_shutup_pins(codec);
 }
 
@@ -365,6 +369,17 @@ static void alc_fixup_sku_ignore(struct hda_codec *codec,
        }
 }
 
+static void alc_fixup_no_depop_delay(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PROBE) {
+               spec->no_depop_delay = 1;
+               codec->depop_delay = 0;
+       }
+}
+
 static int alc_auto_parse_customize_define(struct hda_codec *codec)
 {
        unsigned int ass, tmp, i;
@@ -454,9 +469,7 @@ static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
  *     7  ~ 0  :       Assembly ID
  *     port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
  */
-static int alc_subsystem_id(struct hda_codec *codec,
-                           hda_nid_t porta, hda_nid_t porte,
-                           hda_nid_t portd, hda_nid_t porti)
+static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
 {
        unsigned int ass, tmp, i;
        unsigned nid;
@@ -546,14 +559,7 @@ do_sku:
              spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
                hda_nid_t nid;
                tmp = (ass >> 11) & 0x3;        /* HP to chassis */
-               if (tmp == 0)
-                       nid = porta;
-               else if (tmp == 1)
-                       nid = porte;
-               else if (tmp == 2)
-                       nid = portd;
-               else if (tmp == 3)
-                       nid = porti;
+               nid = ports[tmp];
                if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
                                      spec->gen.autocfg.line_outs))
                        return 1;
@@ -566,7 +572,7 @@ do_sku:
  * ports contains an array of 4 pin NIDs for port-A, E, D and I */
 static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
 {
-       if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
+       if (!alc_subsystem_id(codec, ports)) {
                struct alc_spec *spec = codec->spec;
                snd_printd("realtek: "
                           "Enable default setup for auto mode as fallback\n");
@@ -863,7 +869,10 @@ static int alc_suspend(struct hda_codec *codec)
 #ifdef CONFIG_PM
 static int alc_resume(struct hda_codec *codec)
 {
-       msleep(150); /* to avoid pop noise */
+       struct alc_spec *spec = codec->spec;
+
+       if (!spec->no_depop_delay)
+               msleep(150); /* to avoid pop noise */
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
@@ -903,7 +912,7 @@ static int alc_codec_rename(struct hda_codec *codec, const char *name)
 }
 
 /*
- * Rename codecs appropriately from COEF value
+ * Rename codecs appropriately from COEF value or subvendor id
  */
 struct alc_codec_rename_table {
        unsigned int vendor_id;
@@ -912,6 +921,13 @@ struct alc_codec_rename_table {
        const char *name;
 };
 
+struct alc_codec_rename_pci_table {
+       unsigned int codec_vendor_id;
+       unsigned short pci_subvendor;
+       unsigned short pci_subdevice;
+       const char *name;
+};
+
 static struct alc_codec_rename_table rename_tbl[] = {
        { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
        { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
@@ -931,9 +947,20 @@ static struct alc_codec_rename_table rename_tbl[] = {
        { } /* terminator */
 };
 
+static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
+       { 0x10ec0280, 0x1028, 0, "ALC3220" },
+       { 0x10ec0282, 0x1028, 0, "ALC3221" },
+       { 0x10ec0283, 0x1028, 0, "ALC3223" },
+       { 0x10ec0292, 0x1028, 0, "ALC3226" },
+       { 0x10ec0255, 0x1028, 0, "ALC3234" },
+       { 0x10ec0668, 0x1028, 0, "ALC3661" },
+       { } /* terminator */
+};
+
 static int alc_codec_rename_from_preset(struct hda_codec *codec)
 {
        const struct alc_codec_rename_table *p;
+       const struct alc_codec_rename_pci_table *q;
 
        for (p = rename_tbl; p->vendor_id; p++) {
                if (p->vendor_id != codec->vendor_id)
@@ -941,6 +968,17 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec)
                if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
                        return alc_codec_rename(codec, p->name);
        }
+
+       for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
+               if (q->codec_vendor_id != codec->vendor_id)
+                       continue;
+               if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
+                       continue;
+               if (!q->pci_subdevice ||
+                   q->pci_subdevice == codec->bus->pci->subsystem_device)
+                       return alc_codec_rename(codec, q->name);
+       }
+
        return 0;
 }
 
@@ -1763,6 +1801,7 @@ enum {
        ALC882_FIXUP_ACER_ASPIRE_7736,
        ALC882_FIXUP_ASUS_W90V,
        ALC889_FIXUP_CD,
+       ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
        ALC889_FIXUP_VAIO_TT,
        ALC888_FIXUP_EEE1601,
        ALC882_FIXUP_EAPD,
@@ -1780,6 +1819,7 @@ enum {
        ALC889_FIXUP_DAC_ROUTE,
        ALC889_FIXUP_MBP_VREF,
        ALC889_FIXUP_IMAC91_VREF,
+       ALC889_FIXUP_MBA11_VREF,
        ALC889_FIXUP_MBA21_VREF,
        ALC882_FIXUP_INV_DMIC,
        ALC882_FIXUP_NO_PRIMARY_HP,
@@ -1910,6 +1950,16 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
                alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
 }
 
+/* Set VREF on speaker pins on mba11 */
+static void alc889_fixup_mba11_vref(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[1] = { 0x18 };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
 /* Set VREF on speaker pins on mba21 */
 static void alc889_fixup_mba21_vref(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
@@ -1980,6 +2030,15 @@ static const struct hda_fixup alc882_fixups[] = {
                        { }
                }
        },
+       [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[]) {
@@ -2119,6 +2178,12 @@ static const struct hda_fixup alc882_fixups[] = {
                .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,
@@ -2194,7 +2259,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        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_MBP_VREF),
+       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),
@@ -2211,7 +2276,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -2314,6 +2379,7 @@ enum {
        ALC262_FIXUP_BENQ,
        ALC262_FIXUP_BENQ_T31,
        ALC262_FIXUP_INV_DMIC,
+       ALC262_FIXUP_INTEL_BAYLEYBAY,
 };
 
 static const struct hda_fixup alc262_fixups[] = {
@@ -2378,6 +2444,10 @@ static const struct hda_fixup alc262_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_no_depop_delay,
+       },
 };
 
 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
@@ -2389,6 +2459,7 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
        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),
        {}
 };
 
@@ -3526,6 +3597,15 @@ static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
        alc_fixup_headset_mode(codec, fix, action);
 }
 
+static void alc_fixup_auto_mute_via_amp(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->gen.auto_mute_via_amp = 1;
+       }
+}
+
 static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
 {
@@ -3717,101 +3797,18 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
 static void alc290_fixup_mono_speakers(struct hda_codec *codec,
                                       const struct hda_fixup *fix, int action)
 {
-       if (action == HDA_FIXUP_ACT_PRE_PROBE)
-               /* Remove DAC node 0x03, as it seems to be
-                  giving mono output */
-               snd_hda_override_wcaps(codec, 0x03, 0);
-}
-
-#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
-
-#include <linux/thinkpad_acpi.h>
-#include <acpi/acpi.h>
-
-static int (*led_set_func)(int, bool);
-
-static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
-                                void **rv)
-{
-       bool *found = context;
-       *found = true;
-       return AE_OK;
-}
-
-static bool is_thinkpad(struct hda_codec *codec)
-{
-       bool found = false;
-       if (codec->subsystem_id >> 16 != 0x17aa)
-               return false;
-       if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
-               return true;
-       found = false;
-       return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
-}
-
-static void update_tpacpi_mute_led(void *private_data, int enabled)
-{
-       if (led_set_func)
-               led_set_func(TPACPI_LED_MUTE, !enabled);
-}
-
-static void update_tpacpi_micmute_led(struct hda_codec *codec,
-                                     struct snd_ctl_elem_value *ucontrol)
-{
-       if (!ucontrol || !led_set_func)
-               return;
-       if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
-               /* TODO: How do I verify if it's a mono or stereo here? */
-               bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
-               led_set_func(TPACPI_LED_MICMUTE, !val);
-       }
-}
-
-static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
-                                 const struct hda_fixup *fix, int action)
-{
-       struct alc_spec *spec = codec->spec;
-       bool removefunc = false;
-
-       if (action == HDA_FIXUP_ACT_PROBE) {
-               if (!is_thinkpad(codec))
-                       return;
-               if (!led_set_func)
-                       led_set_func = symbol_request(tpacpi_led_set);
-               if (!led_set_func) {
-                       snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
-                       return;
-               }
-
-               removefunc = true;
-               if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
-                       spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
-                       removefunc = false;
-               }
-               if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
-                       if (spec->gen.num_adc_nids > 1)
-                               snd_printdd("Skipping micmute LED control due to several ADCs");
-                       else {
-                               spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
-                               removefunc = false;
-                       }
-               }
-       }
-
-       if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
-               symbol_put(tpacpi_led_set);
-               led_set_func = NULL;
+       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. */
+               hda_nid_t conn1[2] = { 0x0c };
+               snd_hda_override_conn_list(codec, 0x14, 1, conn1);
+               snd_hda_override_conn_list(codec, 0x15, 1, conn1);
        }
 }
 
-#else
-
-static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
-                                 const struct hda_fixup *fix, int action)
-{
-}
-
-#endif
+/* for hda_fixup_thinkpad_acpi() */
+#include "thinkpad_helper.c"
 
 enum {
        ALC269_FIXUP_SONY_VAIO,
@@ -3853,6 +3850,7 @@ enum {
        ALC269_FIXUP_ACER_AC700,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
        ALC269VB_FIXUP_ASUS_ZENBOOK,
+       ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
        ALC269VB_FIXUP_ORDISSIMO_EVE2,
        ALC283_FIXUP_CHROME_BOOK,
@@ -3860,6 +3858,9 @@ enum {
        ALC282_FIXUP_ASUS_TX300,
        ALC283_FIXUP_INT_MIC,
        ALC290_FIXUP_MONO_SPEAKERS,
+       ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
+       ALC290_FIXUP_SUBWOOFER,
+       ALC290_FIXUP_SUBWOOFER_HSJACK,
        ALC269_FIXUP_THINKPAD_ACPI,
        ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC255_FIXUP_HEADSET_MODE,
@@ -4143,6 +4144,17 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269VB_FIXUP_DMIC,
        },
+       [ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* class-D output amp +5dB */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x12 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x2800 },
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC269VB_FIXUP_ASUS_ZENBOOK,
+       },
        [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc269_fixup_limit_int_mic_boost,
@@ -4182,15 +4194,37 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
        },
+       [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x17, 0x90170112 }, /* subwoofer */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
+       },
+       [ALC290_FIXUP_SUBWOOFER] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x17, 0x90170112 }, /* subwoofer */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
+       },
        [ALC290_FIXUP_MONO_SPEAKERS] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc290_fixup_mono_speakers,
+       },
+       [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc290_fixup_mono_speakers,
                .chained = true,
                .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
        },
        [ALC269_FIXUP_THINKPAD_ACPI] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = alc_fixup_thinkpad_acpi,
+               .v.func = hda_fixup_thinkpad_acpi,
        },
        [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
@@ -4229,6 +4263,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
        SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -4247,16 +4282,24 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x060f, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
+       SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+       SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
        SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
+       SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
        SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x064d, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -4269,7 +4312,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
-       SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK),
+       SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
@@ -4502,7 +4545,7 @@ static int patch_alc269(struct hda_codec *codec)
        }
 
        if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
-               spec->has_alc5505_dsp = true;
+               spec->has_alc5505_dsp = 1;
                spec->init_hook = alc5505_dsp_init;
        }
 
@@ -4841,6 +4884,7 @@ enum {
        ALC662_FIXUP_BASS_CHMAP,
        ALC662_FIXUP_BASS_1A,
        ALC662_FIXUP_BASS_1A_CHMAP,
+       ALC668_FIXUP_AUTO_MUTE,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -5001,6 +5045,12 @@ static const struct hda_fixup alc662_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC668_FIXUP_AUTO_MUTE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_auto_mute_via_amp,
+               .chained = true,
+               .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
+       },
        [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -5046,11 +5096,12 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE),
+       SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE),
        SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE),
+       SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
        SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),