Commit 463419de authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 6a84c305
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment