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
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;
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;
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;