From 463419de865622e4b13e977e1536375ab897a53f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Dec 2012 14:17:37 +0100 Subject: [PATCH] ALSA: hda/realtek - List up all available DACs In the probing phase, create a list of all available DACs in the codec and use it for checking the single DAC connections. This list will be used in more other places in the later commits, too. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 76 ++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ca077402d6c0..8b768a566be0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -172,6 +172,10 @@ struct alc_spec { int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ hda_nid_t inv_dmic_pin; + /* DAC list */ + int num_all_dacs; + hda_nid_t all_dacs[16]; + /* hooks */ void (*init_hook)(struct hda_codec *codec); #ifdef CONFIG_PM @@ -2916,48 +2920,42 @@ static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) return false; } +/* check whether the DAC is reachable from the pin */ +static bool alc_auto_is_dac_reachable(struct hda_codec *codec, + hda_nid_t pin, hda_nid_t dac) +{ + if (!pin || !dac) + return false; + return snd_hda_get_conn_index(codec, pin, dac, true) >= 0; +} + /* look for an empty DAC slot */ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) { - hda_nid_t srcs[5]; - int i, num; + struct alc_spec *spec = codec->spec; + int i; - 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++) { - hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); - if (!nid) + for (i = 0; i < spec->num_all_dacs; i++) { + hda_nid_t nid = spec->all_dacs[i]; + if (!nid || alc_is_dac_already_used(codec, nid)) continue; - if (!alc_is_dac_already_used(codec, nid)) + if (alc_auto_is_dac_reachable(codec, pin, nid)) return nid; } return 0; } -/* check whether the DAC is reachable from the pin */ -static bool alc_auto_is_dac_reachable(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac) -{ - if (!pin || !dac) - return false; - return snd_hda_get_conn_index(codec, pin, dac, true) >= 0; -} - static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) { struct alc_spec *spec = codec->spec; - hda_nid_t sel = alc_go_down_to_selector(codec, pin); - hda_nid_t nid, nid_found, srcs[5]; - int i, num = snd_hda_get_connections(codec, sel, srcs, - ARRAY_SIZE(srcs)); - if (num == 1) - return alc_auto_look_for_dac(codec, pin); - nid_found = 0; - for (i = 0; i < num; i++) { - if (srcs[i] == spec->mixer_nid) + int i; + hda_nid_t nid_found = 0; + + for (i = 0; i < spec->num_all_dacs; i++) { + hda_nid_t nid = spec->all_dacs[i]; + if (!nid || alc_is_dac_already_used(codec, nid)) continue; - nid = alc_auto_mix_to_dac(codec, srcs[i]); - if (nid && !alc_is_dac_already_used(codec, nid)) { + if (alc_auto_is_dac_reachable(codec, pin, nid)) { if (nid_found) return 0; nid_found = nid; @@ -3308,6 +3306,26 @@ static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg) spec->multiout.extra_out_nid[3]); } +/* find all available DACs of the codec */ +static void alc_fill_all_nids(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int i; + hda_nid_t nid = codec->start_nid; + + spec->num_all_dacs = 0; + memset(spec->all_dacs, 0, sizeof(spec->all_dacs)); + for (i = 0; i < codec->num_nodes; i++, nid++) { + if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT) + continue; + if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) { + snd_printk(KERN_ERR "hda: Too many DACs!\n"); + break; + } + spec->all_dacs[spec->num_all_dacs++] = nid; + } +} + static int alc_auto_fill_dac_nids(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -3319,6 +3337,8 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) bool best_wired = true, best_mio = true; bool hp_spk_swapped = false; + alc_fill_all_nids(codec); + best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); if (!best_cfg) return -ENOMEM; -- 2.30.2