diff mbox series

[08/20] ASoC: soc-pcm.c: cleanup soc_get_playback_capture()

Message ID 87r0rep4we.wl-kuninori.morimoto.gx@renesas.com
State New
Headers show
Series ASoC: replace dpcm_playback/capture to playback/capture_only | expand

Commit Message

Kuninori Morimoto May 18, 2023, 5:47 a.m. UTC
Current soc_get_playback_capture() (A) is checking playback/capture
availability for DPCM (X) / Normal (Y) / Codec2Codec (Z) connections.

(A)	static int soc_get_playback_capture(...)
	{
		...
 ^		if (dai_link->dynamic || dai_link->no_pcm) {
 |			...
 |(a)			if (dai_link->dpcm_playback) {
 |				...
 | ^				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
 |(*)					...
 | v				}
 |				...
(X)			}
 |(b)			if (dai_link->dpcm_capture) {
 |				...
 | ^				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
 |(*)					...
 | v				}
 |				...
 v			}
		} else {
 ^ ^			/* Adapt stream for codec2codec links */
 |(Z)			int cpu_capture = ...
 | v			int cpu_playback = ...
(Y)
 | ^			for_each_rtd_codec_dais(rtd, i, codec_dai) {
 |(*)				...
 v v			}
		}
		...
	}

(*) part is checking each DAI's availability.

At first, (X) part is for DPCM, and it checks playback/capture
availability if dai_link has dpcm_playback/capture flag (a)(b).
But we are already using playback/capture_only flag.
for Normal (Y) and Codec2Codec (Z). We can use this flags for DPCM too.

Before				After
	dpcm_playback = 1;	=>	/* no flags */
	dpcm_capture  = 1;

	dpcm_playback = 1;	=>	playback_only = 1;

	dpcm_capture = 1;	=>	capture_only = 1;

This patch enables both flags case, but dpcm_playback/capture flags
will be removed if all driver were switched to new playback/capture_only
flags.

Here, CPU <-> Codec relationship is like this

	DPCM
		[CPU/dummy]-[dummy/Codec]
		^^^^^^^^^^^
	Normal
		[CPU/Codec]
		^^^^^^^^^^^

(X) part is checking only CPU       DAI, and
(Y) part is checking both CPU/Codec DAI

This means (X)/(Y) are checking same position.
Because dammy DAI is always available,
we can share same code for all cases (= X/Y/Z).

This patch merge these.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/soc-pcm.c | 75 +++++++++++++--------------------------------
 1 file changed, 22 insertions(+), 53 deletions(-)

Comments

Amadeusz Sławiński May 18, 2023, 10:38 a.m. UTC | #1
On 5/18/2023 7:47 AM, Kuninori Morimoto wrote:
> Current soc_get_playback_capture() (A) is checking playback/capture
> availability for DPCM (X) / Normal (Y) / Codec2Codec (Z) connections.
> 
> (A)	static int soc_get_playback_capture(...)
> 	{
> 		...
>   ^		if (dai_link->dynamic || dai_link->no_pcm) {
>   |			...
>   |(a)			if (dai_link->dpcm_playback) {
>   |				...
>   | ^				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
>   |(*)					...
>   | v				}
>   |				...
> (X)			}
>   |(b)			if (dai_link->dpcm_capture) {
>   |				...
>   | ^				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
>   |(*)					...
>   | v				}
>   |				...
>   v			}
> 		} else {
>   ^ ^			/* Adapt stream for codec2codec links */
>   |(Z)			int cpu_capture = ...
>   | v			int cpu_playback = ...
> (Y)
>   | ^			for_each_rtd_codec_dais(rtd, i, codec_dai) {
>   |(*)				...
>   v v			}
> 		}
> 		...
> 	}
> 
> (*) part is checking each DAI's availability.
> 
> At first, (X) part is for DPCM, and it checks playback/capture
> availability if dai_link has dpcm_playback/capture flag (a)(b).
> But we are already using playback/capture_only flag.
> for Normal (Y) and Codec2Codec (Z). We can use this flags for DPCM too.
> 
> Before				After
> 	dpcm_playback = 1;	=>	/* no flags */
> 	dpcm_capture  = 1;
> 
> 	dpcm_playback = 1;	=>	playback_only = 1;
> 
> 	dpcm_capture = 1;	=>	capture_only = 1;
> 
> This patch enables both flags case, but dpcm_playback/capture flags
> will be removed if all driver were switched to new playback/capture_only
> flags.
> 
> Here, CPU <-> Codec relationship is like this
> 
> 	DPCM
> 		[CPU/dummy]-[dummy/Codec]
> 		^^^^^^^^^^^
> 	Normal
> 		[CPU/Codec]
> 		^^^^^^^^^^^
> 
> (X) part is checking only CPU       DAI, and
> (Y) part is checking both CPU/Codec DAI
> 
> This means (X)/(Y) are checking same position.
> Because dammy DAI is always available,
> we can share same code for all cases (= X/Y/Z).
> 
> This patch merge these.
> 
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> ---

Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Amadeusz Sławiński May 19, 2023, 9:57 a.m. UTC | #2
On 5/18/2023 7:47 AM, Kuninori Morimoto wrote:
> Current soc_get_playback_capture() (A) is checking playback/capture
> availability for DPCM (X) / Normal (Y) / Codec2Codec (Z) connections.
> 
> (A)	static int soc_get_playback_capture(...)
> 	{
> 		...
>   ^		if (dai_link->dynamic || dai_link->no_pcm) {
>   |			...
>   |(a)			if (dai_link->dpcm_playback) {
>   |				...
>   | ^				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
>   |(*)					...
>   | v				}
>   |				...
> (X)			}
>   |(b)			if (dai_link->dpcm_capture) {
>   |				...
>   | ^				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
>   |(*)					...
>   | v				}
>   |				...
>   v			}
> 		} else {
>   ^ ^			/* Adapt stream for codec2codec links */
>   |(Z)			int cpu_capture = ...
>   | v			int cpu_playback = ...
> (Y)
>   | ^			for_each_rtd_codec_dais(rtd, i, codec_dai) {
>   |(*)				...
>   v v			}
> 		}
> 		...
> 	}
> 
> (*) part is checking each DAI's availability.
> 
> At first, (X) part is for DPCM, and it checks playback/capture
> availability if dai_link has dpcm_playback/capture flag (a)(b).
> But we are already using playback/capture_only flag.
> for Normal (Y) and Codec2Codec (Z). We can use this flags for DPCM too.
> 
> Before				After
> 	dpcm_playback = 1;	=>	/* no flags */
> 	dpcm_capture  = 1;
> 
> 	dpcm_playback = 1;	=>	playback_only = 1;
> 
> 	dpcm_capture = 1;	=>	capture_only = 1;
> 
> This patch enables both flags case, but dpcm_playback/capture flags
> will be removed if all driver were switched to new playback/capture_only
> flags.
> 
> Here, CPU <-> Codec relationship is like this
> 
> 	DPCM
> 		[CPU/dummy]-[dummy/Codec]
> 		^^^^^^^^^^^
> 	Normal
> 		[CPU/Codec]
> 		^^^^^^^^^^^
> 
> (X) part is checking only CPU       DAI, and
> (Y) part is checking both CPU/Codec DAI
> 
> This means (X)/(Y) are checking same position.
> Because dammy DAI is always available,
> we can share same code for all cases (= X/Y/Z).
> 
> This patch merge these.
> 
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> ---
>   sound/soc/soc-pcm.c | 75 +++++++++++++--------------------------------
>   1 file changed, 22 insertions(+), 53 deletions(-)
> 
> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> index af5d4e1effdf..f47ddf660c57 100644
> --- a/sound/soc/soc-pcm.c
> +++ b/sound/soc/soc-pcm.c
> @@ -2732,7 +2732,10 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
>   				    int *playback, int *capture)
>   {
>   	struct snd_soc_dai_link *dai_link = rtd->dai_link;
> +	struct snd_soc_dai *codec_dai;
>   	struct snd_soc_dai *cpu_dai;
> +	int cpu_capture  = SNDRV_PCM_STREAM_CAPTURE;
> +	int cpu_playback = SNDRV_PCM_STREAM_PLAYBACK;
>   	int tmp_playback = 0;
>   	int tmp_capture  = 0;
>   	int i;
> @@ -2748,61 +2751,27 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
>   		return -EINVAL;
>   	}
>   
> -	if (dai_link->dynamic || dai_link->no_pcm) {
> -		int stream;
> -
> -		if (dai_link->dpcm_playback) {
> -			stream = SNDRV_PCM_STREAM_PLAYBACK;
> +	/* Adapt stream for codec2codec links */
> +	if (dai_link->c2c_params) {
> +		cpu_capture  = SNDRV_PCM_STREAM_PLAYBACK;
> +		cpu_playback = SNDRV_PCM_STREAM_CAPTURE;
> +	}
>   
> -			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> -				if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
> -					tmp_playback = 1;
> -					break;
> -				}
> -			}
> -			if (!tmp_playback) {
> -				dev_err(rtd->card->dev,
> -					"No CPU DAIs support playback for stream %s\n",
> -					dai_link->stream_name);
> -				return -EINVAL;
> -			}
> -		}
> -		if (dai_link->dpcm_capture) {
> -			stream = SNDRV_PCM_STREAM_CAPTURE;
> +	/* REMOVE ME */
> +	if (dai_link->dpcm_playback && !dai_link->dpcm_capture)
> +		dai_link->playback_only = 1;
> +	if (!dai_link->dpcm_playback && dai_link->dpcm_capture)
> +		dai_link->capture_only = 1;
>   
> -			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> -				if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
> -					tmp_capture = 1;
> -					break;
> -				}
> -			}
> -
> -			if (!tmp_capture) {
> -				dev_err(rtd->card->dev,
> -					"No CPU DAIs support capture for stream %s\n",
> -					dai_link->stream_name);
> -				return -EINVAL;
> -			}
> -		}
> -	} else {
> -		struct snd_soc_dai *codec_dai;
> -
> -		/* Adapt stream for codec2codec links */
> -		int cpu_capture = dai_link->c2c_params ?
> -			SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
> -		int cpu_playback = dai_link->c2c_params ?
> -			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
> -
> -		for_each_rtd_codec_dais(rtd, i, codec_dai) {
> -			cpu_dai = asoc_rtd_to_cpu(rtd, i);
> -
> -			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
> -			    snd_soc_dai_stream_valid(cpu_dai,   cpu_playback))
> -				tmp_playback = 1;
> -			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
> -			    snd_soc_dai_stream_valid(cpu_dai,   cpu_capture))
> -				tmp_capture = 1;
> -		}
> +	for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> +		codec_dai = asoc_rtd_to_codec(rtd, i); /* get paired codec */
> +
> +		if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
> +		    snd_soc_dai_stream_valid(cpu_dai,   cpu_playback))
> +			tmp_playback = 1;
> +		if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
> +		    snd_soc_dai_stream_valid(cpu_dai,   cpu_capture))
> +			tmp_capture = 1;
>   	}
>   
>   	if (dai_link->playback_only)

I put the patchset to test and it fails to enumerate devices on our 
platforms.

Bisect leads me to this patch, here is dmesg fragment:

[   34.609909] snd_soc_avs:avs_component_probe: avs_hdaudio 
avs_hdaudio.2: probing hdaudioB0D2-platform card hdaudioB0D2
[   34.612274] snd_soc_core:soc_tplg_load_header: avs_hdaudio 
avs_hdaudio.2: ASoC: Got 0x490 bytes of type 8 version 0 vendor 0 at pass 0
[   34.612456] snd_soc_core:soc_tplg_load_header: avs_hdaudio 
avs_hdaudio.2: ASoC: Got 0x7ec bytes of type 5 version 0 vendor 0 at pass 3
[   34.612477] snd_soc_core:soc_tplg_dapm_widget_elems_load: avs_hdaudio 
avs_hdaudio.2: ASoC: adding 6 DAPM widgets
[   34.612493] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio 
avs_hdaudio.2: ASoC: creating DAPM widget hdmi1_fe id 17
[   34.612774] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio 
avs_hdaudio.2: ASoC: creating DAPM widget hdmi1_be id 17
[   34.613025] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio 
avs_hdaudio.2: ASoC: creating DAPM widget hdmi2_fe id 17
[   34.613297] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio 
avs_hdaudio.2: ASoC: creating DAPM widget hdmi2_be id 17
[   34.613552] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio 
avs_hdaudio.2: ASoC: creating DAPM widget hdmi3_fe id 17
[   34.613823] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio 
avs_hdaudio.2: ASoC: creating DAPM widget hdmi3_be id 17
[   34.614077] snd_soc_core:soc_tplg_load_header: avs_hdaudio 
avs_hdaudio.2: ASoC: Got 0xab0 bytes of type 7 version 0 vendor 0 at pass 4
[   34.614272] snd_soc_core:snd_soc_register_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Registered DAI 'HDMI1-dai'
[   34.614290] snd_soc_core:snd_soc_dapm_new_dai_widgets: snd_soc_avs 
0000:00:0e.0: ASoC: adding HDMI1-playback widget
[   34.614453] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio 
avs_hdaudio.2: ASoC: binding HDMI1
[   34.615192] snd_soc_core:snd_soc_register_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Registered DAI 'HDMI2-dai'
[   34.615210] snd_soc_core:snd_soc_dapm_new_dai_widgets: snd_soc_avs 
0000:00:0e.0: ASoC: adding HDMI2-playback widget
[   34.615371] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio 
avs_hdaudio.2: ASoC: binding HDMI2
[   34.616060] snd_soc_core:snd_soc_register_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Registered DAI 'HDMI3-dai'
[   34.616077] snd_soc_core:snd_soc_dapm_new_dai_widgets: snd_soc_avs 
0000:00:0e.0: ASoC: adding HDMI3-playback widget
[   34.616235] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio 
avs_hdaudio.2: ASoC: binding HDMI3
[   34.616858] snd_soc_core:soc_tplg_pcm_elems_load: avs_hdaudio 
avs_hdaudio.2: ASoC: adding 3 PCM DAIs
[   34.616876] snd_soc_core:soc_tplg_load_header: avs_hdaudio 
avs_hdaudio.2: ASoC: Got 0x4a4 bytes of type 4 version 0 vendor 0 at pass 5
[   34.616895] snd_soc_core:soc_tplg_dapm_graph_elems_load: avs_hdaudio 
avs_hdaudio.2: ASoC: adding 9 DAPM routes for index 0
[   34.617601] avs_hdaudio avs_hdaudio.2: ASoC: Parent card not yet 
available, widget card binding deferred
[   34.618153] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio 
avs_hdaudio.2: ASoC: binding hdaudioB0D2 link0
[   34.618724] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio 
avs_hdaudio.2: ASoC: binding hdaudioB0D2 link1
[   34.619221] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio 
avs_hdaudio.2: ASoC: binding hdaudioB0D2 link2
[   34.619973]  probing-LINK: substream (null) has no playback, no capture
[   34.620016] avs_hdaudio avs_hdaudio.2: ASoC: can't create pcm (null) :-22
[   34.620196] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Unregistered DAI 'hdaudioB0D2-cpu0'
[   34.620309] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Unregistered DAI 'hdaudioB0D2-cpu1'
[   34.620419] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Unregistered DAI 'hdaudioB0D2-cpu2'
[   34.621254] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Unregistered DAI 'HDMI3-dai'
[   34.621837] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Unregistered DAI 'HDMI2-dai'
[   34.622704] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 
0000:00:0e.0: ASoC: Unregistered DAI 'HDMI1-dai'
[   34.623620] snd_soc_core:snd_soc_unregister_dai: snd_hda_codec_hdmi 
hdaudioB0D2: ASoC: Unregistered DAI 'HDMI 0'
[   34.623695] snd_soc_core:snd_soc_unregister_dai: snd_hda_codec_hdmi 
hdaudioB0D2: ASoC: Unregistered DAI 'HDMI 1'
[   34.623769] snd_soc_core:snd_soc_unregister_dai: snd_hda_codec_hdmi 
hdaudioB0D2: ASoC: Unregistered DAI 'HDMI 2'
[   34.624779] snd_hda_core:snd_hdac_display_power: snd_soc_avs 
0000:00:0e.0: display power disable
[   34.628057] avs_hdaudio: probe of avs_hdaudio.2 failed with error -22
Kuninori Morimoto May 22, 2023, 4:35 a.m. UTC | #3
Hi Amadeusz

