[alsa-devel] [PATCH v3 2/3] ASoC: Add Multi CPU DAI support for PCM ops
Shreyas NC
shreyas.nc at intel.com
Wed May 2 11:15:11 CEST 2018
On Mon, Apr 30, 2018 at 05:22:36PM +0100, Charles Keepax wrote:
> > @@ -361,7 +386,16 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
> > }
> > bits = max(codec_dai->driver->playback.sig_bits, bits);
> > }
> > - cpu_bits = cpu_dai->driver->playback.sig_bits;
> > +
> > + for (i = 0; i < rtd->num_cpu_dai; i++) {
> > + cpu_dai = rtd->cpu_dais[i];
> > + if (cpu_dai->driver->playback.sig_bits == 0) {
> > + cpu_bits = 0;
> > + break;
> > + }
> > +
> > + cpu_bits = max(cpu_dai->driver->playback.sig_bits, bits);
>
> Do you want cpu_bits at the end here? You are not going to get
> the max of the cpu_bits here, you will end up with the max of the
> CODEC bits and the last CPU bits?
>
You are right, will fix this :)
> > @@ -427,30 +464,47 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
> > rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
> > }
> >
> > - /*
> > - * chan min/max cannot be enforced if there are multiple CODEC DAIs
> > - * connected to a single CPU DAI, use CPU DAI's directly and let
> > - * channel allocation be fixed up later
> > - */
> > - if (rtd->num_codecs > 1) {
> > - chan_min = cpu_stream->channels_min;
> > - chan_max = cpu_stream->channels_max;
> > - }
> > + for (i = 0; i < rtd->num_cpu_dai; i++) {
> > + cpu_dai_drv = rtd->cpu_dais[i]->driver;
> >
> > - hw->channels_min = max(chan_min, cpu_stream->channels_min);
> > - hw->channels_max = min(chan_max, cpu_stream->channels_max);
> > - if (hw->formats)
> > - hw->formats &= formats & cpu_stream->formats;
> > - else
> > - hw->formats = formats & cpu_stream->formats;
> > - hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates);
> > + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> > + cpu_stream = &cpu_dai_drv->playback;
> > + else
> > + cpu_stream = &cpu_dai_drv->capture;
> >
> > - snd_pcm_limit_hw_rates(runtime);
> > + /*
> > + * chan min/max cannot be enforced if there are multiple
> > + * CODEC DAIs connected to a single CPU DAI, use CPU DAI's
> > + * directly and let channel allocation be fixed up later
> > + */
> > + if (rtd->num_codecs > 1 && rtd->num_cpu_dai == 1) {
> > + chan_min = cpu_stream->channels_min;
> > + chan_max = cpu_stream->channels_max;
> > + }
>
> This still doesn't quite look like, I am not seeing how the
> multiple CPU DAI and single CPU DAI cases differ with respect to
> whether we should ignore the CODEC channel settings?
>
Ok
> > +
> > + hw->channels_min = max(hw->channels_min, chan_min);
> > + hw->channels_min = max(hw->channels_min,
> > + cpu_stream->channels_min);
> > + hw->channels_max = min(hw->channels_max,
> > + cpu_stream->channels_max);
> > + hw->channels_max = min(hw->channels_max,
> > + cpu_stream->channels_max);
> > +
> > + if (hw->formats)
> > + hw->formats &= formats & cpu_stream->formats;
>
> Minor nit.
>
> This feels a little funny now, since we are anding each CPU
> formats with the CODEC formats, and then anding them into the
> result.
>
> Feels like we should just and in the CODEC format once.
Yes, makes sense. Thanks :)
>
> > + else
> > + hw->formats = formats & cpu_stream->formats;
>
> > +
> > + hw->rates = snd_pcm_rate_mask_intersect(rates,
> > + cpu_stream->rates);
>
> I think this is broken since the rates will end up and the
> intersection of the last CPU DAI rates and the CODEC rates, not
> an intersection of all the CPU rates.
>
Ok, will fix this :)
I have had a tough time in handling this function :(
> > @@ -602,7 +668,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
> > }
> >
> > pr_debug("ASoC: %s <-> %s info:\n",
> > - codec_dai_name, cpu_dai->name);
> > + codec_dai_name, cpu_dai_name);
> > pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
> > pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
> > runtime->hw.channels_max);
> > @@ -649,9 +715,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
> > platform->driver->ops->close(substream);
> >
> > platform_err:
> > - if (cpu_dai->driver->ops->shutdown)
> > - cpu_dai->driver->ops->shutdown(substream, cpu_dai);
> > -out:
> > + j = rtd->num_cpu_dai;
> > + while (--j >= 0) {
> > + cpu_dai = rtd->cpu_dais[j];
> > + if (cpu_dai->driver->ops->shutdown)
> > + cpu_dai->driver->ops->shutdown(substream, cpu_dai);
> > + }
> > +
>
> This will call shutdown for DAIs that never had startup called on
> them, probably better to avoid that.
>
Ok, will fix this.
> > @@ -1070,12 +1168,18 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
> > platform->driver->ops->hw_free(substream);
> >
> > platform_err:
> > - if (cpu_dai->driver->ops->hw_free)
> > - cpu_dai->driver->ops->hw_free(substream, cpu_dai);
> > + j = rtd->num_cpu_dai;
> >
> > interface_err:
> > i = rtd->num_codecs;
> >
> > + while (--j >= 0) {
> > + cpu_dai = rtd->cpu_dais[j];
> > +
> > + if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
> > + cpu_dai->driver->ops->hw_free(substream, cpu_dai);
> > + }
> > +
>
> Minor nit might be nicer to add this before the i = since that
> kinda relates to the code underneath.
>
Sure, that aids readability. I will check if we can do that at other places
as well :)
Thanks for the review!
--Shreyas
--
More information about the Alsa-devel
mailing list