2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-26 14:14:01 +08:00

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 <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2012-12-05 14:17:37 +01:00
parent 6a84c305f0
commit 463419de86

View File

@ -172,6 +172,10 @@ struct alc_spec {
int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
hda_nid_t inv_dmic_pin; hda_nid_t inv_dmic_pin;
/* DAC list */
int num_all_dacs;
hda_nid_t all_dacs[16];
/* hooks */ /* hooks */
void (*init_hook)(struct hda_codec *codec); void (*init_hook)(struct hda_codec *codec);
#ifdef CONFIG_PM #ifdef CONFIG_PM
@ -2916,24 +2920,6 @@ static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
return false; return false;
} }
/* 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;
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)
continue;
if (!alc_is_dac_already_used(codec, nid))
return nid;
}
return 0;
}
/* check whether the DAC is reachable from the pin */ /* check whether the DAC is reachable from the pin */
static bool alc_auto_is_dac_reachable(struct hda_codec *codec, static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
hda_nid_t pin, hda_nid_t dac) hda_nid_t pin, hda_nid_t dac)
@ -2943,21 +2929,33 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
return snd_hda_get_conn_index(codec, pin, dac, true) >= 0; 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)
{
struct alc_spec *spec = codec->spec;
int i;
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_auto_is_dac_reachable(codec, pin, nid))
return nid;
}
return 0;
}
static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
hda_nid_t sel = alc_go_down_to_selector(codec, pin); int i;
hda_nid_t nid, nid_found, srcs[5]; hda_nid_t nid_found = 0;
int i, num = snd_hda_get_connections(codec, sel, srcs,
ARRAY_SIZE(srcs)); for (i = 0; i < spec->num_all_dacs; i++) {
if (num == 1) hda_nid_t nid = spec->all_dacs[i];
return alc_auto_look_for_dac(codec, pin); if (!nid || alc_is_dac_already_used(codec, nid))
nid_found = 0;
for (i = 0; i < num; i++) {
if (srcs[i] == spec->mixer_nid)
continue; continue;
nid = alc_auto_mix_to_dac(codec, srcs[i]); if (alc_auto_is_dac_reachable(codec, pin, nid)) {
if (nid && !alc_is_dac_already_used(codec, nid)) {
if (nid_found) if (nid_found)
return 0; return 0;
nid_found = nid; 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]); 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) static int alc_auto_fill_dac_nids(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; 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 best_wired = true, best_mio = true;
bool hp_spk_swapped = false; bool hp_spk_swapped = false;
alc_fill_all_nids(codec);
best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
if (!best_cfg) if (!best_cfg)
return -ENOMEM; return -ENOMEM;