On 6/7/23 04:29, Richard Fitzgerald wrote: > 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. Humm, that's not really true. Each SoundWire link and the CPU DAI they expose are handled by different auxiliary devices with their own pm_runtime handling. > 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. This is questionable when the CPUs are connected to different links. SoundWire is not a giant switch matrix, there's a clear parent-child dependency and limited scope. Example topology for a 2 link/4 amplifier solution. link1 CPU DAI1 - Codec1 DAI1 - Codec2 DAI1 link2 CPU DAI1 - Codec1 DAI1 - Codec2 DAI1 There is no physical or logical connection between link2 CPU DAI1 and the two Codec1 DAI1 and Codec2 DAI1. I don't think it's wise to make DAPM connections between devices that are not on the same link. Each link is clock- and powered-managed separately, I only see trouble ahead with such virtual connections. 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; > } > } >