[ALSA] Add speaker pin sequencing to hda_codec.c:snd_hda_parse_pin_def_config()
authorSteve Longerbeam <stevel@embeddedalley.com>
Tue, 8 May 2007 13:33:03 +0000 (15:33 +0200)
committerJaroslav Kysela <perex@suse.cz>
Fri, 11 May 2007 14:56:18 +0000 (16:56 +0200)
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>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
sound/pci/hda/hda_codec.c

index ff12de474d2ccde94a94dcebddc3993e9ebde9cd..14649d54b49342bc55b5636fd63c75c1a522a585 100644 (file)
@@ -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;
 }