linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
To: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>,
	alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org
Cc: gustavoars@kernel.org, tiwai@suse.com, lgirdwood@gmail.com,
	mirq-linux@rere.qmqm.pl, broonie@kernel.org
Subject: Re: [RFC PATCH 0/3] Separate BE DAI HW constraints from FE ones
Date: Tue, 23 Mar 2021 14:25:53 -0500	[thread overview]
Message-ID: <7364fb08-fe43-167d-a083-db4a6234222c@linux.intel.com> (raw)
In-Reply-To: <20210323114327.3969072-1-codrin.ciubotariu@microchip.com>



On 3/23/21 6:43 AM, Codrin Ciubotariu wrote:
> HW constraints are needed to set limitations for HW parameters used to
> configure the DAIs. All DAIs on the same link must agree upon the HW
> parameters, so the parameters are affected by the DAIs' features and
> their limitations. In case of DPCM, the FE DAIs can be used to perform
> different kind of conversions, such as format or rate changing, bringing
> the audio stream to a configuration supported by all the DAIs of the BE's
> link. For this reason, the limitations of the BE DAIs are not always
> important for the HW parameters between user-space and FE, only for the
> paratemers between FE and BE DAI links. This brings us to this patch-set,
> which aims to separate the FE HW constraints from the BE HW constraints.
> This way, the FE can be used to perform more efficient HW conversions, on
> the initial audio stream parameters, to parameters supported by the BE
> DAIs.
> To achieve this, the first thing needed is to detect whether a HW
> constraint rule is enforced by a FE or a BE DAI. This means that
> snd_pcm_hw_rule_add() needs to be able to differentiate between the two
> type of DAIs. For this, the runtime pointer to struct snd_pcm_runtime is
> replaced with a pointer to struct snd_pcm_substream, to be able to reach
> substream->pcm->internal to differentiate between FE and BE DAIs.
> This change affects many sound drivers (and one gpu drm driver).
> All these changes are included in the first patch, to have a better
> overview of the implications created by this change.
> The second patch adds a new struct snd_pcm_hw_constraints under struct
> snd_soc_dpcm_runtime, which is used to store the HW constraint rules
> added by the BE DAIs. This structure is initialized with a subset of the
> runtime constraint rules which does not include the rules that affect
> the buffer or period size. snd_pcm_hw_rule_add() will add the BE rules
> to the new struct snd_pcm_hw_constraints.
> The third and last patch will apply the BE rule constraints, after the
> fixup callback. If the fixup HW parameters do not respect the BE
> constraint rules, the rules will exit with an error. The FE mask and
> interval constraints are copied to the BE ones, to satisfy the
> dai_link->dpcm_merged_* flags. The dai_link->dpcm_merged_* flags are
> used to know if the FE does format or sampling rate conversion.
> 
> I tested with ad1934 and wm8731 codecs as BEs, with a not-yet-mainlined
> ASRC as FE, that can also do format conversion. I realize that the
> change to snd_pcm_hw_rule_add() has a big impact, even though all the
> drivers use snd_pcm_hw_rule_add() with substream->runtime, so passing
> substream instead of runtime is not that risky.

can you use the BE hw_params_fixup instead?

That's what we use for SOF.

The FE hw_params are propagated to the BE, and then the BE can update 
the hw_params based on its own limitations and pass the result 
downstream, e.g. to a codec.

I'll copy below my understanding of the flow, which we discussed 
recently in the SOF team:

my understanding is that we start with the front-end hw_params as the 
basis for the back-end hw_params.

static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
                  struct snd_pcm_hw_params *params)
{
     struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
     int ret, stream = substream->stream;

     mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
     dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);

     memcpy(&fe->dpcm[stream].hw_params, params,
             sizeof(struct snd_pcm_hw_params));
     ret = dpcm_be_dai_hw_params(fe, stream);
<<< the BE is handled first.
     if (ret < 0) {
         dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret);
         goto out;
     }

     dev_dbg(fe->dev, "ASoC: hw_params FE %s rate %d chan %x fmt %d\n",
             fe->dai_link->name, params_rate(params),
             params_channels(params), params_format(params));

     /* call hw_params on the frontend */
     ret = soc_pcm_hw_params(substream, params);

then each BE will be configured

