[PATCH 4/4] ASoC: soc-pcm: ignore dummy-DAI at soc_pcm_params_symmetry()

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Fri Apr 16 04:00:32 CEST 2021


From: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>

soc_pcm_params_symmetry() checks CPU / Codec symmetry.
Unfortunately there was bug on it (= A) which didn't check Codec.
But is back by (B).

	A: v5.7:  commit c840f7698d26 ("ASoC: soc-pcm: Merge for_each_rtd_cpu/codec_dais()")
	B: v5.12: commit 3a9067211122 ("ASoC: soc-pcm: cleanup soc_pcm_params_symmetry()")

In total,
old - v5.6 (= Generation-1):

	symmetric_rate		: DAI_Link / CPU / Codec
	symmetric_channels	: DAI_Link / CPU / Codec
	symmetric_sample_bits	: DAI_Link / CPU / Codec

v5.7 - v5.11 (= Generation-2): (= because of bug by (A))

	symmetric_rate		: DAI_Link / CPU
	symmetric_channels	: DAI_Link / CPU / Codec
	symmetric_sample_bits	: DAI_Link / CPU / Codec

v5.12 - (= Generation-3): (= back by (B))

	symmetric_rate		: DAI_Link / CPU / Codec
	symmetric_channels	: DAI_Link / CPU / Codec
	symmetric_sample_bits	: DAI_Link / CPU / Codec

OTOH, we can use DPCM which is configured by FE / BE.
Both FE / BE uses dummy-DAI.

	FE: CPU       <-> dummy-DAI
	BE: dummy-DAI <-> Codec

One note is that we can use .be_hw_params_fixup in DPCM case.
This means BE settings might be fixuped/updated by FE.
This feature is used for example on MIXer case.
It can be happen not only for rate, but for channels/sample_bits too.

Because of these reasons, below issue happen on
Generation-1 / Generation-3, if...

	1) Sound Card used DPCM
	2) It exchanges rate to 48kHz by using .be_hw_params_fixup()
	3) Codec had symmetric_rate = 1

I didn't confirm, but maybe same things happen
if it exchanged channels/sample_bits at Generation-1/2/3 too.

	# aplay 44100.wav
	# aplay 44100.wav
=>	[kernel] be.ak4613-hifi: ASoC: unmatched rate symmetry: snd-soc-dummy-dai:44100 - soc_pcm_params_symmetry:48000
	[kernel] be.ak4613-hifi: ASoC: hw_params BE failed -22
	[kernel] fe.rsnd-dai.0: ASoC: hw_params BE failed -22
	aplay: set_params:1407: Unable to install hw params:
	ACCESS:  RW_INTERLEAVED
	FORMAT:  S16_LE
	SUBFORMAT:  STD
	SAMPLE_BITS: 16
	FRAME_BITS: 32
	CHANNELS: 2
	RATE: 44100
	PERIOD_TIME: (23219 23220)
	PERIOD_SIZE: 1024
	PERIOD_BYTES: 4096
	PERIODS: 4
	BUFFER_TIME: (92879 92880)
	BUFFER_SIZE: 4096
	BUFFER_BYTES: 16384
	TICK_TIME: 0

soc_pcm_params_symmetry() checks by below

	if (symmetry)
		for_each_rtd_cpu_dais(rtd, i, cpu_dai)
			if (cpu_dai->xxx && cpu_dai->xxx != d.xxx) {
				dev_err(rtd->dev, "...");
				return -EINVAL;
			}

Because of above reason 3) (= Codec had symmetric_rate = 1)
BE can't ignore "if (symmetric)".

At 1st aplay, soc_pcm_params_symmetry() ignores it,
because dummy-DAI->rate is 0.
After this check, each DAI sets/keep settings.

In above sample case, BE gets 48000 and FE gets 44100,
and it happen BE -> FE order.
Because DPCM is sharing *same* dummy-DAI,
dummy-DAI sets as 48000 by BE, and is overwrote by 44100 by FE.

This settings never be cleaned (= a) after 1st aplay,
because dummy-DAI is used from FE/BE, never be last user (b).

	static int soc_pcm_hw_clean(...)
	{
		...
		for_each_rtd_dais(rtd, i, dai) {
			...
(b)			if (snd_soc_dai_active(dai) == 1)
(a)				soc_pcm_set_dai_params(dai, NULL);
			...
		}
		...
	}

At 2nd aplay, BE gets 48000 but dummy-DAI is keeping 44100,
soc_pcm_params_symmetry() checks will fail.

To solve this issue, this patch ignores dummy-DAI
at soc_pcm_params_symmetry()

Link: https://lore.kernel.org/r/87a6q0z4xt.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 sound/soc/soc-pcm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 09d63cbbc602..327bb91ee28e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -394,7 +394,8 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
 									\
 	if (symmetry)							\
 		for_each_rtd_cpu_dais(rtd, i, cpu_dai)			\
-			if (cpu_dai->xxx && cpu_dai->xxx != d.xxx) {	\
+			if (!snd_soc_dai_is_dummy(cpu_dai) &&		\
+			    cpu_dai->xxx && cpu_dai->xxx != d.xxx) {	\
 				dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \
 					#xxx, cpu_dai->name, cpu_dai->xxx, d.name, d.xxx); \
 				return -EINVAL;				\
-- 
2.25.1



More information about the Alsa-devel mailing list