[alsa-devel] [PATCH] Add sequence parsing for speaker-outs in snd_hda_parse_pin_def_config()
Any comments on this patch? It really is needed because some BIOS's only define speaker-out's in the HDA codec default pin configs, and no line-outs. So speaker-out's must be sequenced just as is being done for line-out's, otherwise the surround pin assignments will be wrong. Steve Steve Longerbeam wrote:
------------------------------------------------------------------------
changeset: 5028:01537f056c79 tag: tip user: stevel@embeddedalley.com date: Thu May 03 10:30:04 2007 -0700 summary: 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 <stevel@embeddedalley.com>
diff -r c7366efee611 -r 01537f056c79 pci/hda/hda_codec.c --- a/pci/hda/hda_codec.c Thu May 03 10:24:35 2007 -0700 +++ b/pci/hda/hda_codec.c Thu May 03 10:30:04 2007 -0700 @@ -2112,6 +2112,32 @@ static int __devinit is_in_nid_list(hda_ 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_conf 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_conf 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_conf }
/* 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_conf 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; }
------------------------------------------------------------------------
_______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Hi Steve, At Sat, 05 May 2007 11:16:44 -0700, Steve Longerbeam wrote:
Any comments on this patch? It really is needed because some BIOS's only define speaker-out's in the HDA codec default pin configs, and no line-outs. So speaker-out's must be sequenced just as is being done for line-out's, otherwise the surround pin assignments will be wrong.
I've been (and am still) sick since the last week, so I couldn't check posts on ML but only private mails. At the next time, if you'd like a patch review for merge, please add my address to Cc so that it'll reach to me certainly. Your patch looks nice, but unfortunately I have no test machines with HD-audio around my bed... Will test and merge to the upstream soon after I'm recovered :) Thanks, Takashi
Steve
Steve Longerbeam wrote:
------------------------------------------------------------------------
changeset: 5028:01537f056c79 tag: tip user: stevel@embeddedalley.com date: Thu May 03 10:30:04 2007 -0700 summary: 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 <stevel@embeddedalley.com>
diff -r c7366efee611 -r 01537f056c79 pci/hda/hda_codec.c --- a/pci/hda/hda_codec.c Thu May 03 10:24:35 2007 -0700 +++ b/pci/hda/hda_codec.c Thu May 03 10:30:04 2007 -0700 @@ -2112,6 +2112,32 @@ static int __devinit is_in_nid_list(hda_ 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_conf 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_conf 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_conf }
/* 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_conf 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; }
------------------------------------------------------------------------
_______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
_______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
Steve Longerbeam -
Takashi Iwai