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:
parent
54d778b31c
commit
3a65bcdc57
1 changed files with 22 additions and 12 deletions
|
@ -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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue