diff mbox series

ASoC: soc-pcm: fix hw->formats cleared by soc_pcm_hw_init() for dpcm

Message ID 1678346017-3660-1-git-send-email-shengjiu.wang@nxp.com (mailing list archive)
State Accepted
Commit 083a25b18d6ad9f1f540e629909aa3eaaaf01823
Headers show
Series ASoC: soc-pcm: fix hw->formats cleared by soc_pcm_hw_init() for dpcm | expand

Commit Message

Shengjiu Wang March 9, 2023, 7:13 a.m. UTC
The hw->formats may be set by snd_dmaengine_pcm_refine_runtime_hwparams()
in component's startup()/open(), but soc_pcm_hw_init() will init
hw->formats in dpcm_runtime_setup_fe() after component's startup()/open(),
which causes the valuable hw->formats to be cleared.

So need to store the hw->formats before initialization, then restore
it after initialization.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
 sound/soc/soc-pcm.c | 4 ++++
 1 file changed, 4 insertions(+)

Comments

Kuninori Morimoto March 12, 2023, 11:58 p.m. UTC | #1
Hi Shengjiu

> The hw->formats may be set by snd_dmaengine_pcm_refine_runtime_hwparams()
> in component's startup()/open(), but soc_pcm_hw_init() will init
> hw->formats in dpcm_runtime_setup_fe() after component's startup()/open(),
> which causes the valuable hw->formats to be cleared.
> 
> So need to store the hw->formats before initialization, then restore
> it after initialization.
> 
> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> ---
>  sound/soc/soc-pcm.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> index 5eb056b942ce..7958c9defd49 100644
> --- a/sound/soc/soc-pcm.c
> +++ b/sound/soc/soc-pcm.c
> @@ -1661,10 +1661,14 @@ static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream)
>  	struct snd_pcm_hardware *hw = &runtime->hw;
>  	struct snd_soc_dai *dai;
>  	int stream = substream->stream;
> +	u64 formats = hw->formats;
>  	int i;
>  
>  	soc_pcm_hw_init(hw);
>  
> +	if (formats)
> +		hw->formats &= formats;
> +

If my understanding was correct, dpcm_runtime_setup_fe() (B) is called
after __soc_pcm_open() (A), and you updated (B) part.

	static int dpcm_fe_dai_startup(...) {
		...
(A)		ret = __soc_pcm_open(fe, fe_substream);
		...
(B)		dpcm_runtime_setup_fe(fe_substream);
		...
	}

But, it is doing same things under (A), too.
Do we need to initialize hw many times ? I'm not sure.
Can we simply remove soc_pcm_hw_init() from dpcm_runtime_setup_fe() ?

(A)	static int __soc_pcm_open()
	{
		...
(X)		soc_pcm_init_runtime_hw(substream);
		...
	}

(X)	static void soc_pcm_init_runtime_hw(...)
	{
=>		u64 formats = hw->formats;

(Y)		snd_soc_runtime_calc_hw(rtd, hw, substream->stream);

=>		if (formats)
=>			hw->formats &= formats;
	}

(Y)	int snd_soc_runtime_calc_hw(...)
	{
		...
=>		soc_pcm_hw_init(hw);
		...
	}

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Shengjiu Wang March 13, 2023, 2:36 a.m. UTC | #2
Hi

On Mon, Mar 13, 2023 at 7:59 AM Kuninori Morimoto <
kuninori.morimoto.gx@renesas.com> wrote:

