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++) {
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;
}
{
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;
} 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;
}
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;