Thank you for testing

> I put the patchset to test and it fails to enumerate devices on our 
> platforms.
> 
> Bisect leads me to this patch, here is dmesg fragment:
(snip)
> [   34.617601] avs_hdaudio avs_hdaudio.2: ASoC: Parent card not yet 
> available, widget card binding deferred
(snip)
> [   34.619973]  probing-LINK: substream (null) has no playback, no capture

Hmm..  I tested it on my many type of connections,
but couldn't reproduce the error...

It seems you got [01/20] patch error = no playback, no capture.
This means has_playback/capture both flags are 0.

It seems you are using soc-topology.
Is it topology specific something ?

But hmm.. ?

static int soc_get_playback_capture(...)
{
	...
(A)	if (dai_link->dynamic || dai_link->no_pcm) {
		...
		if (dai_link->dpcm_playback) {
			...
(B)			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
				...
			}
			...
		}
		if (dai_link->dpcm_capture) {
			...
(B)			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
				...
			}
		}
		...
	}
}

It checks CPU (B) when no_pcm (A) on original.
But I think "no_pcm - CPU" is dummy DAI -> above check is no meaning.
After the patch, it checks both CPU/Codec.

I wonder is your Codec which is connected to no_pcm DAI valid ?

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Amadeusz Sławiński May 22, 2023, 9:14 a.m. UTC | #4
On 5/22/2023 6:35 AM, Kuninori Morimoto wrote:
> 
> Hi Amadeusz
> 
> Thank you for testing
> 
>> I put the patchset to test and it fails to enumerate devices on our
>> platforms.
>>
>> Bisect leads me to this patch, here is dmesg fragment:
> (snip)
>> [   34.617601] avs_hdaudio avs_hdaudio.2: ASoC: Parent card not yet
>> available, widget card binding deferred
> (snip)
>> [   34.619973]  probing-LINK: substream (null) has no playback, no capture
> 
> Hmm..  I tested it on my many type of connections,
> but couldn't reproduce the error...
> 
> It seems you got [01/20] patch error = no playback, no capture.
> This means has_playback/capture both flags are 0.
> 
> It seems you are using soc-topology.
> Is it topology specific something ?
> 
> But hmm.. ?
> 
> static int soc_get_playback_capture(...)
> {
> 	...
> (A)	if (dai_link->dynamic || dai_link->no_pcm) {
> 		...
> 		if (dai_link->dpcm_playback) {
> 			...
> (B)			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> 				...
> 			}
> 			...
> 		}
> 		if (dai_link->dpcm_capture) {
> 			...
> (B)			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> 				...
> 			}
> 		}
> 		...
> 	}
> }
> 
> It checks CPU (B) when no_pcm (A) on original.
> But I think "no_pcm - CPU" is dummy DAI -> above check is no meaning.
> After the patch, it checks both CPU/Codec.

no_pcm means that we are describing Back End, if you check any file in 
sound/soc/intel/avs/boards, they set link->no_pcm to 1 - those files 
describe card and BE (codec) configuration.
Topology in case of our driver describe Front Ends (what is visible when 
you do "aplay -l"), as well as DSP path. Topology sets link->dynamic to 
1 in soc_tplg_fe_link_create().
Do note that card and topology are loaded separately hence the "card 
binding deferred" message in dmesg above.

> I wonder is your Codec which is connected to no_pcm DAI valid ?
> 

I'm not sure what do you mean, if it is valid? It works fine before this 
patch ;)
Kuninori Morimoto May 22, 2023, 11:49 p.m. UTC | #5
Hi Amadeusz

> > static int soc_get_playback_capture(...)
> > {
> > 	...
> > (A)	if (dai_link->dynamic || dai_link->no_pcm) {
> > 		...
> > 		if (dai_link->dpcm_playback) {
> > 			...
> > (B)			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> > 				...
> > 			}
> > 			...
> > 		}
> > 		if (dai_link->dpcm_capture) {
> > 			...
> > (B)			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
> > 				...
> > 			}
> > 		}
> > 		...
> > 	}
> > }
> > 
> > It checks CPU (B) when no_pcm (A) on original.
> > But I think "no_pcm - CPU" is dummy DAI -> above check is no meaning.
> > After the patch, it checks both CPU/Codec.
(snip)
> > I wonder is your Codec which is connected to no_pcm DAI valid ?
> 
> I'm not sure what do you mean, if it is valid? It works fine before this 
> patch ;)

