Commit fefd67f3 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Add line-out jack detection on IDT/STAC codecs

Add the automatic mute of speakers via line-out jack plugging on
STAC/IDT codecs.  The feature is enabled when the HP detect is present.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent bf677bd8
...@@ -40,6 +40,7 @@ enum { ...@@ -40,6 +40,7 @@ enum {
STAC_INSERT_EVENT, STAC_INSERT_EVENT,
STAC_PWR_EVENT, STAC_PWR_EVENT,
STAC_HP_EVENT, STAC_HP_EVENT,
STAC_LO_EVENT,
STAC_MIC_EVENT, STAC_MIC_EVENT,
}; };
...@@ -4345,6 +4346,14 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -4345,6 +4346,14 @@ static int stac92xx_init(struct hda_codec *codec)
hda_nid_t nid = cfg->hp_pins[i]; hda_nid_t nid = cfg->hp_pins[i];
enable_pin_detect(codec, nid, STAC_HP_EVENT); enable_pin_detect(codec, nid, STAC_HP_EVENT);
} }
if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
/* enable pin-detect for line-outs as well */
for (i = 0; i < cfg->hp_outs; i++) {
hda_nid_t nid = cfg->hp_pins[i];
enable_pin_detect(codec, nid, STAC_LO_EVENT);
}
}
/* force to enable the first line-out; the others are set up /* force to enable the first line-out; the others are set up
* in unsol_event * in unsol_event
*/ */
...@@ -4543,6 +4552,48 @@ static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) ...@@ -4543,6 +4552,48 @@ static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
return 0; return 0;
} }
static void stac92xx_line_out_detect(struct hda_codec *codec,
int presence)
{
struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
int i;
for (i = 0; i < cfg->line_outs; i++) {
if (presence)
break;
presence = get_pin_presence(codec, cfg->line_out_pins[i]);
if (presence) {
unsigned int pinctl;
pinctl = snd_hda_codec_read(codec,
cfg->line_out_pins[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
if (pinctl & AC_PINCTL_IN_EN)
presence = 0; /* mic- or line-input */
}
}
if (presence) {
/* disable speakers */
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask);
} else {
/* enable speakers */
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data |
spec->eapd_mask);
}
}
/* return non-zero if the hp-pin of the given array index isn't /* return non-zero if the hp-pin of the given array index isn't
* a jack-detection target * a jack-detection target
*/ */
...@@ -4595,13 +4646,6 @@ static void stac92xx_hp_detect(struct hda_codec *codec) ...@@ -4595,13 +4646,6 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
for (i = 0; i < cfg->line_outs; i++) for (i = 0; i < cfg->line_outs; i++)
stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
AC_PINCTL_OUT_EN); AC_PINCTL_OUT_EN);
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask);
} else { } else {
/* enable lineouts */ /* enable lineouts */
if (spec->hp_switch) if (spec->hp_switch)
...@@ -4610,14 +4654,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec) ...@@ -4610,14 +4654,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
for (i = 0; i < cfg->line_outs; i++) for (i = 0; i < cfg->line_outs; i++)
stac92xx_set_pinctl(codec, cfg->line_out_pins[i], stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
AC_PINCTL_OUT_EN); AC_PINCTL_OUT_EN);
for (i = 0; i < cfg->speaker_outs; i++)
stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
AC_PINCTL_OUT_EN);
if (spec->eapd_mask && spec->eapd_switch)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data |
spec->eapd_mask);
} }
stac92xx_line_out_detect(codec, presence);
/* toggle hp outs */ /* toggle hp outs */
for (i = 0; i < cfg->hp_outs; i++) { for (i = 0; i < cfg->hp_outs; i++) {
unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
...@@ -4744,6 +4782,9 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -4744,6 +4782,9 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
case STAC_HP_EVENT: case STAC_HP_EVENT:
stac92xx_hp_detect(codec); stac92xx_hp_detect(codec);
break; break;
case STAC_LO_EVENT:
stac92xx_line_out_detect(codec, 0);
break;
case STAC_MIC_EVENT: case STAC_MIC_EVENT:
stac92xx_mic_detect(codec); stac92xx_mic_detect(codec);
break; break;
...@@ -4751,6 +4792,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -4751,6 +4792,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
switch (event->type) { switch (event->type) {
case STAC_HP_EVENT: case STAC_HP_EVENT:
case STAC_LO_EVENT:
case STAC_MIC_EVENT: case STAC_MIC_EVENT:
case STAC_INSERT_EVENT: case STAC_INSERT_EVENT:
case STAC_PWR_EVENT: case STAC_PWR_EVENT:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment