OSDN Git Service

ALSA: hda - Fix headset mic support for Asus X101CH
[android-x86/kernel.git] / sound / pci / hda / patch_realtek.c
index 1bd2d49..cba9dc6 100644 (file)
@@ -52,6 +52,20 @@ enum {
        ALC_INIT_GPIO3,
 };
 
+enum {
+       ALC_HEADSET_MODE_UNKNOWN,
+       ALC_HEADSET_MODE_UNPLUGGED,
+       ALC_HEADSET_MODE_HEADSET,
+       ALC_HEADSET_MODE_MIC,
+       ALC_HEADSET_MODE_HEADPHONE,
+};
+
+enum {
+       ALC_HEADSET_TYPE_UNKNOWN,
+       ALC_HEADSET_TYPE_CTIA,
+       ALC_HEADSET_TYPE_OMTP,
+};
+
 struct alc_customize_define {
        unsigned int  sku_cfg;
        unsigned char port_connectivity;
@@ -87,6 +101,11 @@ struct alc_spec {
 
        unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
 
+       hda_nid_t headset_mic_pin;
+       hda_nid_t headphone_mic_pin;
+       int current_headset_mode;
+       int current_headset_type;
+
        /* hooks */
        void (*init_hook)(struct hda_codec *codec);
 #ifdef CONFIG_PM
@@ -2617,7 +2636,8 @@ static void alc271_fixup_dmic(struct hda_codec *codec,
        };
        unsigned int cfg;
 
-       if (strcmp(codec->chip_name, "ALC271X"))
+       if (strcmp(codec->chip_name, "ALC271X") &&
+           strcmp(codec->chip_name, "ALC269VB"))
                return;
        cfg = snd_hda_codec_get_pincfg(codec, 0x12);
        if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
@@ -2679,6 +2699,34 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec,
        spec->gen.automute_hook = alc269_quanta_automute;
 }
 
+static void alc269_x101_hp_automute_hook(struct hda_codec *codec,
+                                        struct hda_jack_tbl *jack)
+{
+       struct alc_spec *spec = codec->spec;
+       int vref;
+       msleep(200);
+       snd_hda_gen_hp_automute(codec, jack);
+
+       vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
+       msleep(100);
+       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                           vref);
+       msleep(500);
+       snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+                           vref);
+}
+
+static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
+               spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook;
+       }
+}
+
+
 /* update mute-LED according to the speaker mute state via mic VREF pin */
 static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
 {
@@ -2797,6 +2845,302 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
        }
 }
 
