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

Commit dc31b58d authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda/realtek - Refactor the DAC filler function



Refactor the DAC filling function to be used for both the primary
line outputs and extra outputs using the individual badness tables.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f02aab5d
Loading
Loading
Loading
Loading
+77 −77
Original line number Original line Diff line number Diff line
@@ -2969,6 +2969,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
	hda_nid_t srcs[5];
	hda_nid_t srcs[5];
	int i, num;
	int i, num;


	if (!pin || !dac)
		return false;
	pin = alc_go_down_to_selector(codec, pin);
	pin = alc_go_down_to_selector(codec, pin);
	num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
	num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
	for (i = 0; i < num; i++) {
	for (i = 0; i < num; i++) {
@@ -3087,60 +3089,88 @@ static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
	return badness;
	return badness;
}
}


/* try to assign DACs to extra pins and return the resultant badness */
struct badness_table {
static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
	int no_primary_dac;	/* no primary DAC */
				    const hda_nid_t *pins, hda_nid_t *dacs)
	int no_dac;		/* no secondary DACs */
	int shared_primary;	/* primary DAC is shared with main output */
	int shared_surr;	/* secondary DAC shared with main or primary */
	int shared_clfe;	/* third DAC shared with main or primary */
	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
};

static struct badness_table main_out_badness = {
	.no_primary_dac = BAD_NO_PRIMARY_DAC,
	.no_dac = BAD_NO_DAC,
	.shared_primary = BAD_NO_PRIMARY_DAC,
	.shared_surr = BAD_SHARED_SURROUND,
	.shared_clfe = BAD_SHARED_CLFE,
	.shared_surr_main = BAD_SHARED_SURROUND,
};

static struct badness_table extra_out_badness = {
	.no_primary_dac = BAD_NO_DAC,
	.no_dac = BAD_NO_DAC,
	.shared_primary = BAD_NO_EXTRA_DAC,
	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
};

/* try to assign DACs to pins and return the resultant badness */
static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs,
			      const hda_nid_t *pins, hda_nid_t *dacs,
			      const struct badness_table *bad)
{
{
	struct alc_spec *spec = codec->spec;
	struct alc_spec *spec = codec->spec;
	int i;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	int i, j;
	int badness = 0;
	int badness = 0;
	hda_nid_t dac;
	hda_nid_t dac;


	if (!num_outs)
	if (!num_outs)
		return 0;
		return 0;


	if (!dacs[0])
	for (i = 0; i < num_outs; i++) {
		dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
		hda_nid_t pin = pins[i];
	if (!dacs[0]) {
		if (!dacs[i])
		for (i = 1; i < num_outs; i++) {
			dacs[i] = alc_auto_look_for_dac(codec, pin);
			dac = dacs[i];
		if (!dacs[i] && !i) {
			if (dac && alc_auto_is_dac_reachable(codec, pins[0], dac)) {
			for (j = 1; j < num_outs; j++) {
				dacs[0] = dac;
				if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) {
				dacs[i] = 0;
					dacs[0] = dacs[j];
					dacs[j] = 0;
					break;
					break;
				}
				}
			}
			}
		}
		}
	dac = dacs[0];
	if (!dac) {
		dac = spec->private_dac_nids[0];
		if (!alc_auto_is_dac_reachable(codec, pins[0], dac))
			return BAD_NO_DAC;
		badness += BAD_NO_EXTRA_DAC;
	}
	if (dac)
		badness += eval_shared_vol_badness(codec, pins[0], dac);

	for (i = 1; i < num_outs; i++)
		dacs[i] = get_dac_if_single(codec, pins[i]);
	for (i = 1; i < num_outs; i++) {
		dac = dacs[i];
		dac = dacs[i];
		if (!dac)
			dac = dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
		if (!dac) {
		if (!dac) {
			if (alc_auto_is_dac_reachable(codec, pins[i], dacs[0])) {
			if (alc_auto_is_dac_reachable(codec, pin, dacs[0]))
				dac = dacs[0];
				dac = dacs[0];
				badness += BAD_SHARED_EXTRA_SURROUND;
			else if (cfg->line_outs > i &&
			} else if (alc_auto_is_dac_reachable(codec, pins[i],
				 alc_auto_is_dac_reachable(codec, pin,
					spec->private_dac_nids[i]))
				dac = spec->private_dac_nids[i];
			if (dac) {
				if (!i)
					badness += bad->shared_primary;
				else if (i == 1)
					badness += bad->shared_surr;
				else
					badness += bad->shared_clfe;
			} else if (alc_auto_is_dac_reachable(codec, pin,
					spec->private_dac_nids[0])) {
					spec->private_dac_nids[0])) {
				dac = spec->private_dac_nids[0];
				dac = spec->private_dac_nids[0];
				badness += BAD_NO_EXTRA_SURR_DAC;
				badness += bad->shared_surr_main;
			} else
			} else if (!i)
				badness += BAD_NO_DAC;
				badness += bad->no_primary_dac;
			else
				badness += bad->no_dac;
		}
		}
		if (dac)
		if (dac)
			badness += eval_shared_vol_badness(codec, pins[i], dac);
			badness += eval_shared_vol_badness(codec, pin, dac);
	}
	}

	return badness;
	return badness;
}
}


