/* 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 */
        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;
 }
 
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct sigmatel_spec *spec = codec->spec;
-
-       spec->hp_switch = ucontrol->value.integer.value[0];
+       int nid = kcontrol->private_value;
+ 
+       spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0;
 
        /* check to be sure that the ports are upto date with
         * switch changes
        if (cfg->hp_outs > 1) {
                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;
        }
        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;
        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);
                                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);
                                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)