--- /dev/null
+From: Takashi Iwai <tiwai@suse.de>
+Subject: ALSA: hda - Fix IDT/STAC multiple HP detection
+Patch-mainline:
+References: bnc#443267
+
+Due to the recent change for multiple HP as line-out switch, only
+one of the multiple headphons (usually a wrong one) is toggled
+and the other pins are still disabled. This causes the silent output
+problem on some Dell laptops.
+
+Also, the hp_switch check is screwed up when a line-in or a mic-in
+jack exists. This is added as an additional output, but hp_switch
+check doesn't take it into account.
+
+This patch fixes these issues: simplify hp_switch check by using
+the NID instead of bool, and clean up / fix the toggle of HP pins
+in unsol event handler code.
+
+Reference: Novell bnc#443267
+ https://bugzilla.novell.com/show_bug.cgi?id=443267
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/pci/hda/patch_sigmatel.c | 57 +++++++++++++++++++++++++++++++----------
+ 1 file changed, 44 insertions(+), 13 deletions(-)
+
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -212,7 +212,7 @@ struct sigmatel_spec {
+ /* i/o switches */
+ unsigned int io_switch[2];
+ unsigned int clfe_swap;
+- unsigned int hp_switch;
++ unsigned int hp_switch; /* NID of HP as line-out */
+ unsigned int aloopback;
+
+ struct hda_pcm pcm_rec[2]; /* PCM information */
+@@ -2448,7 +2448,7 @@ static int stac92xx_hp_switch_get(struct
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+
+- ucontrol->value.integer.value[0] = spec->hp_switch;
++ ucontrol->value.integer.value[0] = !!spec->hp_switch;
+ return 0;
+ }
+
+@@ -2457,8 +2457,9 @@ static int stac92xx_hp_switch_put(struct
+ {
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
++ int nid = kcontrol->private_value;
+
+- spec->hp_switch = ucontrol->value.integer.value[0];
++ spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0;
+
+ /* check to be sure that the ports are upto date with
+ * switch changes
+@@ -2867,7 +2868,8 @@ static int stac92xx_auto_create_multi_ou
+ if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
+ err = stac92xx_add_control(spec,
+ STAC_CTL_WIDGET_HP_SWITCH,
+- "Headphone as Line Out Switch", 0);
++ "Headphone as Line Out Switch",
++ cfg->hp_pins[cfg->hp_outs - 1]);
+ if (err < 0)
+ return err;
+ }
+@@ -3791,11 +3793,30 @@ static int get_hp_pin_presence(struct hd
+ return 0;
+ }
+
++/* return non-zero if the hp-pin of the given array index isn't
++ * a jack-detection target
++ */
++static int no_hp_sensing(struct sigmatel_spec *spec, int i)
++{
++ struct auto_pin_cfg *cfg = &spec->autocfg;
++
++ /* ignore sensing of shared line and mic jacks */
++ if (spec->line_switch &&
++ cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE])
++ return 1;
++ if (spec->mic_switch &&
++ cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC])
++ return 1;
++ /* ignore if the pin is set as line-out */
++ if (cfg->hp_pins[i] == spec->hp_switch)
++ return 1;
++ return 0;
++}
++
+ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+- int nid = cfg->hp_pins[cfg->hp_outs - 1];
+ int i, presence;
+
+ presence = 0;
+@@ -3806,15 +3827,16 @@ static void stac92xx_hp_detect(struct hd
+ for (i = 0; i < cfg->hp_outs; i++) {
+ if (presence)
+ break;
+- if (spec->hp_switch && cfg->hp_pins[i] == nid)
+- break;
++ if (no_hp_sensing(spec, i))
++ continue;
+ presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
+ }
+
+ if (presence) {
+- /* disable lineouts, enable hp */
++ /* disable lineouts */
+ if (spec->hp_switch)
+- stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN);
++ stac92xx_reset_pinctl(codec, spec->hp_switch,
++ AC_PINCTL_OUT_EN);
+ for (i = 0; i < cfg->line_outs; i++)
+ stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
+ AC_PINCTL_OUT_EN);
+@@ -3826,9 +3848,10 @@ static void stac92xx_hp_detect(struct hd
+ spec->gpio_dir, spec->gpio_data &
+ ~spec->eapd_mask);
+ } else {
+- /* enable lineouts, disable hp */
++ /* enable lineouts */
+ if (spec->hp_switch)
+- stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
++ stac92xx_set_pinctl(codec, spec->hp_switch,
++ AC_PINCTL_OUT_EN);
+ for (i = 0; i < cfg->line_outs; i++)
+ stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
+ AC_PINCTL_OUT_EN);
+@@ -3840,8 +3863,16 @@ static void stac92xx_hp_detect(struct hd
+ spec->gpio_dir, spec->gpio_data |
+ spec->eapd_mask);
+ }
+- if (!spec->hp_switch && cfg->hp_outs > 1 && presence)
+- stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
++ /* toggle hp outs */
++ for (i = 0; i < cfg->hp_outs; i++) {
++ unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
++ if (no_hp_sensing(spec, i))
++ continue;
++ if (presence)
++ stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
++ else
++ stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val);
++ }
+ }
+
+ static void stac92xx_pin_sense(struct hda_codec *codec, int idx)