@@ -3170,7 +3200,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
{
{
	struct alc_spec *spec = codec->spec;
	struct alc_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	int i, j, err, badness;
	int i, err, badness;


	/* set num_dacs once to full for alc_auto_look_for_dac() */
	/* set num_dacs once to full for alc_auto_look_for_dac() */
	spec->multiout.num_dacs = cfg->line_outs;
	spec->multiout.num_dacs = cfg->line_outs;
@@ -3204,40 +3234,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
		} while (mapped);
		} while (mapped);
	}
	}


	for (i = 0; i < cfg->line_outs; i++) {
	badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins,
		hda_nid_t pin = cfg->line_out_pins[i];
				      spec->private_dac_nids,
		hda_nid_t dac;
				      &main_out_badness);
		if (!spec->private_dac_nids[i])
			spec->private_dac_nids[i] =
				alc_auto_look_for_dac(codec, pin);
		dac = spec->private_dac_nids[i];
		if (!dac && !i) {
			for (j = 1; j < cfg->line_outs; j++) {
				hda_nid_t dac2 = spec->private_dac_nids[j];
				if (dac2 &&
				    alc_auto_is_dac_reachable(codec, pin, dac2)) {
					dac = spec->private_dac_nids[0] = dac2;
					spec->private_dac_nids[j] = 0;
					break;
				}
			}
		}
		if (!dac) {
			if (!i)
				badness += BAD_NO_PRIMARY_DAC;
			else if (alc_auto_is_dac_reachable(codec, pin,
					spec->private_dac_nids[0])) {
				if (i == 1)
					badness += BAD_SHARED_SURROUND;
				else
					badness += BAD_SHARED_CLFE;
				dac = spec->private_dac_nids[0];
			} else
				badness += BAD_NO_DAC;
		}
		if (dac)
			badness += eval_shared_vol_badness(codec, pin, dac);
	}


	/* re-count num_dacs and squash invalid entries */
	/* re-count num_dacs and squash invalid entries */
	spec->multiout.num_dacs = 0;
	spec->multiout.num_dacs = 0;
@@ -3262,17 +3261,18 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
	}
	}


	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
		err = alc_auto_fill_extra_dacs(codec, cfg->hp_outs,
		err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins,
					       cfg->hp_pins,
					 spec->multiout.hp_out_nid,
					       spec->multiout.hp_out_nid);
					 &extra_out_badness);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		badness += err;
		badness += err;
	}
	}
	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
		err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
		err = alc_auto_fill_dacs(codec, cfg->speaker_outs,
					 cfg->speaker_pins,
					 cfg->speaker_pins,
					       spec->multiout.extra_out_nid);
					 spec->multiout.extra_out_nid,
					 &extra_out_badness);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		badness += err;
		badness += err;