diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index b077bb6..b2f7c43 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -1166,6 +1166,17 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
 		/* for multi-io case, only the primary out */
 		if (ch && spec->multi_ios)
 			break;
+		if (ch > 0) {
+			*index = 0;
+			switch (ch) {
+			case 1:
+				return "Headphone2";
+			case 2:
+				return "Headphone3";
+			case 3:
+				return "Headphone4";
+			}
+		}
 		*index = ch;
 		return "Headphone";
 	case AUTO_PIN_LINE_OUT:
@@ -2092,19 +2103,70 @@ static int create_multi_out_ctls(struct hda_codec *codec,
 	return 0;
 }
 
+#define is_dock_pin(codec, nid) \
+	((get_defcfg_location(snd_hda_codec_get_pincfg(codec, nid)) & 0x30) \
+	== AC_JACK_LOC_SEPARATE)
+
+char *get_hp_pfx(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hda_gen_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+
+	if (is_dock_pin(codec, nid))
+		return "Dock Headphone";
+	if ((nid == auto_cfg_hp_pins(cfg)[0]) && (spec->hs_mic_use_hp_sense))
+		return "Headset";
+	return "Headphone";
+}
+
 static int create_extra_out(struct hda_codec *codec, int path_idx,
 			    const char *pfx, int cidx)
 {
 	struct nid_path *path;
-	int err;
+	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+	hda_nid_t nid;
+	const hda_nid_t *p;
+	int err, i;
+	struct hda_gen_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
 
 	path = snd_hda_get_path_from_idx(codec, path_idx);
 	if (!path)
 		return 0;
-	err = add_stereo_vol(codec, pfx, cidx, path);
+	if (strcmp(pfx, "Headphone") == 0) {
+		p = auto_cfg_hp_pins(cfg);
+		nid = path->ctls[NID_PATH_VOL_CTL];
+		if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN)
+			strcpy(name, get_hp_pfx(codec, nid));
+		else {
+			strcpy(name, get_hp_pfx(codec, *p));
+			for (i = 1; i < auto_cfg_hp_outs(cfg); i++) {
+				p++;
+				strcat(name, "+");
+				strcat(name, get_hp_pfx(codec, *p));
+			}
+		}
+		err = add_stereo_vol(codec, name, cidx, path);
+	} else
+		err = add_stereo_vol(codec, pfx, cidx, path);
 	if (err < 0)
 		return err;
-	err = add_stereo_sw(codec, pfx, cidx, path);
+	if (strcmp(pfx, "Headphone") == 0) {
+		p = auto_cfg_hp_pins(cfg);
+		nid = path->ctls[NID_PATH_MUTE_CTL];
+		if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN)
+			strcpy(name, get_hp_pfx(codec, nid));
+		else {
+			strcpy(name, get_hp_pfx(codec, *p));
+			for (i = 1; i < auto_cfg_hp_outs(cfg); i++) {
+				p++;
+				strcat(name, "+");
+				strcat(name, get_hp_pfx(codec, *p));
+			}
+		}
+		err = add_stereo_sw(codec, name, cidx, path);
+	} else
+		err = add_stereo_sw(codec, pfx, cidx, path);
 	if (err < 0)
 		return err;
 	return 0;
@@ -4385,10 +4447,12 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
 			continue;
 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
+			codec_info(codec, "Mic 0x%x plugged\n", pin);
 			mux_select(codec, 0, spec->am_entry[i].idx);
 			return;
 		}
 	}
+	codec_info(codec, "Internal Mic selected\n");
 	mux_select(codec, 0, spec->am_entry[0].idx);
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
@@ -4665,7 +4729,9 @@ static int check_auto_mic_availability(struct hda_codec *codec)
 			if (!spec->line_in_auto_switch &&
 			    cfg->inputs[i].type != AUTO_PIN_MIC)
 				return 0; /* only mic is allowed */