+static void alc_headset_mode_unplugged(struct hda_codec *codec)
+{
+       int val;
+
+       switch (codec->vendor_id) {
+       case 0x10ec0283:
+               alc_write_coef_idx(codec, 0x1b, 0x0c0b);
+               alc_write_coef_idx(codec, 0x45, 0xc429);
+               val = alc_read_coef_idx(codec, 0x35);
+               alc_write_coef_idx(codec, 0x35, val & 0xbfff);
+               alc_write_coef_idx(codec, 0x06, 0x2104);
+               alc_write_coef_idx(codec, 0x1a, 0x0001);
+               alc_write_coef_idx(codec, 0x26, 0x0004);
+               alc_write_coef_idx(codec, 0x32, 0x42a3);
+               break;
+       case 0x10ec0292:
+               alc_write_coef_idx(codec, 0x76, 0x000e);
+               alc_write_coef_idx(codec, 0x6c, 0x2400);
+               alc_write_coef_idx(codec, 0x18, 0x7308);
+               alc_write_coef_idx(codec, 0x6b, 0xc429);
+               break;
+       case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x15, 0x0d40);
+               alc_write_coef_idx(codec, 0xb7, 0x802b);
+               break;
+       }
+       snd_printdd("Headset jack set to unplugged mode.\n");
+}
+
+
+static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
+                                   hda_nid_t mic_pin)
+{
+       int val;
+
+       switch (codec->vendor_id) {
+       case 0x10ec0283:
+               alc_write_coef_idx(codec, 0x45, 0xc429);
+               snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
+               val = alc_read_coef_idx(codec, 0x35);
+               alc_write_coef_idx(codec, 0x35, val | 1<<14);
+               alc_write_coef_idx(codec, 0x06, 0x2100);
+               alc_write_coef_idx(codec, 0x1a, 0x0021);
+               alc_write_coef_idx(codec, 0x26, 0x008c);
+               snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
+               break;
+       case 0x10ec0292:
+               snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
+               alc_write_coef_idx(codec, 0x19, 0xa208);
+               alc_write_coef_idx(codec, 0x2e, 0xacf0);
+               break;
+       case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
+               snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
+               alc_write_coef_idx(codec, 0xb7, 0x802b);
+               alc_write_coef_idx(codec, 0xb5, 0x1040);
+               val = alc_read_coef_idx(codec, 0xc3);
+               alc_write_coef_idx(codec, 0xc3, val | 1<<12);
+               snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
+               break;
+       }
+       snd_printdd("Headset jack set to mic-in mode.\n");
+}
+
+static void alc_headset_mode_default(struct hda_codec *codec)
+{
+       switch (codec->vendor_id) {
+       case 0x10ec0283:
+               alc_write_coef_idx(codec, 0x06, 0x2100);
+               alc_write_coef_idx(codec, 0x32, 0x4ea3);
+               break;
+       case 0x10ec0292:
+               alc_write_coef_idx(codec, 0x76, 0x000e);
+               alc_write_coef_idx(codec, 0x6c, 0x2400);
+               alc_write_coef_idx(codec, 0x6b, 0xc429);
+               alc_write_coef_idx(codec, 0x18, 0x7308);
+               break;
+       case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0041);
+               alc_write_coef_idx(codec, 0x15, 0x0d40);
+               alc_write_coef_idx(codec, 0xb7, 0x802b);
+               break;
+       }
+       snd_printdd("Headset jack set to headphone (default) mode.\n");
+}
+
+/* Iphone type */
+static void alc_headset_mode_ctia(struct hda_codec *codec)
+{
+       switch (codec->vendor_id) {
+       case 0x10ec0283:
+               alc_write_coef_idx(codec, 0x45, 0xd429);
+               alc_write_coef_idx(codec, 0x1b, 0x0c2b);
+               alc_write_coef_idx(codec, 0x32, 0x4ea3);
+               break;
+       case 0x10ec0292:
+               alc_write_coef_idx(codec, 0x6b, 0xd429);
+               alc_write_coef_idx(codec, 0x76, 0x0008);
+               alc_write_coef_idx(codec, 0x18, 0x7388);
+               break;
+       case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x15, 0x0d60);
+               alc_write_coef_idx(codec, 0xc3, 0x0000);
+               break;
+       }
+       snd_printdd("Headset jack set to iPhone-style headset mode.\n");
+}
+
+/* Nokia type */
+static void alc_headset_mode_omtp(struct hda_codec *codec)
+{
+       switch (codec->vendor_id) {
+       case 0x10ec0283:
+               alc_write_coef_idx(codec, 0x45, 0xe429);
+               alc_write_coef_idx(codec, 0x1b, 0x0c2b);
+               alc_write_coef_idx(codec, 0x32, 0x4ea3);
+               break;
+       case 0x10ec0292:
+               alc_write_coef_idx(codec, 0x6b, 0xe429);
+               alc_write_coef_idx(codec, 0x76, 0x0008);
+               alc_write_coef_idx(codec, 0x18, 0x7388);
+               break;
+       case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x15, 0x0d50);
+               alc_write_coef_idx(codec, 0xc3, 0x0000);
+               break;
+       }
+       snd_printdd("Headset jack set to Nokia-style headset mode.\n");
+}
+
+static void alc_determine_headset_type(struct hda_codec *codec)
+{
+       int val;
+       bool is_ctia = false;
+       struct alc_spec *spec = codec->spec;
+
+       switch (codec->vendor_id) {
+       case 0x10ec0283:
+               alc_write_coef_idx(codec, 0x45, 0xd029);
+               msleep(300);
+               val = alc_read_coef_idx(codec, 0x46);
+               is_ctia = (val & 0x0070) == 0x0070;
+               break;
+       case 0x10ec0292:
+               alc_write_coef_idx(codec, 0x6b, 0xd429);
+               msleep(300);
+               val = alc_read_coef_idx(codec, 0x6c);
+               is_ctia = (val & 0x001c) == 0x001c;
+               break;
+       case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
+               alc_write_coef_idx(codec, 0xb7, 0x802b);
+               alc_write_coef_idx(codec, 0x15, 0x0d60);
+               alc_write_coef_idx(codec, 0xc3, 0x0c00);
+               msleep(300);
+               val = alc_read_coef_idx(codec, 0xbe);
+               is_ctia = (val & 0x1c02) == 0x1c02;
+               break;
+       }
+
+       snd_printdd("Headset jack detected iPhone-style headset: %s\n",
+                   is_ctia ? "yes" : "no");
+       spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
+}
+
+static void alc_update_headset_mode(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
+       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+
+       int new_headset_mode;
+
+       if (!snd_hda_jack_detect(codec, hp_pin))
+               new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
+       else if (mux_pin == spec->headset_mic_pin)
+               new_headset_mode = ALC_HEADSET_MODE_HEADSET;
+       else if (mux_pin == spec->headphone_mic_pin)
+               new_headset_mode = ALC_HEADSET_MODE_MIC;
+       else
+               new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
+
+       if (new_headset_mode == spec->current_headset_mode)
+               return;
+
+       switch (new_headset_mode) {
+       case ALC_HEADSET_MODE_UNPLUGGED:
+               alc_headset_mode_unplugged(codec);
+               spec->gen.hp_jack_present = false;
+               break;
+       case ALC_HEADSET_MODE_HEADSET:
+               if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
+                       alc_determine_headset_type(codec);
+               if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
+                       alc_headset_mode_ctia(codec);
+               else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
+                       alc_headset_mode_omtp(codec);
+               spec->gen.hp_jack_present = true;
+               break;
+       case ALC_HEADSET_MODE_MIC:
+               alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
+               spec->gen.hp_jack_present = false;
+               break;
+       case ALC_HEADSET_MODE_HEADPHONE:
+               alc_headset_mode_default(codec);
+               spec->gen.hp_jack_present = true;
+               break;
+       }
+       if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
+               snd_hda_set_pin_ctl_cache(codec, hp_pin,
+                                         AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
+               if (spec->headphone_mic_pin)
+                       snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
+                                                 PIN_VREFHIZ);
+       }
+       spec->current_headset_mode = new_headset_mode;
+
+       snd_hda_gen_update_outputs(codec);
+}
+
+static void alc_update_headset_mode_hook(struct hda_codec *codec,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       alc_update_headset_mode(codec);
+}
+
+static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->current_headset_type = ALC_HEADSET_MODE_UNKNOWN;
+       snd_hda_gen_hp_automute(codec, jack);
+}
+
+static void alc_probe_headset_mode(struct hda_codec *codec)
+{
+       int i;
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+
+       /* Find mic pins */
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
+                       spec->headset_mic_pin = cfg->inputs[i].pin;
+               if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
+                       spec->headphone_mic_pin = cfg->inputs[i].pin;
+       }
+
+       spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
+       spec->gen.automute_hook = alc_update_headset_mode;
+       spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
+}
+
+static void alc_fixup_headset_mode(struct hda_codec *codec,
+                               const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
+               break;
+       case HDA_FIXUP_ACT_PROBE:
+               alc_probe_headset_mode(codec);
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               spec->current_headset_mode = 0;
+               alc_update_headset_mode(codec);
+               break;
+       }
+}
+
+static void alc_fixup_headset_mode_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;
+       }
+       else
+               alc_fixup_headset_mode(codec, fix, action);
+}
+
+static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
+                               const struct hda_fixup *fix, int action)
+{
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               int val;
+               alc_write_coef_idx(codec, 0xc4, 0x8000);
+               val = alc_read_coef_idx(codec, 0xc2);
+               alc_write_coef_idx(codec, 0xc2, val & 0xfe);
+               snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
+       }
+       alc_fixup_headset_mode(codec, fix, action);
+}
+
 static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
                                    const struct hda_fixup *fix,
                                    int action)
