Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+22 −12
Original line number Diff line number Diff line
@@ -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;
	}