+++ /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)