@@ -2836,8 +3180,16 @@ enum {
        ALC269_FIXUP_INV_DMIC,
        ALC269_FIXUP_LENOVO_DOCK,
        ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
+       ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+       ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
+       ALC269_FIXUP_HEADSET_MODE,
+       ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
+       ALC269_FIXUP_ASUS_X101_FUNC,
+       ALC269_FIXUP_ASUS_X101_VERB,
+       ALC269_FIXUP_ASUS_X101,
        ALC271_FIXUP_AMIC_MIC2,
        ALC271_FIXUP_HP_GATE_MIC_JACK,
+       ALC269_FIXUP_ACER_AC700,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -2994,6 +3346,59 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
        },
+       [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE
+       },
+       [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x16, 0x21014020 }, /* dock line out */
+                       { 0x19, 0x21a19030 }, /* dock mic */
+                       { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+       },
+       [ALC269_FIXUP_HEADSET_MODE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_headset_mode,
+       },
+       [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_headset_mode_no_hp_mic,
+       },
+       [ALC269_FIXUP_ASUS_X101_FUNC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_x101_headset_mic,
+       },
+       [ALC269_FIXUP_ASUS_X101_VERB] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
+                       {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
+                       {0x20, AC_VERB_SET_PROC_COEF,  0x0310},
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_ASUS_X101_FUNC
+       },
+       [ALC269_FIXUP_ASUS_X101] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x18, 0x04a1182c }, /* Headset mic */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_ASUS_X101_VERB
+       },
        [ALC271_FIXUP_AMIC_MIC2] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -3010,11 +3415,44 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC271_FIXUP_AMIC_MIC2,
        },
+       [ALC269_FIXUP_ACER_AC700] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x12, 0x99a3092f }, /* int-mic */
+                       { 0x14, 0x99130110 }, /* speaker */
+                       { 0x18, 0x03a11c20 }, /* mic */
+                       { 0x1e, 0x0346101e }, /* SPDIF1 */
+                       { 0x21, 0x0321101f }, /* HP out */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC271_FIXUP_DMIC,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
+       SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05c5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05c6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05c7, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05c8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05ec, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05ed, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05ee, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05f3, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
        SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -3029,11 +3467,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
        SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
        SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
        SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+       SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
        SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
@@ -3519,6 +3959,8 @@ enum {
        ALC662_FIXUP_NO_JACK_DETECT,
        ALC662_FIXUP_ZOTAC_Z68,
        ALC662_FIXUP_INV_DMIC,
+       ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
+       ALC668_FIXUP_HEADSET_MODE,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -3679,6 +4121,20 @@ static const struct hda_fixup alc662_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
+                       { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC668_FIXUP_HEADSET_MODE
+       },
+       [ALC668_FIXUP_HEADSET_MODE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_headset_mode_alc668,
+       },
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -3687,6 +4143,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
        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(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
        SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),