Commit 07b18f69 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda/realtek - Create multi-io jacks more aggresively

So far the driver creates the multi-io jacks only when a single output
jack, i.e. no multiple speakers are assigned.  This patch adds the
similar multi-io detection even with multiple speakers are assigned
primarily, so that 5.1-speakers + HP/mic/LI combination can work.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent da691064
...@@ -2974,6 +2974,23 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) ...@@ -2974,6 +2974,23 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
return 0; 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)
{
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 == dac)
return true;
}
return false;
}
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)
{ {
hda_nid_t sel = alc_go_down_to_selector(codec, pin); hda_nid_t sel = alc_go_down_to_selector(codec, pin);
...@@ -3003,13 +3020,15 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, ...@@ -3003,13 +3020,15 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
} }
static int alc_auto_fill_multi_ios(struct hda_codec *codec, static int alc_auto_fill_multi_ios(struct hda_codec *codec,
unsigned int location); unsigned int location, int offset);
/* fill in the dac_nids table from the parsed pin configuration */ /* fill in the dac_nids table from the parsed pin configuration */
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;
const struct auto_pin_cfg *cfg = &spec->autocfg; const struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int location, defcfg;
int num_pins;
bool redone = false; bool redone = false;
int i; int i;
...@@ -3061,13 +3080,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) ...@@ -3061,13 +3080,10 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
/* try to fill multi-io first */ /* try to fill multi-io first */
unsigned int location, defcfg;
int num_pins;
defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]); defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
location = get_defcfg_location(defcfg); location = get_defcfg_location(defcfg);
num_pins = alc_auto_fill_multi_ios(codec, location); num_pins = alc_auto_fill_multi_ios(codec, location, 0);
if (num_pins > 0) { if (num_pins > 0) {
spec->multi_ios = num_pins; spec->multi_ios = num_pins;
spec->ext_channel_count = 2; spec->ext_channel_count = 2;
...@@ -3082,6 +3098,21 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) ...@@ -3082,6 +3098,21 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins,
spec->multiout.extra_out_nid); spec->multiout.extra_out_nid);
if (!spec->multi_ios &&
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
cfg->hp_outs) {
/* try multi-ios with HP + inputs */
defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
location = get_defcfg_location(defcfg);
num_pins = alc_auto_fill_multi_ios(codec, location, 1);
if (num_pins > 0) {
spec->multi_ios = num_pins;
spec->ext_channel_count = 2;
spec->multiout.num_dacs = num_pins + 1;
}
}
return 0; return 0;
} }
...@@ -3467,17 +3498,19 @@ static void alc_auto_init_extra_out(struct hda_codec *codec) ...@@ -3467,17 +3498,19 @@ static void alc_auto_init_extra_out(struct hda_codec *codec)
* multi-io helper * multi-io helper
*/ */
static int alc_auto_fill_multi_ios(struct hda_codec *codec, static int alc_auto_fill_multi_ios(struct hda_codec *codec,
unsigned int location) unsigned int location,
int offset)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t prime_dac = spec->private_dac_nids[0]; hda_nid_t prime_dac = spec->private_dac_nids[0];
int type, i, num_pins = 0; int type, i, dacs, num_pins = 0;
dacs = spec->multiout.num_dacs;
for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
for (i = 0; i < cfg->num_inputs; i++) { for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin; hda_nid_t nid = cfg->inputs[i].pin;
hda_nid_t dac; hda_nid_t dac = 0;
unsigned int defcfg, caps; unsigned int defcfg, caps;
if (cfg->inputs[i].type != type) if (cfg->inputs[i].type != type)
continue; continue;
...@@ -3489,7 +3522,13 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, ...@@ -3489,7 +3522,13 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
caps = snd_hda_query_pin_caps(codec, nid); caps = snd_hda_query_pin_caps(codec, nid);
if (!(caps & AC_PINCAP_OUT)) if (!(caps & AC_PINCAP_OUT))
continue; continue;
dac = alc_auto_look_for_dac(codec, nid); if (offset && offset + num_pins < dacs) {
dac = spec->private_dac_nids[offset + num_pins];
if (!alc_auto_is_dac_reachable(codec, nid, dac))
dac = 0;
}
if (!dac)
dac = alc_auto_look_for_dac(codec, nid);
if (!dac) if (!dac)
continue; continue;
spec->multi_io[num_pins].pin = nid; spec->multi_io[num_pins].pin = nid;
...@@ -3498,11 +3537,11 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, ...@@ -3498,11 +3537,11 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec,
spec->private_dac_nids[spec->multiout.num_dacs++] = dac; spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
} }
} }
spec->multiout.num_dacs = 1; spec->multiout.num_dacs = dacs;
if (num_pins < 2) { if (num_pins < 2) {
/* clear up again */ /* clear up again */
memset(spec->private_dac_nids, 0, memset(spec->private_dac_nids + dacs, 0,
sizeof(spec->private_dac_nids)); sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
spec->private_dac_nids[0] = prime_dac; spec->private_dac_nids[0] = prime_dac;
return 0; return 0;
} }
......
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