Commit 3a65bcdc authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 54d778b3
...@@ -2002,24 +2002,24 @@ static int check_dyn_adc_switch(struct hda_codec *codec) ...@@ -2002,24 +2002,24 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
{ {
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->input_mux; 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; int i, n, nums;
hda_nid_t pin, adc;
again: again:
nums = 0; nums = 0;
ok_bits = 0;
for (n = 0; n < spec->num_adc_nids; n++) { for (n = 0; n < spec->num_adc_nids; n++) {
adc = spec->adc_nids[n];
for (i = 0; i < imux->num_items; i++) { for (i = 0; i < imux->num_items; i++) {
pin = spec->imux_pins[i]; if (!spec->input_paths[i][n])
if (!is_reachable_path(codec, pin, adc))
break; break;
} }
if (i >= imux->num_items) if (i >= imux->num_items) {
adc_nids[nums++] = adc; ok_bits |= (1 << n);
nums++;
}
} }
if (!nums) { if (!ok_bits) {
if (spec->shared_mic_hp) { if (spec->shared_mic_hp) {
spec->shared_mic_hp = 0; spec->shared_mic_hp = 0;
imux->num_items = 1; imux->num_items = 1;
...@@ -2028,10 +2028,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec) ...@@ -2028,10 +2028,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
/* check whether ADC-switch is possible */ /* check whether ADC-switch is possible */
for (i = 0; i < imux->num_items; i++) { for (i = 0; i < imux->num_items; i++) {
pin = spec->imux_pins[i];
for (n = 0; n < spec->num_adc_nids; n++) { for (n = 0; n < spec->num_adc_nids; n++) {
adc = spec->adc_nids[n]; if (spec->input_paths[i][n]) {
if (is_reachable_path(codec, pin, adc)) {
spec->dyn_adc_idx[i] = n; spec->dyn_adc_idx[i] = n;
break; break;
} }
...@@ -2041,7 +2039,19 @@ static int check_dyn_adc_switch(struct hda_codec *codec) ...@@ -2041,7 +2039,19 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
snd_printdd("hda-codec: enabling ADC switching\n"); snd_printdd("hda-codec: enabling ADC switching\n");
spec->dyn_adc_switch = 1; spec->dyn_adc_switch = 1;
} else if (nums != spec->num_adc_nids) { } 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; spec->num_adc_nids = nums;
} }
......
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