Commit 504765f3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: hda - Fix IDT/STAC multiple HP detection
  ALSA: hda - Fix input pin initialization for STAC/IDT codecs
  ALSA: hda - Add missing analog-mux mixer creation for STAC9200
parents 58a47481 24924f88
...@@ -212,7 +212,7 @@ struct sigmatel_spec { ...@@ -212,7 +212,7 @@ struct sigmatel_spec {
/* i/o switches */ /* i/o switches */
unsigned int io_switch[2]; unsigned int io_switch[2];
unsigned int clfe_swap; unsigned int clfe_swap;
unsigned int hp_switch; unsigned int hp_switch; /* NID of HP as line-out */
unsigned int aloopback; unsigned int aloopback;
struct hda_pcm pcm_rec[2]; /* PCM information */ struct hda_pcm pcm_rec[2]; /* PCM information */
...@@ -2443,7 +2443,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, ...@@ -2443,7 +2443,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
ucontrol->value.integer.value[0] = spec->hp_switch; ucontrol->value.integer.value[0] = !!spec->hp_switch;
return 0; return 0;
} }
...@@ -2452,8 +2452,9 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, ...@@ -2452,8 +2452,9 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
{ {
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec; 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 /* check to be sure that the ports are upto date with
* switch changes * switch changes
...@@ -2862,7 +2863,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, ...@@ -2862,7 +2863,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
if (cfg->hp_outs > 1) { if (cfg->hp_outs > 1) {
err = stac92xx_add_control(spec, err = stac92xx_add_control(spec,
STAC_CTL_WIDGET_HP_SWITCH, 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) if (err < 0)
return err; return err;
} }
...@@ -3530,6 +3532,12 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) ...@@ -3530,6 +3532,12 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0)
return err; return err;
if (spec->num_muxes > 0) {
err = stac92xx_auto_create_mux_input_ctls(codec);
if (err < 0)
return err;
}
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = 0x05; spec->multiout.dig_out_nid = 0x05;
if (spec->autocfg.dig_in_pin) if (spec->autocfg.dig_in_pin)
...@@ -3647,14 +3655,18 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3647,14 +3655,18 @@ static int stac92xx_init(struct hda_codec *codec)
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = cfg->input_pins[i]; hda_nid_t nid = cfg->input_pins[i];
if (nid) { if (nid) {
unsigned int pinctl = snd_hda_codec_read(codec, nid, unsigned int pinctl;
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
/* if PINCTL already set then skip */ /* for mic pins, force to initialize */
if (pinctl & AC_PINCAP_IN) pinctl = stac92xx_get_vref(codec, nid);
continue; } else {
pinctl = AC_PINCTL_IN_EN; pinctl = snd_hda_codec_read(codec, nid, 0,
if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
pinctl |= stac92xx_get_vref(codec, nid); /* if PINCTL already set then skip */
if (pinctl & AC_PINCTL_IN_EN)
continue;
}
pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid, pinctl); stac92xx_auto_set_pinctl(codec, nid, pinctl);
} }
} }
...@@ -3776,11 +3788,30 @@ static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) ...@@ -3776,11 +3788,30 @@ static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
return 0; 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) static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
int nid = cfg->hp_pins[cfg->hp_outs - 1];
int i, presence; int i, presence;
presence = 0; presence = 0;
...@@ -3791,15 +3822,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) ...@@ -3791,15 +3822,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
for (i = 0; i < cfg->hp_outs; i++) { for (i = 0; i < cfg->hp_outs; i++) {
if (presence) if (presence)
break; break;
if (spec->hp_switch && cfg->hp_pins[i] == nid) if (no_hp_sensing(spec, i))
break; continue;
presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
} }
if (presence) { if (presence) {
/* disable lineouts, enable hp */ /* disable lineouts */
if (spec->hp_switch) 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++) 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);
...@@ -3811,9 +3843,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) ...@@ -3811,9 +3843,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
spec->gpio_dir, spec->gpio_data & spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask); ~spec->eapd_mask);
} else { } else {
/* enable lineouts, disable hp */ /* enable lineouts */
if (spec->hp_switch) 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++) 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);
...@@ -3825,8 +3858,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) ...@@ -3825,8 +3858,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
spec->gpio_dir, spec->gpio_data | spec->gpio_dir, spec->gpio_data |
spec->eapd_mask); spec->eapd_mask);
} }
if (!spec->hp_switch && cfg->hp_outs > 1 && presence) /* toggle hp outs */
stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); 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) static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
......
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