int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
{
     struct snd_soc_dpcm *dpcm;
     int ret;

     for_each_dpcm_be(fe, stream, dpcm) {

         struct snd_soc_pcm_runtime *be = dpcm->be;
         struct snd_pcm_substream *be_substream =
             snd_soc_dpcm_get_substream(be, stream);

         /* is this op for this BE ? */
         if (!snd_soc_dpcm_be_can_update(fe, be, stream))
             continue;

         /* copy params for each dpcm */
         memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
                 sizeof(struct snd_pcm_hw_params));

         /* perform any hw_params fixups */
         ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params);

The fixup is the key, in SOF this is where we are going to look for 
information from the topology.

/* fixup the BE DAI link to match any values from topology */
int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct 
snd_pcm_hw_params *params)
{
     struct snd_interval *rate = hw_param_interval(params,
             SNDRV_PCM_HW_PARAM_RATE);
     struct snd_interval *channels = hw_param_interval(params,
                         SNDRV_PCM_HW_PARAM_CHANNELS);
     struct snd_mask *fmt = hw_param_mask(params, 
SNDRV_PCM_HW_PARAM_FORMAT);
     struct snd_soc_component *component =
         snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
     struct snd_sof_dai *dai =
         snd_sof_find_dai(component, (char *)rtd->dai_link->name);
     struct snd_soc_dpcm *dpcm;

     /* no topology exists for this BE, try a common configuration */
     if (!dai) {
         dev_warn(component->dev,
              "warning: no topology found for BE DAI %s config\n",
              rtd->dai_link->name);

         /*  set 48k, stereo, 16bits by default */
         rate->min = 48000;
         rate->max = 48000;

         channels->min = 2;
         channels->max = 2;

         snd_mask_none(fmt);
         snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);

         return 0;
     }

     /* read format from topology */
     snd_mask_none(fmt);

     switch (dai->comp_dai.config.frame_fmt) {
     case SOF_IPC_FRAME_S16_LE:
         snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
         break;
     case SOF_IPC_FRAME_S24_4LE:
         snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
         break;
     case SOF_IPC_FRAME_S32_LE:
         snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
         break;
     default:
         dev_err(component->dev, "error: No available DAI format!\n");
         return -EINVAL;
     }

     /* read rate and channels from topology */
     switch (dai->dai_config->type) {
     case SOF_DAI_INTEL_SSP:
         rate->min = dai->dai_config->ssp.fsync_rate;
         rate->max = dai->dai_config->ssp.fsync_rate;
         channels->min = dai->dai_config->ssp.tdm_slots;
         channels->max = dai->dai_config->ssp.tdm_slots;

  parent reply	other threads:[~2021-03-23 19:26 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-23 11:43 [RFC PATCH 0/3] Separate BE DAI HW constraints from FE ones Codrin Ciubotariu
2021-03-23 11:43 ` [RFC PATCH 1/3] pcm: use substream instead of runtime in snd_pcm_hw_rule_add() Codrin Ciubotariu
2021-03-23 11:43 ` [RFC PATCH 2/3] ASoC: soc-pcm: add hw_constraints for BE DAI links Codrin Ciubotariu
2021-03-23 11:43 ` [RFC PATCH 3/3] ASoC: soc-pcm: apply BE HW constraint rules Codrin Ciubotariu
2021-03-23 12:15 ` [RFC PATCH 0/3] Separate BE DAI HW constraints from FE ones Jaroslav Kysela
2021-03-23 14:18   ` Codrin.Ciubotariu
2021-04-14 14:58     ` Codrin.Ciubotariu
2021-04-15 16:17       ` Mark Brown
2021-04-15 16:56         ` Codrin.Ciubotariu
2021-04-15 17:25           ` Mark Brown
2021-04-16 16:03             ` Codrin.Ciubotariu
2021-04-16 16:31               ` Mark Brown
2021-04-16 16:47                 ` Pierre-Louis Bossart
2021-04-16 18:55                   ` Mark Brown
2021-04-16 19:39                     ` Pierre-Louis Bossart
2021-04-19 15:07                       ` Mark Brown
2021-04-16 17:39                 ` Codrin.Ciubotariu
2021-03-23 19:25 ` Pierre-Louis Bossart [this message]
2021-03-24  9:51   ` Codrin.Ciubotariu
2021-03-24 15:28     ` Pierre-Louis Bossart
2021-03-24 17:12       ` Codrin.Ciubotariu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7364fb08-fe43-167d-a083-db4a6234222c@linux.intel.com \
    --to=pierre-louis.bossart@linux.intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=codrin.ciubotariu@microchip.com \
    --cc=gustavoars@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mirq-linux@rere.qmqm.pl \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).