Ah, sorry, let me explain detail.

	static int soc_get_playback_capture(...)
	{
		...
(A)		if (dai_link->dynamic || dai_link->no_pcm) {
			int stream;

			if (dai_link->dpcm_playback) {
				stream = SNDRV_PCM_STREAM_PLAYBACK;

(B)				for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
(C)					if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
						has_playback = 1;
						break;
					}
				}
			...
	}

Before appling the patch, in DPCM case (A), it checks CPU valid only (B)/(C).
In many case, DPCM is like this

	dynamic			no_pcm
	[CPU/dummy-Codec] - [dummy-CPU/Codec]

I noticed that before the patch, it checks dummy DAI only for no_pcm case.
But after appling the patch, it will check both CPU and Codec
valid (X)/(Y)/(Z).

I think this was changed after patch.
So, my question was what happen for snd_soc_dai_stream_valid() on your Codec.

# I notcied that avs_create_dai_links() is not using dummy CPU on no_pcm case...


	static int soc_get_playback_capture(...)
	{
		...
(X)		for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
(Y)			codec_dai = asoc_rtd_to_codec(rtd, i); /* get paired codec */

(Z)			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
(Z)			    snd_soc_dai_stream_valid(cpu_dai,   cpu_playback))
				has_playback = 1;
(Z)			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
(Z)			    snd_soc_dai_stream_valid(cpu_dai,   cpu_capture))
				has_capture = 1;
		}
		...
	}

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Kuninori Morimoto May 24, 2023, 11:48 p.m. UTC | #6
Hi Amadeusz
Cc Mark

Thank you for debuging/checking.

