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

Commit 81937d3b authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Jaroslav Kysela
Browse files

[ALSA] Add speaker pin sequencing to hda_codec.c:snd_hda_parse_pin_def_config()



Some verb tables (such as an Asus VT sent by IDT) contain only speaker
outs in the default pin configs, and no line-outs. In such a case the
speaker sequence numbers have to be used to order the speaker out
pins, just as is being done for line-out pins. Then, when speaker-outs
are copied to line-outs, the line-outs will be ordered properly.

Signed-off-by: default avatarSteve Longerbeam <stevel@embeddedalley.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent bdd148a3
Loading
Loading
Loading
Loading
+69 −37
Original line number Diff line number Diff line
@@ -2112,6 +2112,32 @@ static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
	return 0;
}


/*
 * Sort an associated group of pins according to their sequence numbers.
 */
static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
				  int num_pins)
{
	int i, j;
	short seq;
	hda_nid_t nid;
	
	for (i = 0; i < num_pins; i++) {
		for (j = i + 1; j < num_pins; j++) {
			if (sequences[i] > sequences[j]) {
				seq = sequences[i];
				sequences[i] = sequences[j];
				sequences[j] = seq;
				nid = pins[i];
				pins[i] = pins[j];
				pins[j] = nid;
			}
		}
	}
}


/*
 * Parse all pin widgets and store the useful pin nids to cfg
 *
@@ -2134,13 +2160,16 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec,
					   hda_nid_t *ignore_nids)
{
	hda_nid_t nid, nid_start;
	int i, j, nodes;
	short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)];
	int nodes;
	short seq, assoc_line_out, assoc_speaker;
	short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
	short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];

	memset(cfg, 0, sizeof(*cfg));

	memset(sequences, 0, sizeof(sequences));
	assoc_line_out = 0;
	memset(sequences_line_out, 0, sizeof(sequences_line_out));
	memset(sequences_speaker, 0, sizeof(sequences_speaker));
	assoc_line_out = assoc_speaker = 0;

	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
	for (nid = nid_start; nid < nodes + nid_start; nid++) {
@@ -2175,13 +2204,22 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec,
			if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
				continue;
			cfg->line_out_pins[cfg->line_outs] = nid;
			sequences[cfg->line_outs] = seq;
			sequences_line_out[cfg->line_outs] = seq;
			cfg->line_outs++;
			break;
		case AC_JACK_SPEAKER:
			seq = get_defcfg_sequence(def_conf);
			assoc = get_defcfg_association(def_conf);
			if (! assoc)
				continue;
			if (! assoc_speaker)
				assoc_speaker = assoc;
			else if (assoc_speaker != assoc)
				continue;
			if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
				continue;
			cfg->speaker_pins[cfg->speaker_outs] = nid;
			sequences_speaker[cfg->speaker_outs] = seq;
			cfg->speaker_outs++;
			break;
		case AC_JACK_HP_OUT:
@@ -2227,15 +2265,31 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec,
	}

	/* sort by sequence */
	for (i = 0; i < cfg->line_outs; i++)
		for (j = i + 1; j < cfg->line_outs; j++)
			if (sequences[i] > sequences[j]) {
				seq = sequences[i];
				sequences[i] = sequences[j];
				sequences[j] = seq;
				nid = cfg->line_out_pins[i];
				cfg->line_out_pins[i] = cfg->line_out_pins[j];
				cfg->line_out_pins[j] = nid;
	sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
			      cfg->line_outs);
	sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
			      cfg->speaker_outs);
	
	/*
	 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
	 * as a primary output
	 */
	if (!cfg->line_outs) {
		if (cfg->speaker_outs) {
			cfg->line_outs = cfg->speaker_outs;
			memcpy(cfg->line_out_pins, cfg->speaker_pins,
			       sizeof(cfg->speaker_pins));
			cfg->speaker_outs = 0;
			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
		} else if (cfg->hp_outs) {
			cfg->line_outs = cfg->hp_outs;
			memcpy(cfg->line_out_pins, cfg->hp_pins,
			       sizeof(cfg->hp_pins));
			cfg->hp_outs = 0;
			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
			cfg->line_out_type = AUTO_PIN_HP_OUT;
		}
	}

	/* Reorder the surround channels
@@ -2278,28 +2332,6 @@ int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec,
		   cfg->input_pins[AUTO_PIN_CD],
		   cfg->input_pins[AUTO_PIN_AUX]);

	/*
	 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
	 * as a primary output
	 */
	if (!cfg->line_outs) {
		if (cfg->speaker_outs) {
			cfg->line_outs = cfg->speaker_outs;
			memcpy(cfg->line_out_pins, cfg->speaker_pins,
			       sizeof(cfg->speaker_pins));
			cfg->speaker_outs = 0;
			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
		} else if (cfg->hp_outs) {
			cfg->line_outs = cfg->hp_outs;
			memcpy(cfg->line_out_pins, cfg->hp_pins,
			       sizeof(cfg->hp_pins));
			cfg->hp_outs = 0;
			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
			cfg->line_out_type = AUTO_PIN_HP_OUT;
		}
	}

	return 0;
}