-			if (!is_jack_detectable(codec, nid))
+			if (!is_jack_detectable(codec, nid) &&
+				!(spec->hs_mic_use_hp_sense &&
+				cfg->inputs[i].is_headset_mic))
 				return 0; /* no unsol support */
 			break;
 		}
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 56e4139..96f8214 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -236,6 +236,7 @@ struct hda_gen_spec {
 	unsigned int indep_hp_enabled:1; /* independent HP enabled */
 	unsigned int have_aamix_ctl:1;
 	unsigned int hp_mic_jack_modes:1;
+	unsigned int hs_mic_use_hp_sense:1;
 
 	/* additional mute flags (only effective with auto_mute_via_amp=1) */
 	u64 mute_bits;
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 366efbf..a2cd980 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -19,6 +19,7 @@
 #include "hda_local.h"
 #include "hda_auto_parser.h"
 #include "hda_jack.h"
+#include "hda_generic.h"
 
 /**
  * is_jack_detectable - Check whether the given pin is jack-detectable
@@ -157,7 +158,15 @@ static void jack_detect_update(struct hda_codec *codec,
 	if (jack->phantom_jack)
 		jack->pin_sense = AC_PINSENSE_PRESENCE;
 	else
-		jack->pin_sense = read_pin_sense(codec, jack->nid);
+		jack->pin_sense = read_pin_sense(codec,
+				jack->sense_nid ? jack->sense_nid : jack->nid);
+
+	if (jack->slave_nid) {
+		struct hda_jack_tbl *slave =
+			snd_hda_jack_tbl_get(codec, jack->slave_nid);
+		if (slave)
+			slave->pin_sense = jack->pin_sense;
+	}
 
 	/* A gating jack indicates the jack is invalid if gating is unplugged */
 	if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack))
@@ -209,6 +218,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
 		jack_detect_update(codec, jack);
 		return jack->pin_sense;
 	}
+	if (jack->sense_nid)
+		return read_pin_sense(codec, jack->sense_nid);
 	return read_pin_sense(codec, nid);
 }
 EXPORT_SYMBOL_GPL(snd_hda_pin_sense);
@@ -384,7 +395,7 @@ static void hda_free_jack_priv(struct snd_jack *jack)
  * will have the given name and index.
  */
 static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
-			  const char *name, bool phantom_jack)
+		  const char *name, bool phantom_jack, hda_nid_t sense_nid)
 {
 	struct hda_jack_tbl *jack;
 	int err, state, type;
@@ -405,6 +416,7 @@ static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 	jack->type = type;
 	jack->jack->private_data = jack;
 	jack->jack->private_free = hda_free_jack_priv;
+	jack->sense_nid = sense_nid;
 	state = snd_hda_jack_detect(codec, nid);
 	snd_jack_report(jack->jack, state ? jack->type : 0);
 
@@ -422,7 +434,7 @@ static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 			  const char *name)
 {
-	return __snd_hda_jack_add_kctl(codec, nid, name, false);
+	return __snd_hda_jack_add_kctl(codec, nid, name, false, nid);
 }
 EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl);
 
@@ -451,7 +463,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
 	if (phantom_jack)
 		/* Example final name: "Internal Mic Phantom Jack" */
 		strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
-	err = __snd_hda_jack_add_kctl(codec, nid, name, phantom_jack);
+	err = __snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, nid);
 	if (err < 0)
 		return err;
 
@@ -460,6 +472,14 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
 	return 0;
 }
 
