From: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
To: <alsa-devel@alsa-project.org>, <linux-kernel@vger.kernel.org>
Cc: <perex@perex.cz>, <tiwai@suse.com>,
<pierre-louis.bossart@linux.intel.com>, <broonie@kernel.org>,
<joe@perches.com>, <lgirdwood@gmail.com>, <lars@metafoo.de>,
<kuninori.morimoto.gx@renesas.com>, <nicolas.ferre@microchip.com>,
<Cristian.Birsan@microchip.com>,
Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
Subject: [RFC PATCH 5/6] ASoC: soc-pcm: Create new snd_pcm_runtime for BE DAIs
Date: Wed, 19 May 2021 13:48:41 +0300 [thread overview]
Message-ID: <20210519104842.977895-6-codrin.ciubotariu@microchip.com> (raw)
In-Reply-To: <20210519104842.977895-1-codrin.ciubotariu@microchip.com>
The BE DAIs are different than the FE DAIs. They have different HW
capabilities, different HW constraints and different HW parameters. Also,
the buffer used to read/write data from/to user-space to/from FE DAIs has
nothing to do with the BE DAIs. For this reason, this patch creates a new
snd_pcm_runtime for the BE DAIs. The new structure can be used to better
represent the HW capabilities, so the HW parameters are no longer copied
from the FE, but created separately. For BE DAIs that need a buffer to move
the data to/from the FE DAIs (no dev-to-dev DMA capability), the new
snd_pcm_runtime can store the needed parameters to allocate the buffer and
set the DMA transfers.
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
---
sound/soc/soc-pcm.c | 126 +++++++++++++++++++++++++++++++-------------
1 file changed, 90 insertions(+), 36 deletions(-)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 8659089a87a0..7d95df20541e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1134,7 +1134,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
dpcm->be = be;
dpcm->fe = fe;
- be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
@@ -1150,34 +1149,6 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
return 1;
}
-/* reparent a BE onto another FE */
-static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
- struct snd_soc_pcm_runtime *be, int stream)
-{
- struct snd_soc_dpcm *dpcm;
- struct snd_pcm_substream *fe_substream, *be_substream;
-
- /* reparent if BE is connected to other FEs */
- if (!be->dpcm[stream].users)
- return;
-
- be_substream = snd_soc_dpcm_get_substream(be, stream);
-
- for_each_dpcm_fe(be, stream, dpcm) {
- if (dpcm->fe == fe)
- continue;
-
- dev_dbg(fe->dev, "reparent %s path %s %s %s\n",
- stream ? "capture" : "playback",
- dpcm->fe->dai_link->name,
- stream ? "<-" : "->", dpcm->be->dai_link->name);
-
- fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, stream);
- be_substream->runtime = fe_substream->runtime;
- break;
- }
-}
-
/* disconnect a BE and FE */
void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
{
@@ -1196,9 +1167,6 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
stream ? "capture" : "playback", fe->dai_link->name,
stream ? "<-" : "->", dpcm->be->dai_link->name);
- /* BEs still alive need new FE */
- dpcm_be_reparent(fe, dpcm->be, stream);
-
dpcm_remove_debugfs_state(dpcm);
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
@@ -1468,7 +1436,12 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
}
soc_pcm_close(be_substream);
- be_substream->runtime = NULL;
+
+ if (be_substream->runtime) {
+ snd_pcm_runtime_free(be_substream->runtime);
+ be_substream->runtime = NULL;
+ }
+
be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
}
}
@@ -1482,6 +1455,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
/* only startup BE DAIs that are either sinks or sources to this FE DAI */
for_each_dpcm_be(fe, stream, dpcm) {
struct snd_pcm_substream *be_substream;
+ struct snd_pcm_runtime *runtime;
be = dpcm->be;
be_substream = snd_soc_dpcm_get_substream(be, stream);
@@ -1514,7 +1488,23 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
dev_dbg(be->dev, "ASoC: open %s BE %s\n",
stream ? "capture" : "playback", be->dai_link->name);
- be_substream->runtime = be->dpcm[stream].runtime;
+ runtime = snd_pcm_runtime_alloc();
+ if (!runtime) {
+ err = -ENOMEM;
+ goto unwind;
+ }
+
+ be_substream->runtime = runtime;
+
+ /* initialize the BE constraints */
+ err = snd_pcm_hw_constraints_init(be_substream);
+ if (err < 0) {
+ dev_err(be->dev,
+ "dpcm_be_hw_constraints_init failed: %d\n",
+ err);
+ goto unwind;
+ }
+
err = soc_pcm_open(be_substream);
if (err < 0) {
be->dpcm[stream].users--;
@@ -1527,6 +1517,14 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
goto unwind;
}
+ err = snd_pcm_hw_constraints_complete(be_substream);
+ if (err < 0) {
+ dev_err(fe->dev,
+ "snd_pcm_hw_constraints_complete failed: %d\n",
+ err);
+ goto unwind;
+ }
+
be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
count++;
}
@@ -1897,6 +1895,14 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
if (ret < 0)
goto unwind;
+ /* apply constrains */
+ dpcm->hw_params.rmask = ~0U;
+ ret = snd_pcm_hw_refine(be_substream, &dpcm->hw_params);
+ if (ret < 0) {
+ dev_err(fe->dev, "failed to refine hw parameters: %d\n", ret);
+ goto unwind;
+ }
+
/* copy the fixed-up hw params for BE dai */
memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params,
sizeof(struct snd_pcm_hw_params));
@@ -1918,6 +1924,7 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
goto unwind;
be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
+ snd_pcm_runtime_set(be_substream, &dpcm->hw_params);
}
return 0;
@@ -1949,17 +1956,64 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
return ret;
}
+static int dpcm_be_dai_hw_params_init(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
+ int k;
+
+ for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK;
+ k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++)
+ snd_mask_any(hw_param_mask(params, k));
+
+ for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
+ k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++)
+ snd_interval_any(hw_param_interval(params, k));
+
+ return 0;
+}
+
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;
+ struct snd_interval *t, *dpcm_t;
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));
+ /* initialize the BE HW params */
+ dpcm_be_dai_hw_params_init(fe, stream);
+
+ /* FIXME: a very low period time will make the CPU take too many
+ * interrupts, which might end up not having enough time to actually
+ * fill the buffer(s); for now, the BE min period time will be half of
+ * the FE min period time
+ */
+ t = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
+ dpcm_t = hw_param_interval(&fe->dpcm[stream].hw_params,
+ SNDRV_PCM_HW_PARAM_PERIOD_TIME);
+ dpcm_t->min = t->min / 2;
+
+ if (fe->dai_link->dpcm_merged_format) {
+ memcpy(hw_param_interval(&fe->dpcm[stream].hw_params,
+ SNDRV_PCM_HW_PARAM_FORMAT),
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ sizeof(struct snd_interval));
+ }
+ if (fe->dai_link->dpcm_merged_chan) {
+ memcpy(hw_param_interval(&fe->dpcm[stream].hw_params,
+ SNDRV_PCM_HW_PARAM_CHANNELS),
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS),
+ sizeof(struct snd_interval));
+ }
+ if (fe->dai_link->dpcm_merged_rate) {
+ memcpy(hw_param_interval(&fe->dpcm[stream].hw_params,
+ SNDRV_PCM_HW_PARAM_RATE),
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
+ sizeof(struct snd_interval));
+ }
+
ret = dpcm_be_dai_hw_params(fe, stream);
if (ret < 0)
goto out;
--
2.27.0
next prev parent reply other threads:[~2021-05-19 10:50 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-19 10:48 [RFC PATCH 0/6] soc-pcm: Add separate snd_pcm_runtime for BEs Codrin Ciubotariu
2021-05-19 10:48 ` [RFC PATCH 1/6] ALSA: core: pcm: Create helpers to allocate/free struct snd_pcm_runtime Codrin Ciubotariu
2021-05-19 10:48 ` [RFC PATCH 2/6] ALSA: pcm: Export constraints initialization functions Codrin Ciubotariu
2021-05-19 10:48 ` [RFC PATCH 3/6] ALSA: pcm: Check for substream->ops before substream->ops->mmap Codrin Ciubotariu
2021-05-19 10:48 ` [RFC PATCH 4/6] ALSA: pcm: Create function for snd_pcm_runtime initialization Codrin Ciubotariu
2021-05-19 10:48 ` Codrin Ciubotariu [this message]
2021-05-19 10:48 ` [RFC PATCH 6/6] ASoC: dmaengine: Allocate buffer if substream is unmanaged Codrin Ciubotariu
2021-05-19 14:15 ` [RFC PATCH 0/6] soc-pcm: Add separate snd_pcm_runtime for BEs Takashi Iwai
2021-05-19 15:08 ` Codrin.Ciubotariu
2021-05-19 15:41 ` Takashi Iwai
2021-05-20 13:59 ` Codrin.Ciubotariu
2021-05-21 14:26 ` Takashi Iwai
2021-05-24 19:33 ` 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=20210519104842.977895-6-codrin.ciubotariu@microchip.com \
--to=codrin.ciubotariu@microchip.com \
--cc=Cristian.Birsan@microchip.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=joe@perches.com \
--cc=kuninori.morimoto.gx@renesas.com \
--cc=lars@metafoo.de \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nicolas.ferre@microchip.com \
--cc=perex@perex.cz \
--cc=pierre-louis.bossart@linux.intel.com \
--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
all inboxes | Powered by JetHome®