[PATCH 1/4] ASoC: soc-pcm: dpcm: fix playback/capture checks

Stephan Gerhold stephan at gerhold.net
Wed Jun 17 11:01:12 CEST 2020


On Tue, Jun 16, 2020 at 12:05:49PM -0500, Pierre-Louis Bossart wrote:
> 
> 
> 
> > > > simple-card.c and audio-graph-card do hard-code but that's done
> > > > with C in
> > > > the driver:
> > > > 
> > > >     ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep,
> > > >                        NULL, &dai_link->dai_fmt);
> > > >     if (ret < 0)
> > > >         goto out_put_node;
> > > > 
> > > >     dai_link->dpcm_playback        = 1;
> > > >     dai_link->dpcm_capture        = 1;
> > > > 
> > > > 
> > > > that that should be fixed based on the DAI format used in that
> > > > dai_link - in
> > > > other words we can make sure the capabilities of the dailink are aligned
> > > > with the dais while parsing the DT blobs.
> > > 
> > > But how do you know which capabilities to set? The device tree doesn't
> > > tells us that. We could add some code to look up the snd_soc_dai_driver
> > > early, based on the references in the device tree (basically something
> > > like snd_soc_of_get_dai_name(), see
> > >     https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/sound/soc/soc-core.c#n2988)
> > > 
> > > 
> > > At least to me that function doesn't exactly look trivial though,
> > > and that's just to properly fill in the dpcm_playback/capture
> > > parameters. Essentially those parameters only complicate the current
> > > device tree use case,  where you want the DAI link to be for both
> > > playback/capture, but restricted to the capabilities of the DAI.
> > > 
> > > Just wondering if setting up dpcm_playback/capture properly is worth it
> > > at all in this case. This isn't necessary for the non-DPCM case either,
> > > there we automatically set it based on the DAI capabilities.
> > 
> > We can add a simple loop for each direction that relies on
> > snd_soc_dai_stream_valid() to identify if each DAI is capable of doing
> > playback/capture.
> 
> see below completely untested diff to show what I had in mind: we already
> make use of snd_soc_dai_stream_valid() in other parts of the core so we
> should be able to determine dpcm_playback/capture based on the same
> information already used.
> 
> diff --git a/sound/soc/generic/audio-graph-card.c
> b/sound/soc/generic/audio-graph-card.c
> index 9ad35d9940fe..4c67f1f65eb4 100644
> --- a/sound/soc/generic/audio-graph-card.c
> +++ b/sound/soc/generic/audio-graph-card.c
> @@ -215,7 +215,9 @@ static int graph_dai_link_of_dpcm(struct
> asoc_simple_priv *priv,
>         struct asoc_simple_dai *dai;
>         struct snd_soc_dai_link_component *cpus = dai_link->cpus;
>         struct snd_soc_dai_link_component *codecs = dai_link->codecs;
> +       int stream;
>         int ret;
> +       int i;
> 
>         /* Do it all CPU endpoint, and 1st Codec endpoint */
>         if (!li->cpu && dup_codec)
> @@ -317,8 +319,34 @@ static int graph_dai_link_of_dpcm(struct
> asoc_simple_priv *priv,
>         if (ret < 0)
>                 goto out_put_node;
> 
> -       dai_link->dpcm_playback         = 1;
> -       dai_link->dpcm_capture          = 1;
> +       for_each_pcm_streams(stream) {
> +               struct snd_soc_dai_link_component *cpu;
> +               struct snd_soc_dai_link_component *codec;
> +               struct snd_soc_dai *d;
> +               bool dpcm_direction = true;
> +
> +               for_each_link_cpus(dai_link, i, cpu) {
> +                       d = snd_soc_find_dai(cpu);
> +                       if (!d || !snd_soc_dai_stream_valid(d, stream)) {
> +                               dpcm_direction = false;
> +                               break;
> +                       }
> +               }
> +               for_each_link_codecs(dai_link, i, codec) {
> +                       d = snd_soc_find_dai(codec);
> +                       if (!d || !snd_soc_dai_stream_valid(d, stream)) {
> +                               dpcm_direction = false;
> +                               break;
> +                       }
> +               }
> +               if (dpcm_direction) {
> +                       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
> +                               dai_link->dpcm_playback = 1;
> +                       if (stream == SNDRV_PCM_STREAM_CAPTURE)
> +                               dai_link->dpcm_capture = 1;
> +               }
> +       }
> +
>         dai_link->ops                   = &graph_ops;
>         dai_link->init                  = asoc_simple_dai_init;
> 

Thanks for the diff! I tested it for my case and it seems to work fine
so far. I'm fine with this solution given that it fixes the problem
I mentioned. We would need to patch it into at least
simple-audio-card.c, audio-graph-card.c and soc/qcom/common.c
(probably best to create a shared function in soc-core.c then).

However, personally I still think that dpcm_playback/capture essentially
just duplicate the capabilities that are already exposed as part of the
DAI drivers. We don't need that duplication in the non-DPCM case,
so I wonder if we really need it for DPCM.

With your diff we go over all the DAIs to set dpcm_playback/capture
correctly so that soc_new_pcm() can then verify that they were set
correctly. IMO it would be much simpler to restore the previous behavior
and just make soc_new_pcm() rely on the DAI capabilities to decide
if playback/capture is supported, without producing the error.

Thanks,
Stephan


More information about the Alsa-devel mailing list