+#define is_subwoofer(codec, nid, i) ((i == 1) && \
+	get_defcfg_device(snd_hda_codec_get_pincfg(codec, nid)) \
+	== AC_JACK_SPEAKER)
+
+#define is_external_pin(codec, nid) \
+((get_defcfg_location(snd_hda_codec_get_pincfg(codec, nid)) & 0x30) \
+	== AC_JACK_LOC_EXTERNAL)
+
 /**
  * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
  * @codec: the HDA codec
@@ -469,6 +489,9 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
 			   const struct auto_pin_cfg *cfg)
 {
 	const hda_nid_t *p;
+	struct hda_jack_tbl *jack;
+	hda_nid_t headset_mic_nid = 0;
+	struct hda_gen_spec *spec = codec->spec;
 	int i, err;
 
 	for (i = 0; i < cfg->num_inputs; i++) {
@@ -482,6 +505,14 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
 				err = add_jack_kctl(codec, cfg->inputs[i].pin,
 						    cfg, "Headphone Mic");
 		} else
+	    if (cfg->inputs[i].is_headset_mic &&
+			spec->hs_mic_use_hp_sense &&
+			is_jack_detectable(codec, auto_cfg_hp_pins(cfg)[0]) &&
+			!is_jack_detectable(codec, cfg->inputs[i].pin)) {
+			headset_mic_nid = cfg->inputs[i].pin;
+			err = __snd_hda_jack_add_kctl(codec, cfg->inputs[i].pin,
+				"Headset Mic", false, auto_cfg_hp_pins(cfg)[0]);
+		} else
 			err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg,
 					    NULL);
 		if (err < 0)
@@ -489,7 +520,10 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
 	}
 
 	for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
-		err = add_jack_kctl(codec, *p, cfg, NULL);
+		if (is_subwoofer(codec, *p, i) && is_external_pin(codec, *p))
+			err = add_jack_kctl(codec, *p, cfg, "Ext Subwoofer");
+		else
+			err = add_jack_kctl(codec, *p, cfg, NULL);
 		if (err < 0)
 			return err;
 	}
@@ -499,6 +533,11 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
 		err = add_jack_kctl(codec, *p, cfg, NULL);
 		if (err < 0)
 			return err;
+	    if ((i == 0) && spec->hs_mic_use_hp_sense) {
+			jack = snd_hda_jack_tbl_get(codec, *p);
+		    if (jack)
+				jack->slave_nid = headset_mic_nid;
+		}
 	}
 	for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
 		if (*p == *cfg->line_out_pins) /* might be duplicated */
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 387d309..ef3d162 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -41,6 +41,8 @@ struct hda_jack_tbl {
 	hda_nid_t gated_jack;		/* gated is dependent on this jack */
 	int type;
 	struct snd_jack *jack;
+	hda_nid_t sense_nid;
+	hda_nid_t slave_nid;
 };
 
 struct hda_jack_tbl *
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c456c04..db768cf 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3593,7 +3593,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
 		alc_process_coef_fw(codec, coef0668);
 		break;
 	}
-	codec_dbg(codec, "Headset jack set to unplugged mode.\n");
+	codec_info(codec, "Headset jack set to unplugged mode.\n");
 }
 
 
@@ -3683,7 +3683,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
 		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
 		break;
 	}
-	codec_dbg(codec, "Headset jack set to mic-in mode.\n");
+	codec_info(codec, "Headset jack set to mic-in mode.\n");
 }
 
 static void alc_headset_mode_default(struct hda_codec *codec)
@@ -3752,7 +3752,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
 		alc_process_coef_fw(codec, coef0688);
 		break;
 	}
-	codec_dbg(codec, "Headset jack set to headphone (default) mode.\n");
+	codec_info(codec, "Headset jack set to headphone (default) mode.\n");
 }
 
 /* Iphone type */
@@ -3823,7 +3823,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
 		alc_process_coef_fw(codec, coef0688);
 		break;
 	}
-	codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
+	codec_info(codec, "Headset jack set to iPhone-style headset mode.\n");
 }
 
 /* Nokia type */
@@ -3894,7 +3894,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
 		alc_process_coef_fw(codec, coef0688);
 		break;
 	}
-	codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
+	codec_info(codec, "Headset jack set to Nokia-style headset mode.\n");
 }
 
 static void alc_determine_headset_type(struct hda_codec *codec)
@@ -3970,7 +3970,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
 		break;
 	}
 
-	codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
+	codec_info(codec, "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;
 }
@@ -3984,8 +3984,21 @@ static void alc_update_headset_mode(struct hda_codec *codec)
 
 	int new_headset_mode;
 
+	if (codec->core.vendor_id == 0x10ec0668 &&
+		spec->gen.hs_mic_use_hp_sense) {
+		if (spec->gen.auto_mic) {
+			codec_info(codec, "mux_pin before 0x%x\n", mux_pin);
+			snd_hda_gen_mic_autoswitch(codec, NULL);
+			mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
+			codec_info(codec, "mux_pin after 0x%x\n", mux_pin);
+		}
+	}
+
 	if (!snd_hda_jack_detect(codec, hp_pin))
 		new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
