ALSA: hda/realtek - Refactor the DAC filler function
authorTakashi Iwai <tiwai@suse.de>
Fri, 17 Feb 2012 16:27:53 +0000 (17:27 +0100)
committerTakashi Iwai <tiwai@suse.de>
Fri, 17 Feb 2012 16:59:10 +0000 (17:59 +0100)
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: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_realtek.c

index 1cad6748e33779836b1286096ba8289d2d3c6d46..a0df05d03864ca6e8455f70cf2a583ef9124269f 100644 (file)
@@ -2969,6 +2969,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
        hda_nid_t srcs[5];
        int i, num;
 
+       if (!pin || !dac)
+               return false;
        pin = alc_go_down_to_selector(codec, pin);
        num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
        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;
 }
 
-/* try to assign DACs to extra pins and return the resultant badness */
-static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
-                                   const hda_nid_t *pins, hda_nid_t *dacs)
+struct badness_table {
+       int no_primary_dac;     /* no primary DAC */
+       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;
-       int i;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i, j;
        int badness = 0;
        hda_nid_t dac;
 
        if (!num_outs)
                return 0;
 
-       if (!dacs[0])
-               dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
-       if (!dacs[0]) {
-               for (i = 1; i < num_outs; i++) {
-                       dac = dacs[i];
-                       if (dac && alc_auto_is_dac_reachable(codec, pins[0], dac)) {
-                               dacs[0] = dac;
-                               dacs[i] = 0;
-                               break;
+       for (i = 0; i < num_outs; i++) {
+               hda_nid_t pin = pins[i];
+               if (!dacs[i])
+                       dacs[i] = alc_auto_look_for_dac(codec, pin);
+               if (!dacs[i] && !i) {
+                       for (j = 1; j < num_outs; j++) {
+                               if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) {
+                                       dacs[0] = dacs[j];
+                                       dacs[j] = 0;
+                                       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];
-               if (!dac)
-                       dac = dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
                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];
-                               badness += BAD_SHARED_EXTRA_SURROUND;
-                       } else if (alc_auto_is_dac_reachable(codec, pins[i],
+                       else if (cfg->line_outs > 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])) {
                                dac = spec->private_dac_nids[0];
-                               badness += BAD_NO_EXTRA_SURR_DAC;
-                       } else
-                               badness += BAD_NO_DAC;
+                               badness += bad->shared_surr_main;
+                       } else if (!i)
+                               badness += bad->no_primary_dac;
+                       else
+                               badness += bad->no_dac;
                }
                if (dac)
-                       badness += eval_shared_vol_badness(codec, pins[i], dac);
+                       badness += eval_shared_vol_badness(codec, pin, dac);
        }
+
        return badness;
 }
 
@@ -3170,7 +3200,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 {
        struct alc_spec *spec = codec->spec;
        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() */
        spec->multiout.num_dacs = cfg->line_outs;
@@ -3204,40 +3234,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
                } while (mapped);
        }
 
-       for (i = 0; i < cfg->line_outs; i++) {
-               hda_nid_t pin = cfg->line_out_pins[i];
-               hda_nid_t dac;
-               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);
-       }
+       badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins,
+                                     spec->private_dac_nids,
+                                     &main_out_badness);
 
        /* re-count num_dacs and squash invalid entries */
        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) {
-               err = alc_auto_fill_extra_dacs(codec, cfg->hp_outs,
-                                              cfg->hp_pins,
-                                              spec->multiout.hp_out_nid);
+               err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins,
+                                        spec->multiout.hp_out_nid,
+                                        &extra_out_badness);
                if (err < 0)
                        return err;
                badness += err;
        }
        if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
-               err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
-                                              cfg->speaker_pins,
-                                              spec->multiout.extra_out_nid);
+               err = alc_auto_fill_dacs(codec, cfg->speaker_outs,
+                                        cfg->speaker_pins,
+                                        spec->multiout.extra_out_nid,
+                                        &extra_out_badness);
                if (err < 0)
                        return err;
                badness += err;