|
@@ -1125,6 +1125,25 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
|
|
|
return snd_hda_get_path_idx(codec, path);
|
|
|
}
|
|
|
|
|
|
+/* fill the empty entries in the dac array for speaker/hp with the
|
|
|
+ * shared dac pointed by the paths
|
|
|
+ */
|
|
|
+static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
|
|
|
+ hda_nid_t *dacs, int *path_idx)
|
|
|
+{
|
|
|
+ struct nid_path *path;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < num_outs; i++) {
|
|
|
+ if (dacs[i])
|
|
|
+ continue;
|
|
|
+ path = snd_hda_get_path_from_idx(codec, path_idx[i]);
|
|
|
+ if (!path)
|
|
|
+ continue;
|
|
|
+ dacs[i] = path->path[0];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* fill in the dac_nids table from the parsed pin configuration */
|
|
|
static int fill_and_eval_dacs(struct hda_codec *codec,
|
|
|
bool fill_hardwired,
|
|
@@ -1183,19 +1202,6 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
|
|
spec->private_dac_nids, spec->out_paths,
|
|
|
&main_out_badness);
|
|
|
|
|
|
- /* re-count num_dacs and squash invalid entries */
|
|
|
- spec->multiout.num_dacs = 0;
|
|
|
- for (i = 0; i < cfg->line_outs; i++) {
|
|
|
- if (spec->private_dac_nids[i])
|
|
|
- spec->multiout.num_dacs++;
|
|
|
- else {
|
|
|
- memmove(spec->private_dac_nids + i,
|
|
|
- spec->private_dac_nids + i + 1,
|
|
|
- sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
|
|
|
- spec->private_dac_nids[cfg->line_outs - 1] = 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (fill_mio_first &&
|
|
|
cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
|
/* try to fill multi-io first */
|
|
@@ -1246,16 +1252,41 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
|
|
|
if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
|
|
|
spec->multi_ios = 1; /* give badness */
|
|
|
|
|
|
+ /* re-count num_dacs and squash invalid entries */
|
|
|
+ spec->multiout.num_dacs = 0;
|
|
|
+ for (i = 0; i < cfg->line_outs; i++) {
|
|
|
+ if (spec->private_dac_nids[i])
|
|
|
+ spec->multiout.num_dacs++;
|
|
|
+ else {
|
|
|
+ memmove(spec->private_dac_nids + i,
|
|
|
+ spec->private_dac_nids + i + 1,
|
|
|
+ sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
|
|
|
+ spec->private_dac_nids[cfg->line_outs - 1] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ spec->ext_channel_count = spec->min_channel_count =
|
|
|
+ spec->multiout.num_dacs;
|
|
|
+
|
|
|
if (spec->multi_ios == 2) {
|
|
|
for (i = 0; i < 2; i++)
|
|
|
spec->private_dac_nids[spec->multiout.num_dacs++] =
|
|
|
spec->multi_io[i].dac;
|
|
|
- spec->ext_channel_count = 2;
|
|
|
} else if (spec->multi_ios) {
|
|
|
spec->multi_ios = 0;
|
|
|
badness += BAD_MULTI_IO;
|
|
|
}
|
|
|
|
|
|
+ /* re-fill the shared DAC for speaker / headphone */
|
|
|
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT)
|
|
|
+ refill_shared_dacs(codec, cfg->hp_outs,
|
|
|
+ spec->multiout.hp_out_nid,
|
|
|
+ spec->hp_paths);
|
|
|
+ if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
|
|
|
+ refill_shared_dacs(codec, cfg->speaker_outs,
|
|
|
+ spec->multiout.extra_out_nid,
|
|
|
+ spec->speaker_paths);
|
|
|
+
|
|
|
return badness;
|
|
|
}
|
|
|
|
|
@@ -1610,14 +1641,15 @@ static int ch_mode_info(struct snd_kcontrol *kcontrol,
|
|
|
{
|
|
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
struct hda_gen_spec *spec = codec->spec;
|
|
|
+ int chs;
|
|
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
|
|
uinfo->count = 1;
|
|
|
uinfo->value.enumerated.items = spec->multi_ios + 1;
|
|
|
if (uinfo->value.enumerated.item > spec->multi_ios)
|
|
|
uinfo->value.enumerated.item = spec->multi_ios;
|
|
|
- sprintf(uinfo->value.enumerated.name, "%dch",
|
|
|
- (uinfo->value.enumerated.item + 1) * 2);
|
|
|
+ chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
|
|
|
+ sprintf(uinfo->value.enumerated.name, "%dch", chs);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1626,7 +1658,8 @@ static int ch_mode_get(struct snd_kcontrol *kcontrol,
|
|
|
{
|
|
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
struct hda_gen_spec *spec = codec->spec;
|
|
|
- ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
|
|
|
+ ucontrol->value.enumerated.item[0] =
|
|
|
+ (spec->ext_channel_count - spec->min_channel_count) / 2;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1674,9 +1707,9 @@ static int ch_mode_put(struct snd_kcontrol *kcontrol,
|
|
|
ch = ucontrol->value.enumerated.item[0];
|
|
|
if (ch < 0 || ch > spec->multi_ios)
|
|
|
return -EINVAL;
|
|
|
- if (ch == (spec->ext_channel_count - 1) / 2)
|
|
|
+ if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
|
|
|
return 0;
|
|
|
- spec->ext_channel_count = (ch + 1) * 2;
|
|
|
+ spec->ext_channel_count = ch * 2 + spec->min_channel_count;
|
|
|
for (i = 0; i < spec->multi_ios; i++)
|
|
|
set_multi_io(codec, i, i < ch);
|
|
|
spec->multiout.max_channels = max(spec->ext_channel_count,
|
|
@@ -3127,17 +3160,16 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
|
|
|
- /* check the multiple speaker pins */
|
|
|
- if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
|
|
|
- spec->const_channel_count = cfg->line_outs * 2;
|
|
|
- else
|
|
|
- spec->const_channel_count = cfg->speaker_outs * 2;
|
|
|
-
|
|
|
- if (spec->multi_ios > 0)
|
|
|
- spec->multiout.max_channels = max(spec->ext_channel_count,
|
|
|
- spec->const_channel_count);
|
|
|
- else
|
|
|
- spec->multiout.max_channels = spec->multiout.num_dacs * 2;
|
|
|
+ spec->const_channel_count = spec->ext_channel_count;
|
|
|
+ /* check the multiple speaker and headphone pins */
|
|
|
+ if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
|
|
|
+ spec->const_channel_count = max(spec->const_channel_count,
|
|
|
+ cfg->speaker_outs * 2);
|
|
|
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT)
|
|
|
+ spec->const_channel_count = max(spec->const_channel_count,
|
|
|
+ cfg->hp_outs * 2);
|
|
|
+ spec->multiout.max_channels = max(spec->ext_channel_count,
|
|
|
+ spec->const_channel_count);
|
|
|
|
|
|
err = check_auto_mute_availability(codec);
|
|
|
if (err < 0)
|