+	else if (codec->core.vendor_id == 0x10ec0668 &&
+			spec->gen.hs_mic_use_hp_sense)
+			new_headset_mode = ALC_HEADSET_MODE_HEADSET;
 	else if (mux_pin == spec->headset_mic_pin)
 		new_headset_mode = ALC_HEADSET_MODE_HEADSET;
 	else if (mux_pin == spec->headphone_mic_pin)
@@ -6232,6 +6245,77 @@ static void alc_fixup_bass_chmap(struct hda_codec *codec,
 	}
 }
 
+static void alc668_fixup_dell_alienware(struct hda_codec *codec,
+				    const struct hda_fixup *fix, int action)
+{
+	const struct hda_pintbl pincfgs[] = {
+		{ 0x1a, 0x99130112 }, /* subwoofer */
+		{ 0x1b, 0x03a1113c }, /* headset mic */
+		{ }
+	};
+	static hda_nid_t preferred_pair[] = {
+		0x14, 0x03,
+		0x1a, 0x04,
+		0x15, 0x02,
+		0x16, 0x02,
+		0
+	};
+
+	struct alc_spec *spec = codec->spec;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		snd_hda_apply_pincfgs(codec, pincfgs);
+		spec->gen.preferred_dacs = preferred_pair;
+		spec->gen.hs_mic_use_hp_sense = 1;
+		spec->parse_flags |= HDA_PINCFG_HEADSET_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;
+	case HDA_FIXUP_ACT_BUILD:
+/* 
+		better to use default hda 2.1 chmap instead of asus 2.1 chmap
+		alc_fixup_bass_chmap(codec, fix, action);
+*/
+		break;
+	}
+}
+
+static void alc668_fixup_asus_headset(struct hda_codec *codec,
+				    const struct hda_fixup *fix, int action)
+{
+	const struct hda_pintbl pincfgs[] = {
+	    { 0x1a, 0x04110011 }, /* external subwoofer */
+		{ 0x1b, 0x03a1113c }, /* headset mic */
+		{ }
+	};
+
+	struct alc_spec *spec = codec->spec;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		snd_hda_apply_pincfgs(codec, pincfgs);
+		spec->gen.hs_mic_use_hp_sense = 1;
+		spec->parse_flags |= HDA_PINCFG_HEADSET_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;
+	case HDA_FIXUP_ACT_BUILD:
+		alc_fixup_bass_chmap(codec, fix, action);
+		break;
+	}
+}
+
 /* avoid D3 for keeping GPIO up */
 static unsigned int gpio_led_power_filter(struct hda_codec *codec,
 					  hda_nid_t nid,
@@ -6313,6 +6397,8 @@ enum {
 	ALC662_FIXUP_INV_DMIC,
 	ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
 	ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
+	ALC668_FIXUP_DELL_ALIENWARE,
+	ALC668_FIXUP_ASUS_HEADSET,
 	ALC662_FIXUP_HEADSET_MODE,
 	ALC668_FIXUP_HEADSET_MODE,
 	ALC662_FIXUP_BASS_MODE4_CHMAP,
@@ -6530,6 +6616,14 @@ static const struct hda_fixup alc662_fixups[] = {
 		.chained = true,
 		.chain_id = ALC668_FIXUP_HEADSET_MODE
 	},
+	[ALC668_FIXUP_DELL_ALIENWARE] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc668_fixup_dell_alienware,
+	},
+	[ALC668_FIXUP_ASUS_HEADSET] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc668_fixup_asus_headset,
+	},
 	[ALC668_FIXUP_HEADSET_MODE] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_headset_mode_alc668,
@@ -6667,6 +6761,8 @@ static const struct hda_model_fixup alc662_fixup_models[] = {
 	{.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
 	{.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
 	{.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
+	{.id = ALC668_FIXUP_DELL_ALIENWARE, .name = "dell-alienware"},
+	{.id = ALC668_FIXUP_ASUS_HEADSET, .name = "asus-headset"},
 	{}
 };
 