> > I noticed that before the patch, it checks dummy DAI only for no_pcm case.
> > But after appling the patch, it will check both CPU and Codec
> > valid (X)/(Y)/(Z).
(snip)
> sorry for small delay, I've debugged the issue. Seems like one less 
> critical problem is in ASoC HDA codec, which blocks HDA and HDMI probing 
> altogether in our driver, something like this should fix this:
(snip)
> @@ -341,6 +341,8 @@ static const struct snd_soc_dapm_widget 
> hda_dapm_widgets[] = {
>   static struct snd_soc_dai_driver card_binder_dai = {
>          .id = -1,
>          .name = "codec-probing-DAI",
> +       .capture.channels_min = 1,
> +       .playback.channels_min = 1,
>   };
(snip)
> and it works for testing purposes, but as commented in code, those 
> fields are initialized later (in hdmi_pcm_open()), which apparently in 
> case of ASoC binding is too late. Likely those assignments need to be 
> moved earlier.
> 
> Another thing that should probably be done is some kind of look through 
> ASoC codec files to make sure that they all define channels_min 
> properly, otherwise there may be more unexpected failures.

Hmm...

>From logic point of view, I think we need to check all validation.
But from compatible point of view, we want to skip validation check
for BE Codec...
Especially, quick hack solution (= adding channels_min in many place)
might case other bug I guess.

OK, let's skip BE Codec in v2 for now.

Thank you for your help !!

Best regards
---
Kuninori Morimoto
diff mbox series

Patch

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index af5d4e1effdf..f47ddf660c57 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2732,7 +2732,10 @@  static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
 				    int *playback, int *capture)
 {
 	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	struct snd_soc_dai *codec_dai;
 	struct snd_soc_dai *cpu_dai;
+	int cpu_capture  = SNDRV_PCM_STREAM_CAPTURE;
+	int cpu_playback = SNDRV_PCM_STREAM_PLAYBACK;
 	int tmp_playback = 0;
 	int tmp_capture  = 0;
 	int i;
@@ -2748,61 +2751,27 @@  static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
 		return -EINVAL;
 	}
 
-	if (dai_link->dynamic || dai_link->no_pcm) {
-		int stream;
-
-		if (dai_link->dpcm_playback) {
-			stream = SNDRV_PCM_STREAM_PLAYBACK;
+	/* Adapt stream for codec2codec links */
+	if (dai_link->c2c_params) {
+		cpu_capture  = SNDRV_PCM_STREAM_PLAYBACK;
+		cpu_playback = SNDRV_PCM_STREAM_CAPTURE;
+	}
 
-			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-				if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
-					tmp_playback = 1;
-					break;
-				}
-			}
-			if (!tmp_playback) {
-				dev_err(rtd->card->dev,
-					"No CPU DAIs support playback for stream %s\n",
-					dai_link->stream_name);
-				return -EINVAL;
-			}
-		}
-		if (dai_link->dpcm_capture) {
-			stream = SNDRV_PCM_STREAM_CAPTURE;
+	/* REMOVE ME */
+	if (dai_link->dpcm_playback && !dai_link->dpcm_capture)
+		dai_link->playback_only = 1;
+	if (!dai_link->dpcm_playback && dai_link->dpcm_capture)
+		dai_link->capture_only = 1;
 
-			for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
-				if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
-					tmp_capture = 1;
-					break;
-				}
-			}
-
-			if (!tmp_capture) {
-				dev_err(rtd->card->dev,
-					"No CPU DAIs support capture for stream %s\n",
-					dai_link->stream_name);
-				return -EINVAL;
-			}
-		}
-	} else {
-		struct snd_soc_dai *codec_dai;
-
-		/* Adapt stream for codec2codec links */
-		int cpu_capture = dai_link->c2c_params ?
-			SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
-		int cpu_playback = dai_link->c2c_params ?
-			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-
-		for_each_rtd_codec_dais(rtd, i, codec_dai) {
-			cpu_dai = asoc_rtd_to_cpu(rtd, i);
-
-			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
-			    snd_soc_dai_stream_valid(cpu_dai,   cpu_playback))
-				tmp_playback = 1;
-			if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
-			    snd_soc_dai_stream_valid(cpu_dai,   cpu_capture))
-				tmp_capture = 1;
-		}
+	for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
+		codec_dai = asoc_rtd_to_codec(rtd, i); /* get paired codec */
+
+		if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
+		    snd_soc_dai_stream_valid(cpu_dai,   cpu_playback))
+			tmp_playback = 1;
+		if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
+		    snd_soc_dai_stream_valid(cpu_dai,   cpu_capture))
+			tmp_capture = 1;
 	}
 
 	if (dai_link->playback_only)