>
> Hi Shengjiu
>
> > The hw->formats may be set by snd_dmaengine_pcm_refine_runtime_hwparams()
> > in component's startup()/open(), but soc_pcm_hw_init() will init
> > hw->formats in dpcm_runtime_setup_fe() after component's
> startup()/open(),
> > which causes the valuable hw->formats to be cleared.
> >
> > So need to store the hw->formats before initialization, then restore
> > it after initialization.
> >
> > Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> > ---
> >  sound/soc/soc-pcm.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> > index 5eb056b942ce..7958c9defd49 100644
> > --- a/sound/soc/soc-pcm.c
> > +++ b/sound/soc/soc-pcm.c
> > @@ -1661,10 +1661,14 @@ static void dpcm_runtime_setup_fe(struct
> snd_pcm_substream *substream)
> >       struct snd_pcm_hardware *hw = &runtime->hw;
> >       struct snd_soc_dai *dai;
> >       int stream = substream->stream;
> > +     u64 formats = hw->formats;
> >       int i;
> >
> >       soc_pcm_hw_init(hw);
> >
> > +     if (formats)
> > +             hw->formats &= formats;
> > +
>
> If my understanding was correct, dpcm_runtime_setup_fe() (B) is called
> after __soc_pcm_open() (A), and you updated (B) part.
>
>         static int dpcm_fe_dai_startup(...) {
>                 ...
> (A)             ret = __soc_pcm_open(fe, fe_substream);
>                 ...
> (B)             dpcm_runtime_setup_fe(fe_substream);
>                 ...
>         }
>
> But, it is doing same things under (A), too.
> Do we need to initialize hw many times ? I'm not sure.
> Can we simply remove soc_pcm_hw_init() from dpcm_runtime_setup_fe() ?
>
> (A)     static int __soc_pcm_open()
>         {
>                 ...
> (X)             soc_pcm_init_runtime_hw(substream);
>                 ...
>         }
>

Here there is condition:

        /* Dynamic PCM DAI links compat checks use dynamic capabilities */
        if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
                goto dynamic;

        /* Check that the codec and cpu DAIs are compatible */
        soc_pcm_init_runtime_hw(substream);

which only calls soc_pcm_init_runtime_hw() for non dpcm case.

So the initialization of hw is not many times.

For dpcm the code here will be skipped. The initialization happens
only in dpcm_runtime_setup_fe().

Best regards
Wang shengjiu


> (X)     static void soc_pcm_init_runtime_hw(...)
>         {
> =>              u64 formats = hw->formats;
>
> (Y)             snd_soc_runtime_calc_hw(rtd, hw, substream->stream);
>
> =>              if (formats)
> =>                      hw->formats &= formats;
>         }
>
> (Y)     int snd_soc_runtime_calc_hw(...)
>         {
>                 ...
> =>              soc_pcm_hw_init(hw);
>                 ...
>         }
>
> Thank you for your help !!
>
> Best regards
> ---
> Kuninori Morimoto
>
Kuninori Morimoto March 13, 2023, 6:15 a.m. UTC | #3
Hi Shengjiu

>     But, it is doing same things under (A), too.
>     Do we need to initialize hw many times ? I'm not sure.
>     Can we simply remove soc_pcm_hw_init() from dpcm_runtime_setup_fe() ?
(snip)
> which only calls soc_pcm_init_runtime_hw() for non dpcm case.
> 
> So the initialization of hw is not many times.
>  
> For dpcm the code here will be skipped. The initialization happens
> only in dpcm_runtime_setup_fe().

Oh I see.
Thank you for clarify it.

Best regards
---
Kuninori Morimoto
Mark Brown March 14, 2023, 3:12 p.m. UTC | #4
On Thu, 09 Mar 2023 15:13:37 +0800, Shengjiu Wang wrote:
> The hw->formats may be set by snd_dmaengine_pcm_refine_runtime_hwparams()
> in component's startup()/open(), but soc_pcm_hw_init() will init
> hw->formats in dpcm_runtime_setup_fe() after component's startup()/open(),
> which causes the valuable hw->formats to be cleared.
> 
> So need to store the hw->formats before initialization, then restore
> it after initialization.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: soc-pcm: fix hw->formats cleared by soc_pcm_hw_init() for dpcm
      commit: 083a25b18d6ad9f1f540e629909aa3eaaaf01823

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark
diff mbox series

Patch

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 5eb056b942ce..7958c9defd49 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1661,10 +1661,14 @@  static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream)
 	struct snd_pcm_hardware *hw = &runtime->hw;
 	struct snd_soc_dai *dai;
 	int stream = substream->stream;
+	u64 formats = hw->formats;
 	int i;
 
 	soc_pcm_hw_init(hw);
 
+	if (formats)
+		hw->formats &= formats;
+
 	for_each_rtd_cpu_dais(fe, i, dai) {
 		struct snd_soc_pcm_stream *cpu_stream;