ALSA: hda - Fix inconsistent input_paths after ADC reduction

In the current parser code, the input_paths[] may become inconsistent
when some of detected ADCs are dropped due to incomplete inputs, since
the driver rearranges only adc_nids[] but doesn't touch input_paths[].

This patch fixes the issue, and also it optimizes the reachability
checks by simply referring to the parsed input_paths[] instead of
calling is_reachable() again for each connection.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2013-01-09 09:06:18 +01:00
parent 54d778b31c
commit 3a65bcdc57

View file

@ -2002,24 +2002,24 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
{
struct hda_gen_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->input_mux;
hda_nid_t adc_nids[ARRAY_SIZE(spec->adc_nids)];
unsigned int ok_bits;
int i, n, nums;
hda_nid_t pin, adc;
again:
nums = 0;
ok_bits = 0;
for (n = 0; n < spec->num_adc_nids; n++) {
adc = spec->adc_nids[n];
for (i = 0; i < imux->num_items; i++) {
pin = spec->imux_pins[i];
if (!is_reachable_path(codec, pin, adc))
if (!spec->input_paths[i][n])
break;
}
if (i >= imux->num_items)
adc_nids[nums++] = adc;
if (i >= imux->num_items) {
ok_bits |= (1 << n);
nums++;
}
}
if (!nums) {
if (!ok_bits) {
if (spec->shared_mic_hp) {
spec->shared_mic_hp = 0;
imux->num_items = 1;
@ -2028,10 +2028,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
/* check whether ADC-switch is possible */
for (i = 0; i < imux->num_items; i++) {
pin = spec->imux_pins[i];
for (n = 0; n < spec->num_adc_nids; n++) {
adc = spec->adc_nids[n];
if (is_reachable_path(codec, pin, adc)) {
if (spec->input_paths[i][n]) {
spec->dyn_adc_idx[i] = n;
break;
}
@ -2041,7 +2039,19 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
snd_printdd("hda-codec: enabling ADC switching\n");
spec->dyn_adc_switch = 1;
} else if (nums != spec->num_adc_nids) {
memcpy(spec->adc_nids, adc_nids, nums * sizeof(hda_nid_t));
/* shrink the invalid adcs and input paths */
nums = 0;
for (n = 0; n < spec->num_adc_nids; n++) {
if (!(ok_bits & (1 << n)))
continue;
if (n != nums) {
spec->adc_nids[nums] = spec->adc_nids[n];
for (i = 0; i < imux->num_items; i++)
spec->input_paths[i][nums] =
spec->input_paths[i][n];
}
nums++;
}
spec->num_adc_nids = nums;
}