[ALSA] hda-codec - Fix BIOS auto-configuration

Modules: HDA Codec driver,HDA generic driver

- Fix autoconfig speaker/hp detection
  Now it allows multiple speaker pins (e.g. Dell laptops have such config)

- Use speaker or hp pins if no line-outs are available
  This fixes the silence output on recent Dell laptops with STAC9200
  (ALSA bug#1843)

- Fix analog/realtek/sigmatel autoconfig parser

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai
2006-03-21 11:24:42 +01:00
committed by Jaroslav Kysela
parent 19739fef02
commit 82bc955f63
5 changed files with 160 additions and 75 deletions

View File

@@ -1899,6 +1899,13 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
if (mout->hp_nid)
/* headphone out will just decode front left/right (stereo) */
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
/* extra outputs copied from front */
for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
if (mout->extra_out_nid[i])
snd_hda_codec_setup_stream(codec,
mout->extra_out_nid[i],
stream_tag, 0, format);
/* surrounds */
for (i = 1; i < mout->num_dacs; i++) {
if (chs >= (i + 1) * 2) /* independent out */
@@ -1923,6 +1930,11 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
if (mout->hp_nid)
snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
if (mout->extra_out_nid[i])
snd_hda_codec_setup_stream(codec,
mout->extra_out_nid[i],
0, 0, 0);
mutex_lock(&codec->spdif_mutex);
if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
@@ -1944,13 +1956,29 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
return 0;
}
/* parse all pin widgets and store the useful pin nids to cfg */
/*
* Parse all pin widgets and store the useful pin nids to cfg
*
* The number of line-outs or any primary output is stored in line_outs,
* and the corresponding output pins are assigned to line_out_pins[],
* in the order of front, rear, CLFE, side, ...
*
* If more extra outputs (speaker and headphone) are found, the pins are
* assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack
* is detected, one of speaker of HP pins is assigned as the primary
* output, i.e. to line_out_pins[0]. So, line_outs is always positive
* if any analog output exists.
*
* The analog input pins are assigned to input_pins array.
* The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
* respectively.
*/
int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg,
hda_nid_t *ignore_nids)
{
hda_nid_t nid, nid_start;
int i, j, nodes;
short seq, sequences[4], assoc_line_out;
short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)];
memset(cfg, 0, sizeof(*cfg));
@@ -1992,7 +2020,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
cfg->line_outs++;
break;
case AC_JACK_SPEAKER:
cfg->speaker_pin = nid;
if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
continue;
cfg->speaker_pins[cfg->speaker_outs] = nid;
cfg->speaker_outs++;
break;
case AC_JACK_HP_OUT:
cfg->hp_pin = nid;
@@ -2057,6 +2088,46 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
break;
}
/*
* debug prints of the parsed results
*/
snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
cfg->line_out_pins[2], cfg->line_out_pins[3],
cfg->line_out_pins[4]);
snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
cfg->speaker_outs, cfg->speaker_pins[0],
cfg->speaker_pins[1], cfg->speaker_pins[2],
cfg->speaker_pins[3], cfg->speaker_pins[4]);
snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n",
cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin);
snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
" cd=0x%x, aux=0x%x\n",
cfg->input_pins[AUTO_PIN_MIC],
cfg->input_pins[AUTO_PIN_FRONT_MIC],
cfg->input_pins[AUTO_PIN_LINE],
cfg->input_pins[AUTO_PIN_FRONT_LINE],
cfg->input_pins[AUTO_PIN_CD],
cfg->input_pins[AUTO_PIN_AUX]);
/*
* FIX-UP: if no line-outs are detected, try to use speaker or HP pin
* as a primary output
*/
if (! cfg->line_outs) {
if (cfg->speaker_outs) {
cfg->line_outs = cfg->speaker_outs;
memcpy(cfg->line_out_pins, cfg->speaker_pins,
sizeof(cfg->speaker_pins));
cfg->speaker_outs = 0;
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
} else if (cfg->hp_pin) {
cfg->line_outs = 1;
cfg->line_out_pins[0] = cfg->hp_pin;
cfg->hp_pin = 0;
}
}
return 0;
}