dect
/
linux-2.6
Archived
13
0
Fork 0

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

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2010-08-30 13:06:15 +02:00
parent 66ceeb6bc2
commit eea7dc932b
1 changed files with 96 additions and 87 deletions

View File

@ -1180,14 +1180,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
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;
}
for (i = 0; i < cfg->num_inputs; i++) {
nid = cfg->inputs[i].pin;
err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE);
if (err < 0)
return err;
}
return 0;
@ -2821,41 +2818,55 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid;
unsigned int pincap;
int i;
if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
return 0;
nid = cfg->input_pins[AUTO_PIN_LINE];
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_OUT)
return nid;
for (i = 0; i < cfg->num_inputs; i++) {
if (cfg->inputs[i].type == AUTO_PIN_LINE) {
nid = cfg->inputs[i].pin;
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_OUT)
return nid;
}
}
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 */
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 auto_pin_cfg *cfg = &spec->autocfg;
unsigned int def_conf, pincap;
unsigned int mic_pin;
int i, mic_type;
*dac = 0;
if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
return 0;
mic_pin = AUTO_PIN_MIC;
for (;;) {
hda_nid_t nid = cfg->input_pins[mic_pin];
mic_type = AUTO_PIN_MIC;
again:
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);
/* some laptops have an internal analog microphone
* which can't be used as a output */
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_OUT)
return nid;
if (pincap & AC_PINCAP_OUT) {
*dac = get_unassigned_dac(codec, nid);
if (*dac)
return nid;
}
}
if (mic_pin == AUTO_PIN_MIC)
mic_pin = AUTO_PIN_FRONT_MIC;
else
break;
}
if (mic_type == AUTO_PIN_MIC) {
mic_type = AUTO_PIN_FRONT_MIC;
goto again;
}
return 0;
}
@ -3002,17 +3013,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
}
}
/* add mic as output */
nid = check_mic_out_switch(codec);
if (nid) {
dac = get_unassigned_dac(codec, nid);
if (dac) {
snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
nid, cfg->line_outs);
cfg->line_out_pins[cfg->line_outs] = nid;
cfg->line_outs++;
spec->mic_switch = nid;
add_spec_dacs(spec, dac);
}
nid = check_mic_out_switch(codec, &dac);
if (nid && dac) {
snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
nid, cfg->line_outs);
cfg->line_out_pins[cfg->line_outs] = nid;
cfg->line_outs++;
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",
@ -3202,13 +3210,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
return err;
}
for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) {
nid = cfg->input_pins[idx];
if (nid) {
err = stac92xx_add_jack_mode_control(codec, nid, idx);
if (err < 0)
return err;
}
for (idx = 0; idx < cfg->num_inputs; idx++) {
if (cfg->inputs[idx].type > AUTO_PIN_FRONT_LINE)
break;
nid = cfg->inputs[idx].pin;
err = stac92xx_add_jack_mode_control(codec, nid, idx);
if (err < 0)
return err;
}
return 0;
@ -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) */
/* return 1 if the volume control is created */
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;
char name[32];
@ -3432,8 +3440,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
if (!nums)
return 0;
snprintf(name, sizeof(name), "%s Capture Volume", label);
err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction));
err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction));
if (err < 0)
return err;
return 1;
@ -3485,11 +3493,11 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
else
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)
return err;
if (!err) {
err = create_elem_capture_vol(codec, nid, label,
err = create_elem_capture_vol(codec, nid, label, 0,
HDA_OUTPUT);
if (err < 0)
return err;
@ -3540,10 +3548,11 @@ static int set_mic_route(struct hda_codec *codec,
int i;
mic->pin = pin;
for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++)
if (pin == cfg->input_pins[i])
for (i = 0; i < cfg->num_inputs; i++) {
if (pin == cfg->inputs[i].pin)
break;
if (i <= AUTO_PIN_FRONT_MIC) {
}
if (i < cfg->num_inputs && cfg->inputs[i].type <= AUTO_PIN_FRONT_MIC) {
/* analog pin */
i = get_connection_index(codec, spec->mux_nids[0], pin);
if (i < 0)
@ -3577,13 +3586,13 @@ static int stac_check_auto_mic(struct hda_codec *codec)
hda_nid_t fixed, ext;
int i;
for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) {
if (cfg->input_pins[i])
for (i = 0; i < cfg->num_inputs; i++) {
if (cfg->inputs[i].type >= AUTO_PIN_LINE)
return 0; /* must be exclusively mics */
}
fixed = ext = 0;
for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++)
if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext))
for (i = 0; i < cfg->num_inputs; i++)
if (check_mic_pin(codec, cfg->inputs[i].pin, &fixed, &ext))
return 0;
for (i = 0; i < spec->num_dmics; i++)
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
{
struct sigmatel_spec *spec = codec->spec;
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++) {
hda_nid_t nid = cfg->input_pins[i];
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
int index, err;
if (!nid)
continue;
index = -1;
for (j = 0; j < spec->num_muxes; 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
if (index < 0)
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,
auto_pin_cfg_labels[i],
auto_pin_cfg_labels[i], type_idx,
HDA_INPUT);
if (err < 0)
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->num_items++;
}
@ -4304,37 +4316,34 @@ static int stac92xx_init(struct hda_codec *codec)
if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
stac_issue_unsol_event(codec, spec->ext_mic.pin);
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = cfg->input_pins[i];
if (nid) {
unsigned int pinctl, conf;
if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
/* for mic pins, force to initialize */
pinctl = stac92xx_get_default_vref(codec, nid);
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
int type = cfg->inputs[i].type;
unsigned int pinctl, conf;
if (type == AUTO_PIN_MIC || type == AUTO_PIN_FRONT_MIC) {
/* for mic pins, force to initialize */
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;
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++)
stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],