Commit e4973e1e authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Create jack detection elements in build_controls

The jack detection input elements should be created in build_controls
callback instead of init callback because init can be called multiple
times by suspend/resume and power-saving.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5f1e71b1
...@@ -1249,10 +1249,13 @@ static const char *slave_sws[] = { ...@@ -1249,10 +1249,13 @@ static const char *slave_sws[] = {
}; };
static void stac92xx_free_kctls(struct hda_codec *codec); static void stac92xx_free_kctls(struct hda_codec *codec);
static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type);
static int stac92xx_build_controls(struct hda_codec *codec) static int stac92xx_build_controls(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid;
int err; int err;
int i; int i;
...@@ -1323,6 +1326,36 @@ static int stac92xx_build_controls(struct hda_codec *codec) ...@@ -1323,6 +1326,36 @@ static int stac92xx_build_controls(struct hda_codec *codec)
} }
stac92xx_free_kctls(codec); /* no longer needed */ stac92xx_free_kctls(codec); /* no longer needed */
/* create jack input elements */
if (spec->hp_detect) {
for (i = 0; i < cfg->hp_outs; i++) {
int type = SND_JACK_HEADPHONE;
nid = cfg->hp_pins[i];
/* jack detection */
if (cfg->hp_outs == i)
type |= SND_JACK_LINEOUT;
err = stac92xx_add_jack(codec, nid, type);
if (err < 0)
return err;
}
}
for (i = 0; i < cfg->line_outs; i++) {
err = stac92xx_add_jack(codec, cfg->line_out_pins[i],
SND_JACK_LINEOUT);
if (err < 0)
return err;
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
nid = cfg->input_pins[i];
if (nid) {
err = stac92xx_add_jack(codec, nid,
SND_JACK_MICROPHONE);
if (err < 0)
return err;
}
}
return 0; return 0;
} }
...@@ -3658,6 +3691,7 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, ...@@ -3658,6 +3691,7 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
static int stac92xx_add_jack(struct hda_codec *codec, static int stac92xx_add_jack(struct hda_codec *codec,
hda_nid_t nid, int type) hda_nid_t nid, int type)
{ {
#ifdef CONFIG_SND_JACK
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
struct sigmatel_jack *jack; struct sigmatel_jack *jack;
int def_conf = snd_hda_codec_read(codec, nid, int def_conf = snd_hda_codec_read(codec, nid,
...@@ -3681,6 +3715,9 @@ static int stac92xx_add_jack(struct hda_codec *codec, ...@@ -3681,6 +3715,9 @@ static int stac92xx_add_jack(struct hda_codec *codec,
snd_hda_get_jack_location(def_conf)); snd_hda_get_jack_location(def_conf));
return snd_jack_new(codec->bus->card, name, type, &jack->jack); return snd_jack_new(codec->bus->card, name, type, &jack->jack);
#else
return 0;
#endif
} }
static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid, static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
...@@ -3748,7 +3785,7 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3748,7 +3785,7 @@ static int stac92xx_init(struct hda_codec *codec)
{ {
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 i, err; int i;
snd_hda_sequence_write(codec, spec->init); snd_hda_sequence_write(codec, spec->init);
...@@ -3762,16 +3799,8 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3762,16 +3799,8 @@ static int stac92xx_init(struct hda_codec *codec)
if (spec->hp_detect) { if (spec->hp_detect) {
/* Enable unsolicited responses on the HP widget */ /* Enable unsolicited responses on the HP widget */
for (i = 0; i < cfg->hp_outs; i++) { for (i = 0; i < cfg->hp_outs; i++) {
int type = SND_JACK_HEADPHONE;
hda_nid_t nid = cfg->hp_pins[i]; hda_nid_t nid = cfg->hp_pins[i];
enable_pin_detect(codec, nid, STAC_HP_EVENT | nid); enable_pin_detect(codec, nid, STAC_HP_EVENT | nid);
/* jack detection */
if (cfg->hp_outs == i)
type |= SND_JACK_LINEOUT;
err = stac92xx_add_jack(codec, nid, type);
if (err < 0)
return err;
} }
/* 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
...@@ -3785,12 +3814,6 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3785,12 +3814,6 @@ static int stac92xx_init(struct hda_codec *codec)
stac92xx_auto_init_multi_out(codec); stac92xx_auto_init_multi_out(codec);
stac92xx_auto_init_hp_out(codec); stac92xx_auto_init_hp_out(codec);
} }
for (i = 0; i < cfg->line_outs; i++) {
err = stac92xx_add_jack(codec,
cfg->line_out_pins[i], SND_JACK_LINEOUT);
if (err < 0)
return err;
}
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) {
...@@ -3807,10 +3830,6 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3807,10 +3830,6 @@ static int stac92xx_init(struct hda_codec *codec)
} }
pinctl |= AC_PINCTL_IN_EN; pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid, pinctl); stac92xx_auto_set_pinctl(codec, nid, pinctl);
err = stac92xx_add_jack(codec, nid,
SND_JACK_MICROPHONE);
if (err < 0)
return err;
enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid); enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid);
} }
} }
...@@ -3855,6 +3874,7 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -3855,6 +3874,7 @@ static int stac92xx_init(struct hda_codec *codec)
static void stac92xx_free_jacks(struct hda_codec *codec) static void stac92xx_free_jacks(struct hda_codec *codec)
{ {
#ifdef CONFIG_SND_JACK
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
if (spec->jacks.list) { if (spec->jacks.list) {
struct sigmatel_jack *jacks = spec->jacks.list; struct sigmatel_jack *jacks = spec->jacks.list;
...@@ -3863,6 +3883,7 @@ static void stac92xx_free_jacks(struct hda_codec *codec) ...@@ -3863,6 +3883,7 @@ static void stac92xx_free_jacks(struct hda_codec *codec)
snd_device_free(codec->bus->card, &jacks[i].jack); snd_device_free(codec->bus->card, &jacks[i].jack);
} }
snd_array_free(&spec->jacks); snd_array_free(&spec->jacks);
#endif
} }
static void stac92xx_free_kctls(struct hda_codec *codec) static void stac92xx_free_kctls(struct hda_codec *codec)
......
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