[RFC PATCH 01/23] ASoC: soc-core: allow default ch_maps on links with more than 8 DAIs
From: Srinivas Kandagatla
Date: Fri Oct 23 2026 - 13:18:36 EST
snd_soc_compensate_channel_connection_map() builds the default channel
map from static 8-entry arrays and fails the card for links with more
DAIs. A speaker protection link carrying both the amplifier and the V/I
sense codec DAIs of four speakers has about sixteen.
Keep the static arrays for links that fit, and allocate a per-link map
with the same 1:1, 1:N or N:1 layout for those that do not.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxxxxxxxx>
---
sound/soc/soc-core.c | 46 +++++++++++++++++++++++++++++++-------------
1 file changed, 33 insertions(+), 13 deletions(-)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 97269b4ee4ca..34d02a39de90 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -915,20 +915,40 @@ static int snd_soc_compensate_channel_connection_map(struct snd_soc_card *card,
if (dai_link->ch_maps)
goto sanity_check;
- /* check default map size */
- if (dai_link->num_cpus > MAX_DEFAULT_CH_MAP_SIZE ||
- dai_link->num_codecs > MAX_DEFAULT_CH_MAP_SIZE) {
- dev_err(card->dev, "soc-core.c needs update default_connection_maps");
- return -EINVAL;
- }
+ /*
+ * Links wider than the static defaults get their own map. The N:M
+ * check above leaves a single DAI on the shorter side, at index 0.
+ */
+ if (dai_link->num_cpus <= MAX_DEFAULT_CH_MAP_SIZE &&
+ dai_link->num_codecs <= MAX_DEFAULT_CH_MAP_SIZE) {
+ if (dai_link->num_cpus == dai_link->num_codecs)
+ dai_link->ch_maps = default_ch_map_sync; /* for 1:1 or N:N */
+ else if (dai_link->num_cpus < dai_link->num_codecs)
+ dai_link->ch_maps = default_ch_map_1cpu; /* for 1:N */
+ else
+ dai_link->ch_maps = default_ch_map_1codec; /* for N:1 */
+ } else {
+ int num_maps = max(dai_link->num_cpus, dai_link->num_codecs);
- /* Compensate missing map for ... */
- if (dai_link->num_cpus == dai_link->num_codecs)
- dai_link->ch_maps = default_ch_map_sync; /* for 1:1 or N:N */
- else if (dai_link->num_cpus < dai_link->num_codecs)
- dai_link->ch_maps = default_ch_map_1cpu; /* for 1:N */
- else
- dai_link->ch_maps = default_ch_map_1codec; /* for N:1 */
+ ch_maps = devm_kcalloc(card->dev, num_maps, sizeof(*ch_maps),
+ GFP_KERNEL);
+ if (!ch_maps)
+ return -ENOMEM;
+
+ if (dai_link->num_cpus == dai_link->num_codecs) {
+ for (i = 0; i < num_maps; i++) {
+ ch_maps[i].cpu = i;
+ ch_maps[i].codec = i;
+ }
+ } else if (dai_link->num_cpus < dai_link->num_codecs) {
+ for (i = 0; i < num_maps; i++)
+ ch_maps[i].codec = i; /* cpu stays 0 */
+ } else {
+ for (i = 0; i < num_maps; i++)
+ ch_maps[i].cpu = i; /* codec stays 0 */
+ }
+ dai_link->ch_maps = ch_maps;
+ }
sanity_check:
dev_dbg(card->dev, "dai_link %s\n", dai_link->stream_name);
--
2.47.3