summaryrefslogtreecommitdiff
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorBard Liao <yung-chuan.liao@linux.intel.com>2023-06-07 06:12:41 +0300
committerMark Brown <broonie@kernel.org>2023-06-13 14:11:15 +0300
commitac950278b0872c87bcef6153fd9c119265c8ba83 (patch)
treefba11f9cc381cd193afc6053bdaf54d313268220 /sound/soc/soc-pcm.c
parent597d364cd7b447aff5668639b90ec33ea420eaa2 (diff)
downloadlinux-ac950278b0872c87bcef6153fd9c119265c8ba83.tar.xz
ASoC: add N cpus to M codecs dai link support
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 patch 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. When a dailink contains two or more cpu DAIs, we should set channel number of cpus based on its channel mask. The new struct also provides channel mask information for each codec and we can construct the cpu channel mask by combining all codec channel masks which map to the cpu. The N:M mapping is however restricted to the N <= M case due to physical restrictions on a time-multiplexed bus such as I2S/TDM, AC97, SoundWire and HDaudio. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20230607031242.1032060-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 799865a6eb56..60cfbe565759 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1034,6 +1034,10 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
}
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
+ struct snd_pcm_hw_params cpu_params;
+ unsigned int ch_mask = 0;
+ int j;
+
/*
* Skip CPUs which don't support the current stream
* type. See soc_pcm_init_runtime_hw() for more details
@@ -1041,13 +1045,32 @@ static int __soc_pcm_hw_params(struct snd_soc_pcm_runtime *rtd,
if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
continue;
- ret = snd_soc_dai_hw_params(cpu_dai, substream, params);
+ /* copy params for each cpu */
+ cpu_params = *params;
+
+ if (!rtd->dai_link->codec_ch_maps)
+ goto hw_params;
+ /*
+ * construct cpu channel mask by combining ch_mask of each
+ * codec which maps to the cpu.
+ */
+ for_each_rtd_codec_dais(rtd, j, codec_dai) {
+ if (rtd->dai_link->codec_ch_maps[j].connected_cpu_id == i)
+ ch_mask |= rtd->dai_link->codec_ch_maps[j].ch_mask;
+ }
+
+ /* fixup cpu channel number */
+ if (ch_mask)
+ soc_pcm_codec_params_fixup(&cpu_params, ch_mask);
+
+hw_params:
+ ret = snd_soc_dai_hw_params(cpu_dai, substream, &cpu_params);
if (ret < 0)
goto out;
/* store the parameters for each DAI */
- soc_pcm_set_dai_params(cpu_dai, params);
- snd_soc_dapm_update_dai(substream, params, cpu_dai);
+ soc_pcm_set_dai_params(cpu_dai, &cpu_params);
+ snd_soc_dapm_update_dai(substream, &cpu_params, cpu_dai);
}
ret = snd_soc_pcm_component_hw_params(substream, params);
@@ -2789,9 +2812,22 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
cpu_dai = asoc_rtd_to_cpu(rtd, 0);
} else if (dai_link->num_cpus == dai_link->num_codecs) {
cpu_dai = asoc_rtd_to_cpu(rtd, i);
+ } else if (rtd->dai_link->num_codecs > rtd->dai_link->num_cpus) {
+ int cpu_id;
+
+ if (!rtd->dai_link->codec_ch_maps) {
+ dev_err(rtd->card->dev, "%s: no codec channel mapping table provided\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ cpu_id = rtd->dai_link->codec_ch_maps[i].connected_cpu_id;
+ cpu_dai = asoc_rtd_to_cpu(rtd, cpu_id);
} else {
dev_err(rtd->card->dev,
- "N cpus to M codecs link is not supported yet\n");
+ "%s codec number %d < cpu number %d is not supported\n",
+ __func__, rtd->dai_link->num_codecs,
+ rtd->dai_link->num_cpus);
return -EINVAL;
}