On 07/06/2023 04:12, Bard Liao wrote:
Currently, ASoC supports dailinks with the following mappings: 1 cpu DAI to N codec DAIs N cpu DAIs to N codec DAIs But the mapping between N cpu DAIs and M codec DAIs is not supported. The reason is that we didn't have a mechanism to map cpu and codec DAIs
This series suggests a new snd_soc_dai_link_codec_ch_map struct in struct snd_soc_dai_link{} which provides codec DAI to cpu DAI mapping information used to implement N cpu DAIs to M codec DAIs support.
And add the codec_ch_maps to SOF SoundWire machine driver.
I think there is a much simpler way to handle this. The existing ASoC code is trying to map CPU to CODEC to match the physical connection. But the physical connection is not important. The dailink represents the _logical_ link.
You are declaring that all the CPU and CODEC in the dailink behave as a single logical link. So you can just connect all CPUs to all CODECS.
That also fixes a problem with the existing N CPU to N CODEC mapping. It assumes that means CPU0 is connected to CODEC0, CPU1 is connected to CODEC1, ... But that isn't necessarily true. You could have an N:N mapping where multiple CPUs have been combined to create a multi-channel stream that is sent to all CODECs. But the existing N:N code won't hook that up correctly.
I suggest that the simple fix is this:
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5d9a671e50f1..f4f955a991d5 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4423,8 +4423,8 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; - struct snd_soc_dai *codec_dai; - int i; + struct snd_soc_dai *codec_dai, *cpu_dai; + int i, j;
/* for each BE DAI link... */ for_each_card_rtds(card, rtd) { @@ -4435,17 +4435,9 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) if (rtd->dai_link->dynamic) continue;
- if (rtd->dai_link->num_cpus == 1) { - for_each_rtd_codec_dais(rtd, i, codec_dai) - dapm_connect_dai_pair(card, rtd, codec_dai, - asoc_rtd_to_cpu(rtd, 0)); - } else if (rtd->dai_link->num_codecs == rtd->dai_link->num_cpus) { - for_each_rtd_codec_dais(rtd, i, codec_dai) - dapm_connect_dai_pair(card, rtd, codec_dai, - asoc_rtd_to_cpu(rtd, i)); - } else { - dev_err(card->dev, - "N cpus to M codecs link is not supported yet\n"); + for_each_rtd_codec_dais(rtd, i, codec_dai) { + for_each_rtd_cpu_dais(rtd, j, cpu_dai) + dapm_connect_dai_pair(card, rtd, codec_dai, cpu_dai); } } } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7958c9defd49..43b1166eb333 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2747,7 +2747,7 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, int *playback, int *capture) { struct snd_soc_dai *cpu_dai; - int i; + int i, j;
if (rtd->dai_link->dynamic && rtd->dai_link->num_cpus > 1) { dev_err(rtd->dev, @@ -2801,22 +2801,14 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
for_each_rtd_codec_dais(rtd, i, codec_dai) { - if (rtd->dai_link->num_cpus == 1) { - cpu_dai = asoc_rtd_to_cpu(rtd, 0); - } else if (rtd->dai_link->num_cpus == rtd->dai_link->num_codecs) { - cpu_dai = asoc_rtd_to_cpu(rtd, i); - } else { - dev_err(rtd->card->dev, - "N cpus to M codecs link is not supported yet\n"); - return -EINVAL; + for_each_rtd_cpu_dais(rtd, j, cpu_dai) { + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && + snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) + *playback = 1; + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && + snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) + *capture = 1; } - - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && - snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) - *playback = 1; - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && - snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) - *capture = 1; } }