[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:

committed by
Jaroslav Kysela

parent
19739fef02
commit
82bc955f63
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user