diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-01-07 10:44:06 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-12 02:44:08 -0500 |
commit | a07a949be6eb1c9aab06adaadce72dbd27b7d9cb (patch) | |
tree | 728f1ff2218cf11fc4440878440a93ae143a994c /sound | |
parent | affdb62b815b38261f09f9d4ec210a35c7ffb1f3 (diff) |
ALSA: hda - Fix multi-io channel mode management
The multi-io channels can vary not only from 1 to 6 but also may vary
from 6 to 8 or such. At the same time, there are more speaker pins
available than the primary output pins. So, we need three variables
to check: the minimum channel counts for primary outputs, the current
channel counts for primary outputs, and the minimum channel counts for
all outputs.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_generic.c | 92 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.h | 16 |
2 files changed, 76 insertions, 32 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 1fbc1b32359c..afa54f87b691 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -1125,6 +1125,25 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx) | |||
1125 | return snd_hda_get_path_idx(codec, path); | 1125 | return snd_hda_get_path_idx(codec, path); |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | /* fill the empty entries in the dac array for speaker/hp with the | ||
1129 | * shared dac pointed by the paths | ||
1130 | */ | ||
1131 | static void refill_shared_dacs(struct hda_codec *codec, int num_outs, | ||
1132 | hda_nid_t *dacs, int *path_idx) | ||
1133 | { | ||
1134 | struct nid_path *path; | ||
1135 | int i; | ||
1136 | |||
1137 | for (i = 0; i < num_outs; i++) { | ||
1138 | if (dacs[i]) | ||
1139 | continue; | ||
1140 | path = snd_hda_get_path_from_idx(codec, path_idx[i]); | ||
1141 | if (!path) | ||
1142 | continue; | ||
1143 | dacs[i] = path->path[0]; | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1128 | /* fill in the dac_nids table from the parsed pin configuration */ | 1147 | /* fill in the dac_nids table from the parsed pin configuration */ |
1129 | static int fill_and_eval_dacs(struct hda_codec *codec, | 1148 | static int fill_and_eval_dacs(struct hda_codec *codec, |
1130 | bool fill_hardwired, | 1149 | bool fill_hardwired, |
@@ -1183,19 +1202,6 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1183 | spec->private_dac_nids, spec->out_paths, | 1202 | spec->private_dac_nids, spec->out_paths, |
1184 | &main_out_badness); | 1203 | &main_out_badness); |
1185 | 1204 | ||
1186 | /* re-count num_dacs and squash invalid entries */ | ||
1187 | spec->multiout.num_dacs = 0; | ||
1188 | for (i = 0; i < cfg->line_outs; i++) { | ||
1189 | if (spec->private_dac_nids[i]) | ||
1190 | spec->multiout.num_dacs++; | ||
1191 | else { | ||
1192 | memmove(spec->private_dac_nids + i, | ||
1193 | spec->private_dac_nids + i + 1, | ||
1194 | sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); | ||
1195 | spec->private_dac_nids[cfg->line_outs - 1] = 0; | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | if (fill_mio_first && | 1205 | if (fill_mio_first && |
1200 | cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 1206 | cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
1201 | /* try to fill multi-io first */ | 1207 | /* try to fill multi-io first */ |
@@ -1246,16 +1252,41 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1246 | if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2) | 1252 | if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2) |
1247 | spec->multi_ios = 1; /* give badness */ | 1253 | spec->multi_ios = 1; /* give badness */ |
1248 | 1254 | ||
1255 | /* re-count num_dacs and squash invalid entries */ | ||
1256 | spec->multiout.num_dacs = 0; | ||
1257 | for (i = 0; i < cfg->line_outs; i++) { | ||
1258 | if (spec->private_dac_nids[i]) | ||
1259 | spec->multiout.num_dacs++; | ||
1260 | else { | ||
1261 | memmove(spec->private_dac_nids + i, | ||
1262 | spec->private_dac_nids + i + 1, | ||
1263 | sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); | ||
1264 | spec->private_dac_nids[cfg->line_outs - 1] = 0; | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | spec->ext_channel_count = spec->min_channel_count = | ||
1269 | spec->multiout.num_dacs; | ||
1270 | |||
1249 | if (spec->multi_ios == 2) { | 1271 | if (spec->multi_ios == 2) { |
1250 | for (i = 0; i < 2; i++) | 1272 | for (i = 0; i < 2; i++) |
1251 | spec->private_dac_nids[spec->multiout.num_dacs++] = | 1273 | spec->private_dac_nids[spec->multiout.num_dacs++] = |
1252 | spec->multi_io[i].dac; | 1274 | spec->multi_io[i].dac; |
1253 | spec->ext_channel_count = 2; | ||
1254 | } else if (spec->multi_ios) { | 1275 | } else if (spec->multi_ios) { |
1255 | spec->multi_ios = 0; | 1276 | spec->multi_ios = 0; |
1256 | badness += BAD_MULTI_IO; | 1277 | badness += BAD_MULTI_IO; |
1257 | } | 1278 | } |
1258 | 1279 | ||
1280 | /* re-fill the shared DAC for speaker / headphone */ | ||
1281 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) | ||
1282 | refill_shared_dacs(codec, cfg->hp_outs, | ||
1283 | spec->multiout.hp_out_nid, | ||
1284 | spec->hp_paths); | ||
1285 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) | ||
1286 | refill_shared_dacs(codec, cfg->speaker_outs, | ||
1287 | spec->multiout.extra_out_nid, | ||
1288 | spec->speaker_paths); | ||
1289 | |||
1259 | return badness; | 1290 | return badness; |
1260 | } | 1291 | } |
1261 | 1292 | ||
@@ -1610,14 +1641,15 @@ static int ch_mode_info(struct snd_kcontrol *kcontrol, | |||
1610 | { | 1641 | { |
1611 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1642 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1612 | struct hda_gen_spec *spec = codec->spec; | 1643 | struct hda_gen_spec *spec = codec->spec; |
1644 | int chs; | ||
1613 | 1645 | ||
1614 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1646 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1615 | uinfo->count = 1; | 1647 | uinfo->count = 1; |
1616 | uinfo->value.enumerated.items = spec->multi_ios + 1; | 1648 | uinfo->value.enumerated.items = spec->multi_ios + 1; |
1617 | if (uinfo->value.enumerated.item > spec->multi_ios) | 1649 | if (uinfo->value.enumerated.item > spec->multi_ios) |
1618 | uinfo->value.enumerated.item = spec->multi_ios; | 1650 | uinfo->value.enumerated.item = spec->multi_ios; |
1619 | sprintf(uinfo->value.enumerated.name, "%dch", | 1651 | chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count; |
1620 | (uinfo->value.enumerated.item + 1) * 2); | 1652 | sprintf(uinfo->value.enumerated.name, "%dch", chs); |
1621 | return 0; | 1653 | return 0; |
1622 | } | 1654 | } |
1623 | 1655 | ||
@@ -1626,7 +1658,8 @@ static int ch_mode_get(struct snd_kcontrol *kcontrol, | |||
1626 | { | 1658 | { |
1627 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1659 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1628 | struct hda_gen_spec *spec = codec->spec; | 1660 | struct hda_gen_spec *spec = codec->spec; |
1629 | ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2; | 1661 | ucontrol->value.enumerated.item[0] = |
1662 | (spec->ext_channel_count - spec->min_channel_count) / 2; | ||
1630 | return 0; | 1663 | return 0; |
1631 | } | 1664 | } |
1632 | 1665 | ||
@@ -1674,9 +1707,9 @@ static int ch_mode_put(struct snd_kcontrol *kcontrol, | |||
1674 | ch = ucontrol->value.enumerated.item[0]; | 1707 | ch = ucontrol->value.enumerated.item[0]; |
1675 | if (ch < 0 || ch > spec->multi_ios) | 1708 | if (ch < 0 || ch > spec->multi_ios) |
1676 | return -EINVAL; | 1709 | return -EINVAL; |
1677 | if (ch == (spec->ext_channel_count - 1) / 2) | 1710 | if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2) |
1678 | return 0; | 1711 | return 0; |
1679 | spec->ext_channel_count = (ch + 1) * 2; | 1712 | spec->ext_channel_count = ch * 2 + spec->min_channel_count; |
1680 | for (i = 0; i < spec->multi_ios; i++) | 1713 | for (i = 0; i < spec->multi_ios; i++) |
1681 | set_multi_io(codec, i, i < ch); | 1714 | set_multi_io(codec, i, i < ch); |
1682 | spec->multiout.max_channels = max(spec->ext_channel_count, | 1715 | spec->multiout.max_channels = max(spec->ext_channel_count, |
@@ -3127,17 +3160,16 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
3127 | if (err < 0) | 3160 | if (err < 0) |
3128 | return err; | 3161 | return err; |
3129 | 3162 | ||
3130 | /* check the multiple speaker pins */ | 3163 | spec->const_channel_count = spec->ext_channel_count; |
3131 | if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 3164 | /* check the multiple speaker and headphone pins */ |
3132 | spec->const_channel_count = cfg->line_outs * 2; | 3165 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) |
3133 | else | 3166 | spec->const_channel_count = max(spec->const_channel_count, |
3134 | spec->const_channel_count = cfg->speaker_outs * 2; | 3167 | cfg->speaker_outs * 2); |
3135 | 3168 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) | |
3136 | if (spec->multi_ios > 0) | 3169 | spec->const_channel_count = max(spec->const_channel_count, |
3137 | spec->multiout.max_channels = max(spec->ext_channel_count, | 3170 | cfg->hp_outs * 2); |
3138 | spec->const_channel_count); | 3171 | spec->multiout.max_channels = max(spec->ext_channel_count, |
3139 | else | 3172 | spec->const_channel_count); |
3140 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
3141 | 3173 | ||
3142 | err = check_auto_mute_availability(codec); | 3174 | err = check_auto_mute_availability(codec); |
3143 | if (err < 0) | 3175 | if (err < 0) |
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 00a1eab2c0b2..b65769cbde2b 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h | |||
@@ -117,8 +117,20 @@ struct hda_gen_spec { | |||
117 | unsigned int cur_mux[3]; | 117 | unsigned int cur_mux[3]; |
118 | 118 | ||
119 | /* channel model */ | 119 | /* channel model */ |
120 | int const_channel_count; /* min. channel count (for speakers) */ | 120 | /* min_channel_count contains the minimum channel count for primary |
121 | int ext_channel_count; /* current channel count for multi-io */ | 121 | * outputs. When multi_ios is set, the channels can be configured |
122 | * between min_channel_count and (min_channel_count + multi_ios * 2). | ||
123 | * | ||
124 | * ext_channel_count contains the current channel count of the primary | ||
125 | * out. This varies in the range above. | ||
126 | * | ||
127 | * Meanwhile, const_channel_count is the channel count for all outputs | ||
128 | * including headphone and speakers. It's a constant value, and the | ||
129 | * PCM is set up as max(ext_channel_count, const_channel_count). | ||
130 | */ | ||
131 | int min_channel_count; /* min. channel count for primary out */ | ||
132 | int ext_channel_count; /* current channel count for primary */ | ||
133 | int const_channel_count; /* channel count for all */ | ||
122 | 134 | ||
123 | /* PCM information */ | 135 | /* PCM information */ |
124 | struct hda_pcm pcm_rec[3]; /* used in build_pcms() */ | 136 | struct hda_pcm pcm_rec[3]; /* used in build_pcms() */ |