Commit eea7dc93 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Use new inputs[] field to parse input-pins for STAC/IDT codecs

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 66ceeb6b
...@@ -1180,14 +1180,11 @@ static int stac92xx_build_controls(struct hda_codec *codec) ...@@ -1180,14 +1180,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
} }
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < cfg->num_inputs; i++) {
nid = cfg->input_pins[i]; nid = cfg->inputs[i].pin;
if (nid) { err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE);
err = stac92xx_add_jack(codec, nid, if (err < 0)
SND_JACK_MICROPHONE); return err;
if (err < 0)
return err;
}
} }
return 0; return 0;
...@@ -2821,41 +2818,55 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) ...@@ -2821,41 +2818,55 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid; hda_nid_t nid;
unsigned int pincap; unsigned int pincap;
int i;
if (cfg->line_out_type != AUTO_PIN_LINE_OUT) if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
return 0; return 0;
nid = cfg->input_pins[AUTO_PIN_LINE]; for (i = 0; i < cfg->num_inputs; i++) {
pincap = snd_hda_query_pin_caps(codec, nid); if (cfg->inputs[i].type == AUTO_PIN_LINE) {
if (pincap & AC_PINCAP_OUT) nid = cfg->inputs[i].pin;
return nid; pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_OUT)
return nid;
}
}
return 0; return 0;
} }
static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid);
/* check whether the mic-input can be used as line-out */ /* check whether the mic-input can be used as line-out */
static hda_nid_t check_mic_out_switch(struct hda_codec *codec) static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac)
{ {
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;
unsigned int def_conf, pincap; unsigned int def_conf, pincap;
unsigned int mic_pin; int i, mic_type;
*dac = 0;
if (cfg->line_out_type != AUTO_PIN_LINE_OUT) if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
return 0; return 0;
mic_pin = AUTO_PIN_MIC; mic_type = AUTO_PIN_MIC;
for (;;) { again:
hda_nid_t nid = cfg->input_pins[mic_pin]; for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
if (cfg->inputs[i].type != mic_type)
continue;
def_conf = snd_hda_codec_get_pincfg(codec, nid); def_conf = snd_hda_codec_get_pincfg(codec, nid);
/* some laptops have an internal analog microphone /* some laptops have an internal analog microphone
* which can't be used as a output */ * which can't be used as a output */
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
pincap = snd_hda_query_pin_caps(codec, nid); pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_OUT) if (pincap & AC_PINCAP_OUT) {
return nid; *dac = get_unassigned_dac(codec, nid);
if (*dac)
return nid;
}
} }
if (mic_pin == AUTO_PIN_MIC) }
mic_pin = AUTO_PIN_FRONT_MIC; if (mic_type == AUTO_PIN_MIC) {
else mic_type = AUTO_PIN_FRONT_MIC;
break; goto again;
} }
return 0; return 0;
} }
...@@ -3002,17 +3013,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) ...@@ -3002,17 +3013,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
} }
} }
/* add mic as output */ /* add mic as output */
nid = check_mic_out_switch(codec); nid = check_mic_out_switch(codec, &dac);
if (nid) { if (nid && dac) {
dac = get_unassigned_dac(codec, nid); snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
if (dac) { nid, cfg->line_outs);
snd_printdd("STAC: Add mic-in 0x%x as output %d\n", cfg->line_out_pins[cfg->line_outs] = nid;
nid, cfg->line_outs); cfg->line_outs++;
cfg->line_out_pins[cfg->line_outs] = nid; spec->mic_switch = nid;
cfg->line_outs++; add_spec_dacs(spec, dac);
spec->mic_switch = nid;
add_spec_dacs(spec, dac);
}
} }
snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
...@@ -3202,13 +3210,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, ...@@ -3202,13 +3210,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
return err; return err;
} }
for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) { for (idx = 0; idx < cfg->num_inputs; idx++) {
nid = cfg->input_pins[idx]; if (cfg->inputs[idx].type > AUTO_PIN_FRONT_LINE)
if (nid) { break;
err = stac92xx_add_jack_mode_control(codec, nid, idx); nid = cfg->inputs[idx].pin;
if (err < 0) err = stac92xx_add_jack_mode_control(codec, nid, idx);
return err; if (err < 0)
} return err;
} }
return 0; return 0;
...@@ -3415,7 +3423,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, ...@@ -3415,7 +3423,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
/* create a volume assigned to the given pin (only if supported) */ /* create a volume assigned to the given pin (only if supported) */
/* return 1 if the volume control is created */ /* return 1 if the volume control is created */
static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
const char *label, int direction) const char *label, int idx, int direction)
{ {
unsigned int caps, nums; unsigned int caps, nums;
char name[32]; char name[32];
...@@ -3432,8 +3440,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, ...@@ -3432,8 +3440,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
if (!nums) if (!nums)
return 0; return 0;
snprintf(name, sizeof(name), "%s Capture Volume", label); snprintf(name, sizeof(name), "%s Capture Volume", label);
err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction));
if (err < 0) if (err < 0)
return err; return err;
return 1; return 1;
...@@ -3485,11 +3493,11 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, ...@@ -3485,11 +3493,11 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
else else
label = stac92xx_dmic_labels[dimux->num_items]; label = stac92xx_dmic_labels[dimux->num_items];
err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); err = create_elem_capture_vol(codec, nid, label, 0, HDA_INPUT);
if (err < 0) if (err < 0)
return err; return err;
if (!err) { if (!err) {
err = create_elem_capture_vol(codec, nid, label, err = create_elem_capture_vol(codec, nid, label, 0,
HDA_OUTPUT); HDA_OUTPUT);
if (err < 0) if (err < 0)
return err; return err;
...@@ -3540,10 +3548,11 @@ static int set_mic_route(struct hda_codec *codec, ...@@ -3540,10 +3548,11 @@ static int set_mic_route(struct hda_codec *codec,
int i; int i;
mic->pin = pin; mic->pin = pin;
for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) for (i = 0; i < cfg->num_inputs; i++) {
if (pin == cfg->input_pins[i]) if (pin == cfg->inputs[i].pin)
break; break;
if (i <= AUTO_PIN_FRONT_MIC) { }
if (i < cfg->num_inputs && cfg->inputs[i].type <= AUTO_PIN_FRONT_MIC) {
/* analog pin */ /* analog pin */
i = get_connection_index(codec, spec->mux_nids[0], pin); i = get_connection_index(codec, spec->mux_nids[0], pin);
if (i < 0) if (i < 0)
...@@ -3577,13 +3586,13 @@ static int stac_check_auto_mic(struct hda_codec *codec) ...@@ -3577,13 +3586,13 @@ static int stac_check_auto_mic(struct hda_codec *codec)
hda_nid_t fixed, ext; hda_nid_t fixed, ext;
int i; int i;
for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { for (i = 0; i < cfg->num_inputs; i++) {
if (cfg->input_pins[i]) if (cfg->inputs[i].type >= AUTO_PIN_LINE)
return 0; /* must be exclusively mics */ return 0; /* must be exclusively mics */
} }
fixed = ext = 0; fixed = ext = 0;
for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) for (i = 0; i < cfg->num_inputs; i++)
if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) if (check_mic_pin(codec, cfg->inputs[i].pin, &fixed, &ext))
return 0; return 0;
for (i = 0; i < spec->num_dmics; i++) for (i = 0; i < spec->num_dmics; i++)
if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext))
...@@ -3603,14 +3612,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const ...@@ -3603,14 +3612,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->private_imux; struct hda_input_mux *imux = &spec->private_imux;
int i, j; int i, j, type_idx = 0;
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->input_pins[i]; hda_nid_t nid = cfg->inputs[i].pin;
int index, err; int index, err;
if (!nid)
continue;
index = -1; index = -1;
for (j = 0; j < spec->num_muxes; j++) { for (j = 0; j < spec->num_muxes; j++) {
index = get_connection_index(codec, spec->mux_nids[j], index = get_connection_index(codec, spec->mux_nids[j],
...@@ -3621,13 +3628,18 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const ...@@ -3621,13 +3628,18 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
if (index < 0) if (index < 0)
continue; continue;
if (i > 0 && cfg->inputs[i].type == cfg->inputs[i - 1].type)
type_idx++;
else
type_idx = 0;
err = create_elem_capture_vol(codec, nid, err = create_elem_capture_vol(codec, nid,
auto_pin_cfg_labels[i], auto_pin_cfg_labels[i], type_idx,
HDA_INPUT); HDA_INPUT);
if (err < 0) if (err < 0)
return err; return err;
imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; imux->items[imux->num_items].label =
snd_hda_get_input_pin_label(cfg, i);
imux->items[imux->num_items].index = index; imux->items[imux->num_items].index = index;
imux->num_items++; imux->num_items++;
} }
...@@ -4304,37 +4316,34 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -4304,37 +4316,34 @@ static int stac92xx_init(struct hda_codec *codec)
if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
stac_issue_unsol_event(codec, spec->ext_mic.pin); stac_issue_unsol_event(codec, spec->ext_mic.pin);
} }
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->input_pins[i]; hda_nid_t nid = cfg->inputs[i].pin;
if (nid) { int type = cfg->inputs[i].type;
unsigned int pinctl, conf; unsigned int pinctl, conf;
if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { if (type == AUTO_PIN_MIC || type == AUTO_PIN_FRONT_MIC) {
/* for mic pins, force to initialize */ /* for mic pins, force to initialize */
pinctl = stac92xx_get_default_vref(codec, nid); pinctl = stac92xx_get_default_vref(codec, nid);
pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid, pinctl);
} else {
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* if PINCTL already set then skip */
/* Also, if both INPUT and OUTPUT are set,
* it must be a BIOS bug; need to override, too
*/
if (!(pinctl & AC_PINCTL_IN_EN) ||
(pinctl & AC_PINCTL_OUT_EN)) {
pinctl &= ~AC_PINCTL_OUT_EN;
pinctl |= AC_PINCTL_IN_EN; pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid, pinctl); stac92xx_auto_set_pinctl(codec, nid, pinctl);
} else {
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* if PINCTL already set then skip */
/* Also, if both INPUT and OUTPUT are set,
* it must be a BIOS bug; need to override, too
*/
if (!(pinctl & AC_PINCTL_IN_EN) ||
(pinctl & AC_PINCTL_OUT_EN)) {
pinctl &= ~AC_PINCTL_OUT_EN;
pinctl |= AC_PINCTL_IN_EN;
stac92xx_auto_set_pinctl(codec, nid,
pinctl);
}
}
conf = snd_hda_codec_get_pincfg(codec, nid);
if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
if (enable_pin_detect(codec, nid,
STAC_INSERT_EVENT))
stac_issue_unsol_event(codec, nid);
} }
} }
conf = snd_hda_codec_get_pincfg(codec, nid);
if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT))
stac_issue_unsol_event(codec, nid);
}
} }
for (i = 0; i < spec->num_dmics; i++) for (i = 0; i < spec->num_dmics; i++)
stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
......
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