From 81937d3bac582ea2249dc2c8891d3371635e8b64 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Tue, 8 May 2007 15:33:03 +0200 Subject: [PATCH] [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: Steve Longerbeam Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_codec.c | 106 ++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 37 deletions(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ff12de4..14649d5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -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,16 +2265,32 @@ 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 * ALSA sequence is front/surr/clfe/side @@ -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; } -- 1.8.2.3