From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
To: vkoul@kernel.org, perex@perex.cz, tiwai@suse.com,
lgirdwood@gmail.com, broonie@kernel.org,
srinivas.kandagatla@oss.qualcomm.com
Cc: linux-sound@vger.kernel.org, kai.vehmanen@linux.intel.com,
yung-chuan.liao@linux.intel.com, pierre-louis.bossart@linux.dev,
daniel.baluta@nxp.com
Subject: [PATCH v3 04/26] ASoC: soc-compress: Provide a runtime for the compressed FE substream
Date: Fri, 11 Sep 2026 14:21:30 +0300 [thread overview]
Message-ID: <20260911112152.28528-5-peter.ujfalusi@linux.intel.com> (raw)
In-Reply-To: <20260911112152.28528-1-peter.ujfalusi@linux.intel.com>
When a compressed stream is used on the FE side of a DPCM link, the
BE is still running as 'normal' PCM.
DPCM lends the runtime of the FE to every BE it opens and
dpcm_be_reparent() re-points it at another FE when the lending one
disconnects. The internal PCM created for a compressed FE by
snd_soc_new_compress() is never opened via the PCM API, so its
substream has no runtime and the BEs of a compressed FE were left
with a NULL one.
BE DAI and codec drivers can look at substream->runtime, they add
their constraints to it in startup(), for example cs42l43, cs42l42,
hdac_hdmi.
The other users of compressed DPCM do not hit this as their BEs are
DSP internal ports, driven by code which takes everything from the
hw_params it is passed and never looks at substream->runtime. The
BEs here end at generic CODEC drivers which are shared with the non
DPCM case and cannot be expected to know about the FE type.
Allocate a runtime for the compressed FE substream while the stream
is open, initialize its constraints as snd_pcm_open() does and fill
it in from the BE parameters once the mandatory machine level
be_hw_params_fixup() has run, so that the compressed FE lends a valid
and populated runtime just like a PCM FE does.
This also allows a BE to be shared between a compressed and a PCM
FE, which is needed to play a notification over PCM to an endpoint
which a compressed stream is already using.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
---
sound/soc/soc-compress.c | 109 +++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 093a70a93d2b..b803e8cb4ea4 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -16,6 +16,7 @@
#include <sound/core.h>
#include <sound/compress_params.h>
#include <sound/compress_driver.h>
+#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/soc-dpcm.h>
@@ -131,6 +132,104 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
return ret;
}
+/*
+ * The internal PCM of a compressed FE is never opened via the PCM API, so its
+ * substream has no runtime attached to it.
+ *
+ * DPCM lends the runtime of the FE to every BE it opens and re-points it at
+ * another FE when the lending one goes away, so the compressed FE must provide
+ * one as well. Without it the BEs are left with a NULL runtime, which oopses
+ * in BE DAI and CODEC drivers looking at substream->runtime, and a BE can not
+ * be shared between a compressed and a PCM FE at all.
+ *
+ * The runtime is owned by the FE for as long as the compressed stream is open.
+ */
+static int soc_compr_alloc_fe_runtime(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream);
+ struct snd_pcm_hw_constraints *constrs;
+ int i;
+
+ if (!fe_substream || fe_substream->runtime)
+ return 0;
+
+ fe_substream->runtime = kzalloc_obj(*fe_substream->runtime);
+ if (!fe_substream->runtime)
+ return -ENOMEM;
+
+ /*
+ * snd_pcm_open() initializes the constraints of a PCM runtime to
+ * 'anything goes'. A zeroed one means an empty mask and a [0, 0]
+ * interval instead, which the constraint helpers refine against and
+ * reject, so initialize them the same way the PCM core does.
+ *
+ * The hw rules snd_pcm_hw_constraints_init() installs on top are only
+ * evaluated by snd_pcm_hw_refine(), which never runs for this
+ * substream, so they are not needed here.
+ */
+ constrs = &fe_substream->runtime->hw_constraints;
+ for (i = SNDRV_PCM_HW_PARAM_FIRST_MASK; i <= SNDRV_PCM_HW_PARAM_LAST_MASK; i++)
+ snd_mask_any(constrs_mask(constrs, i));
+
+ for (i = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; i <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; i++)
+ snd_interval_any(constrs_interval(constrs, i));
+
+ return 0;
+}
+
+static void soc_compr_free_fe_runtime(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream);
+
+ if (!fe_substream || !fe_substream->runtime)
+ return;
+
+ /* BE startup callbacks may have added hw constraint rules */
+ kfree(fe_substream->runtime->hw_constraints.rules);
+ kfree(fe_substream->runtime);
+ fe_substream->runtime = NULL;
+}
+
+/*
+ * The BE parameters of a compressed FE are set up by the machine level
+ * be_hw_params_fixup(), which is mandatory for a compressed BE, see
+ * soc_compr_set_params_fe(). Once they are fixed up, use them to fill in the
+ * runtime the BEs have been lent, so that a BE DAI or CODEC driver sees the
+ * format it is being configured for.
+ */
+static void soc_compr_set_fe_runtime(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ struct snd_pcm_substream *fe_substream = snd_soc_dpcm_get_substream(fe, stream);
+ struct snd_pcm_runtime *runtime;
+ struct snd_soc_dpcm *dpcm;
+
+ snd_soc_dpcm_mutex_assert_held(fe);
+
+ if (!fe_substream || !fe_substream->runtime)
+ return;
+
+ runtime = fe_substream->runtime;
+
+ for_each_dpcm_be(fe, stream, dpcm) {
+ struct snd_pcm_hw_params *params = &dpcm->be->dpcm[stream].hw_params;
+ int bits = snd_pcm_format_physical_width(params_format(params));
+
+ /* skip a BE which has not been fixed up */
+ if (bits <= 0)
+ continue;
+
+ runtime->access = params_access(params);
+ runtime->format = params_format(params);
+ runtime->subformat = params_subformat(params);
+ runtime->channels = params_channels(params);
+ runtime->rate = params_rate(params);
+
+ runtime->sample_bits = bits;
+ runtime->frame_bits = bits * runtime->channels;
+ break;
+ }
+}
+
static int soc_compr_open_fe(struct snd_compr_stream *cstream)
{
struct snd_soc_pcm_runtime *fe = cstream->private_data;
@@ -142,6 +241,10 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
snd_soc_card_mutex_lock(fe->card);
+ ret = soc_compr_alloc_fe_runtime(fe, stream);
+ if (ret < 0)
+ goto be_err;
+
ret = dpcm_path_get(fe, stream, &list);
if (ret < 0)
goto be_err;
@@ -196,6 +299,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
dpcm_path_put(&list);
snd_soc_dpcm_mutex_unlock(fe);
be_err:
+ soc_compr_free_fe_runtime(fe, stream);
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
snd_soc_card_mutex_unlock(fe->card);
return ret;
@@ -238,6 +342,9 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0);
+ /* all BEs are shut down and disconnected, the runtime is unused now */
+ soc_compr_free_fe_runtime(fe, stream);
+
snd_soc_card_mutex_unlock(fe->card);
return 0;
}
@@ -388,6 +495,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
snd_soc_dpcm_mutex_lock(fe);
ret = dpcm_be_dai_hw_params(fe, stream);
+ if (!ret)
+ soc_compr_set_fe_runtime(fe, stream);
snd_soc_dpcm_mutex_unlock(fe);
if (ret < 0)
goto out;
--
2.55.0
next prev parent reply other threads:[~2026-09-11 11:22 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 11:21 [PATCH v3 00/26] ALSA compress / ASoC compress / SOF: Compressed audio support with IPC4 Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 01/26] ALSA: compress: pin card module while stream is open Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 02/26] ALSA: compress: register the open file with the card Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 03/26] ALSA: compress: stop active streams on disconnect Peter Ujfalusi
2026-09-11 11:21 ` Peter Ujfalusi [this message]
2026-09-11 11:21 ` [PATCH v3 05/26] ASoC: soc-compress: Implement trigger FE-BE sequencing as with normal PCMs Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 06/26] ASoC: soc-compress: Stop running dpcm on free Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 07/26] ASoC: SOF: compress: Move the IPC agnostic helpers to sof-audio.c Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 08/26] ASoC: SOF: compress: Rename compress ops with ipc3 prefix Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 09/26] ASoC: SOF: sof-audio: Fix the pipeline_list population Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 10/26] ASoC: SOF: ipc4-pcm: Serialize the PCM free with the pipeline triggers Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 11/26] ASoC: SOF: sof-audio: do not dereference swidget->spipe unconditionally on free Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 12/26] ASoC: SOF: sof-audio: Expose a couple of functions Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 13/26] ASoC: SOF: pcm: Modify the signature of a couple of PCM IPC ops Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 14/26] ASoC: SOF: intel: hda-stream: Clear the current position when releasing stream Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 15/26] ASoC: SOF: ipc4: Add definition of module data in init_ext object type Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 16/26] ASoC: SOF: ipc4-topology: Support init_ext_module_data for process modules Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 17/26] ASoC: SOF: ipc4-pcm: Make the timestamp info usable outside of ipc4-pcm.c Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 18/26] ASoC: SOF: ipc4/ipc4-loader: Add SOF_INFO and CODEC_INFO to fw_config_params Peter Ujfalusi
2026-09-11 21:01 ` Mark Brown
2026-09-11 11:21 ` [PATCH v3 19/26] ASoC: SOF: ipc4-pcm: Handle COMPR DRAIN triggers as EOS pipeline state Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 20/26] ASoC: SOF: ipc4-topology: Set FAST_MODE for host copier in compr mode Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 21/26] ASoC: SOF: ops: Add new platform-specific ops for compress Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 22/26] ASoC: SOF: Add support for IPC4 compressed Peter Ujfalusi
2026-09-11 20:50 ` Mark Brown
2026-09-11 11:21 ` [PATCH v3 23/26] ASoC: SOF: ipc4: Handle compressed drain done notification from firmware Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 24/26] ASoC: SOF: Intel: Kconfig: Remove redundant IPC version selects Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 25/26] ASoC: SOF: Intel: Kconfig: Select compress support for TGL+ platforms Peter Ujfalusi
2026-09-11 11:21 ` [PATCH v3 26/26] ASoC: SOF: topology: Add support for decoder and encoder widgets Peter Ujfalusi
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=20260911112152.28528-5-peter.ujfalusi@linux.intel.com \
--to=peter.ujfalusi@linux.intel.com \
--cc=broonie@kernel.org \
--cc=daniel.baluta@nxp.com \
--cc=kai.vehmanen@linux.intel.com \
--cc=lgirdwood@gmail.com \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=pierre-louis.bossart@linux.dev \
--cc=srinivas.kandagatla@oss.qualcomm.com \
--cc=tiwai@suse.com \
--cc=vkoul@kernel.org \
--cc=yung-chuan.liao@linux.intel.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