mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
ASoC: soc-pcm: Apply snd_soc_dai_link_ch_map.codec_ch_mask to codec params
In __soc_pcm_hw_params() if there is a snd_soc_dai_link_ch_map with
non-zero codec_ch_mask, use that channel mask to restrict which channels
are enabled on the codec. But only if there isn't a TDM mask.
It is possible that a snd_soc_dai_link_ch_map could include the same codec
multiple times on different CPUs so the for_each_rtd_ch_maps() loop
accumulates the channel masks for all entries of that codec.
If a TDM mask was also set, it takes priority and is used instead of any
possible snd_soc_dai_link_ch_map entries. (They cannot be ANDed together
because the bit positions are indicating different things: TDM is a bit
for each TDM slot, codec_ch_mask is a bit for each codec channel.)
This fixes a problem of incorrect TX channels enabled on the codec when
multiple codecs are aggregated on a single capture link. For example:
- Two CPUs with six 4-channel codecs.
- The machine driver chooses to assign one channel from each codec to
one channel on the CPU
- But the codec hw_params() would be passed a channel count of 6, which
(a) is more channels than the codec has and (b) allows enabling channels
that should not be driving the audio bus.
Fixes: ac950278b0 ("ASoC: add N cpus to M codecs dai link support")
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260910114500.1586637-4-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
88b14c0d0b
commit
6b382bdfe2
|
|
@ -1206,7 +1206,9 @@ static int __soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
goto out;
|
||||
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai) {
|
||||
unsigned int tdm_mask = snd_soc_dai_tdm_mask_get(codec_dai, substream->stream);
|
||||
unsigned int ch_mask = snd_soc_dai_tdm_mask_get(codec_dai, substream->stream);
|
||||
struct snd_soc_dai_link_ch_map *ch_maps;
|
||||
int j;
|
||||
|
||||
/*
|
||||
* Skip CODECs which don't support the current stream type,
|
||||
|
|
@ -1228,9 +1230,15 @@ static int __soc_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
/* copy params for each codec */
|
||||
tmp_params = *params;
|
||||
|
||||
/* fixup params based on TDM slot masks */
|
||||
if (tdm_mask)
|
||||
soc_pcm_codec_params_fixup(&tmp_params, tdm_mask);
|
||||
/* fixup params based on TDM or ch_map masks */
|
||||
if (!ch_mask) {
|
||||
for_each_rtd_ch_maps(rtd, j, ch_maps)
|
||||
if (ch_maps->codec == i)
|
||||
ch_mask |= ch_maps->codec_ch_mask;
|
||||
}
|
||||
|
||||
if (ch_mask)
|
||||
soc_pcm_codec_params_fixup(&tmp_params, ch_mask);
|
||||
|
||||
ret = snd_soc_dai_hw_params(codec_dai, substream,
|
||||
&tmp_params);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user