Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1d410e5
ASoC: soc-pcm: Allocate be_substream->runtime for compressed streams
ujfalusi Jan 13, 2026
45f9ce8
ASoC: soc-compress: Implement trigger FE-BE sequencing as with normal…
ujfalusi Jan 27, 2026
7bb224b
ALSA: compress_offload: Add flag to keep running state after drain
ujfalusi Feb 2, 2026
284b19d
ASoC: SOF: compress: Rename compress ops with ipc3 prefix
ranj063 Dec 9, 2025
1fdda91
ASoC: SOF: sof-audio: Expose a couple of functions
ranj063 Dec 9, 2025
be3f01e
ASoC: SOF: pcm: Modify the signature of a couple of PCM IPC ops
ranj063 Dec 9, 2025
10507fc
ASoC: SOF: intel: hda-stream: Clear the current position when releasi…
ranj063 Dec 9, 2025
a3684e5
ASoC: SOF: ops: Add new platform-specific ops for compress
ranj063 Dec 9, 2025
5bb6f8c
ASoC: SOF: ipc4: Add definition of module data in init_ext object type
ujfalusi Jan 12, 2026
49d37d0
ASoC: SOF: ipc4-topology: Support init_ext_module_data for process mo…
ujfalusi Jan 13, 2026
9898606
ASoC: SOF: ipc4-pcm: Make the timestamp info usable outside of ipc4-p…
ujfalusi Jan 13, 2026
834aabe
ASoC: SOF: ipc4/ipc4-loader: Add SOF_INFO and CODEC_INFO to fw_config…
ujfalusi Jan 14, 2026
86af8be
ASoC: SOF: ipc4-pcm: Handle COMPR DRAIN triggers as EOS pipeline state
ujfalusi Jan 30, 2026
88c9574
ASoC: SOF: ipc4-topology: Set FAST_MODE for host copier in compr mode
ujfalusi Jan 30, 2026
2a19d3b
ASoC: SOF: Add support for IPC4 compressed
ranj063 Dec 9, 2025
67e8b49
ASoC: SOF: ipc4: Handle compressed drain done notification from firmware
ujfalusi Jan 30, 2026
1c7a167
ASoC: SOF: Intel: Kconfig: Remove redundant IPC version selects
ujfalusi Dec 31, 2025
3f42333
ASoC: SOF: Intel: Kconfig: Select compress support for TGL+ platforms
ujfalusi Dec 31, 2025
bc8f6ba
ASoC: SOF: topology: Add support for decoder and encoder widgets
ranj063 Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions include/sound/compress_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ struct snd_compr_ops {
* @lock: device lock
* @device: device id
* @use_pause_in_draining: allow pause in draining, true when set
* @keep_running_state_after_drain: after successful drain, keep the RUNNING state instead of
* moving to SETUP
*/
struct snd_compr {
const char *name;
Expand All @@ -201,6 +203,7 @@ struct snd_compr {
struct mutex lock;
int device;
bool use_pause_in_draining;
bool keep_running_state_after_drain;
#ifdef CONFIG_SND_VERBOSE_PROCFS
/* private: */
char id[64];
Expand All @@ -225,6 +228,23 @@ static inline void snd_compr_use_pause_in_draining(struct snd_compr_stream *subs
substream->device->use_pause_in_draining = true;
}

/**
* snd_compr_keep_running_state_after_drain - Keep RUNNING state after drain
* @substream: compress substream to set
*
* Keep the device in RUNNING state after the drain completed instead of transitioning
* to SETUP state.
* For generic drivers the SETUP state is not equal to RUNNING state and a transition
* between them without a trigger is not possible.
* For example in complex systems with Soundwire after the drain the stream can be
* closed, but the stream has not been stopped, which will result errors in codec and
* subsystem level.
*/
static inline void snd_compr_keep_running_state_after_drain(struct snd_compr_stream *substream)
{
substream->device->keep_running_state_after_drain = true;
}

/* dsp driver callback apis
* For playback: driver should call snd_compress_fragment_elapsed() to let the
* framework know that a fragment has been consumed from the ring buffer
Expand All @@ -243,8 +263,11 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
if (snd_BUG_ON(!stream))
return;

/* for partial_drain case we are back to running state on success */
if (stream->partial_drain) {
/*
* For partial_drain case or if keep_running_state_after_drain is set we
* are back to running state on success
*/
if (stream->partial_drain || stream->device->keep_running_state_after_drain) {
stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
stream->partial_drain = false; /* clear this flag as well */
} else {
Expand Down
24 changes: 16 additions & 8 deletions include/sound/sof/ipc4/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,10 @@ enum sof_ipc4_fw_config_params {
SOF_IPC4_FW_CFG_RESERVED,
SOF_IPC4_FW_CFG_POWER_GATING_POLICY,
SOF_IPC4_FW_CFG_ASSERT_MODE,
SOF_IPC4_FW_RESERVED1,
SOF_IPC4_FW_RESERVED2,
SOF_IPC4_FW_RESERVED3,
SOF_IPC4_FW_RESERVED4,
SOF_IPC4_FW_RESERVED5,
SOF_IPC4_FW_CONTEXT_SAVE
/* Reserved: 24 - 28 */
SOF_IPC4_FW_CONTEXT_SAVE = 29,
/* Reserved: 30 - 34 */
SOF_IPC4_FW_CFG_SOF_INFO = 35,
};

struct sof_ipc4_fw_version {
Expand All @@ -448,6 +446,14 @@ struct sof_ipc4_fw_version {
uint16_t build;
} __packed;

/*
* tuple based array for SOF specific information under SOF_IPC4_FW_CFG_SOF_INFO
* tuple of fw_config
*/
enum ipc4_fw_sof_info_params {
SOF_IPC4_SOF_CODEC_INFO,
};

/* Payload data for SOF_IPC4_MOD_SET_DX */
struct sof_ipc4_dx_state_info {
/* core(s) to apply the change */
Expand Down Expand Up @@ -616,9 +622,10 @@ struct sof_ipc4_notify_module_data {
* The event_data contains the struct sof_ipc4_control_msg_payload of the control
* which sent the notification.
*/
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_MASK GENMASK(31, 16)
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_SOF_MAGIC_MASK GENMASK(31, 16)
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL 0xA15A0000
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK GENMASK(15, 0)
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL 0xC0C00000

/*
* Macros for creating struct sof_ipc4_module_init_ext_init payload
Expand Down Expand Up @@ -681,7 +688,8 @@ struct sof_ipc4_module_init_ext_object {
enum sof_ipc4_mod_init_ext_obj_id {
SOF_IPC4_MOD_INIT_DATA_ID_INVALID = 0,
SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MAX = SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MODULE_DATA,
SOF_IPC4_MOD_INIT_DATA_ID_MAX = SOF_IPC4_MOD_INIT_DATA_ID_MODULE_DATA,
};

/* DP module memory configuration data object for ext_init object array */
Expand Down
77 changes: 68 additions & 9 deletions sound/soc/soc-compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,31 +273,90 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
return ret;
}

static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
static int soc_compr_trigger_fe_be(struct snd_compr_stream *cstream, int cmd,
bool fe_first)
{
struct snd_soc_pcm_runtime *fe = cstream->private_data;
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
int ret;

if (fe_first) {
dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
fe->dai_link->name, cmd);

ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
if (ret < 0)
goto out;

ret = snd_soc_component_compr_trigger(cstream, cmd);
if (ret < 0)
goto out;

ret = dpcm_be_dai_trigger(fe, cstream->direction, cmd);
} else {
dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
fe->dai_link->name, cmd);

ret = dpcm_be_dai_trigger(fe, cstream->direction, cmd);
if (ret < 0)
goto out;

ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
if (ret < 0)
goto out;

ret = snd_soc_component_compr_trigger(cstream, cmd);
}

out:
return ret;
}

static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
{
struct snd_soc_pcm_runtime *fe = cstream->private_data;
int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
bool fe_first = true;
int ret;

if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
cmd == SND_COMPR_TRIGGER_DRAIN)
return snd_soc_component_compr_trigger(cstream, cmd);

switch (fe->dai_link->trigger[stream]) {
case SND_SOC_DPCM_TRIGGER_PRE:
fe_first = true;
break;
case SND_SOC_DPCM_TRIGGER_POST:
fe_first = false;
break;
default:
break;
}

snd_soc_card_mutex_lock(fe->card);

ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
if (ret < 0)
goto out;
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = soc_compr_trigger_fe_be(cstream, cmd, fe_first);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ret = soc_compr_trigger_fe_be(cstream, cmd, !fe_first);
break;
default:
ret = -EINVAL;
break;
}

ret = snd_soc_component_compr_trigger(cstream, cmd);
if (ret < 0)
goto out;

fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;

ret = dpcm_be_dai_trigger(fe, stream, cmd);

switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
Expand Down
13 changes: 12 additions & 1 deletion sound/soc/soc-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,8 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream,
}

__soc_pcm_close(be, be_substream);
if (fe->fe_compr)
kfree(be_substream->runtime);
be_substream->runtime = NULL;
be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
}
Expand Down Expand Up @@ -1718,7 +1720,16 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
dev_dbg(be->dev, "ASoC: open %s BE %s\n",
snd_pcm_direction_name(stream), be->dai_link->name);

be_substream->runtime = fe_substream->runtime;
if (!fe->fe_compr) {
be_substream->runtime = fe_substream->runtime;
} else {
be_substream->runtime = kzalloc(sizeof(*be_substream->runtime), GFP_KERNEL);
if (!be_substream->runtime) {
err = -ENOMEM;
goto unwind;
}
}

err = __soc_pcm_open(be, be_substream);
if (err < 0) {
be->dpcm[stream].users--;
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/sof/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ snd-sof-y := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
ifneq ($(CONFIG_SND_SOC_SOF_IPC3),)
snd-sof-y += ipc3.o ipc3-loader.o ipc3-topology.o ipc3-control.o ipc3-pcm.o\
ipc3-dtrace.o
snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += ipc3-compress.o
endif
ifneq ($(CONFIG_SND_SOC_SOF_IPC4),)
snd-sof-y += ipc4.o ipc4-loader.o ipc4-topology.o ipc4-control.o ipc4-pcm.o\
ipc4-mtrace.o ipc4-telemetry.o
snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += ipc4-compress.o
endif

# SOF client support
ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),)
snd-sof-y += sof-client.o
endif

snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += compress.o

snd-sof-pci-y := sof-pci-dev.o
snd-sof-acpi-y := sof-acpi-dev.o
snd-sof-of-y := sof-of-dev.o
Expand Down
10 changes: 7 additions & 3 deletions sound/soc/sof/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)

sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE);

/* set up platform component driver */
snd_sof_new_platform_drv(sdev);

if (sdev->dspless_mode_selected) {
sof_set_fw_state(sdev, SOF_DSPLESS_MODE);

/* set up platform component driver */
snd_sof_new_platform_drv(sdev);

goto skip_dsp_init;
}

Expand All @@ -498,6 +499,9 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
goto ipc_err;
}

/* set up platform component driver after initializing the IPC ops */
snd_sof_new_platform_drv(sdev);

/*
* skip loading/booting firmware and registering the machine driver when DSP OPS testing
* is enabled with IPC4. Normal audio operations will be unavailable in this mode.
Expand Down
9 changes: 2 additions & 7 deletions sound/soc/sof/intel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,6 @@ config SND_SOC_SOF_INTEL_ICL
tristate
select SND_SOC_SOF_HDA_GENERIC
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
select SND_SOC_SOF_IPC3
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_INTEL_CNL

config SND_SOC_SOF_ICELAKE
Expand All @@ -214,9 +212,8 @@ config SND_SOC_SOF_INTEL_TGL
tristate
select SND_SOC_SOF_HDA_GENERIC
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
select SND_SOC_SOF_IPC3
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_INTEL_CNL
select SND_SOC_SOF_COMPRESS

config SND_SOC_SOF_TIGERLAKE
tristate "SOF support for Tigerlake"
Expand Down Expand Up @@ -253,6 +250,7 @@ config SND_SOC_SOF_INTEL_MTL
select SND_SOC_SOF_HDA_GENERIC
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_COMPRESS

config SND_SOC_SOF_METEORLAKE
tristate "SOF support for Meteorlake"
Expand All @@ -270,7 +268,6 @@ config SND_SOC_SOF_INTEL_LNL
select SND_SOC_SOF_HDA_GENERIC
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_SOUNDWIRE != n
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_INTEL_MTL

config SND_SOC_SOF_LUNARLAKE
Expand All @@ -287,7 +284,6 @@ config SND_SOC_SOF_INTEL_PTL
tristate
select SND_SOC_SOF_HDA_COMMON
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_INTEL_LNL

config SND_SOC_SOF_PANTHERLAKE
Expand All @@ -304,7 +300,6 @@ config SND_SOC_SOF_INTEL_NVL
tristate
select SND_SOC_SOF_HDA_COMMON
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_INTEL_PTL

config SND_SOC_SOF_NOVALAKE
Expand Down
8 changes: 8 additions & 0 deletions sound/soc/sof/intel/hda-common-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ const struct snd_sof_dsp_ops sof_hda_common_ops = {
.pcm_pointer = hda_dsp_pcm_pointer,
.pcm_ack = hda_dsp_pcm_ack,

.compr_open = hda_dsp_compr_open,
.compr_hw_params = hda_dsp_compr_hw_params,
.compr_hw_free = hda_dsp_stream_compr_hw_free,
.compr_close = hda_dsp_compr_close,
.compr_trigger = hda_dsp_compr_trigger,
.compr_pointer = hda_dsp_compr_pointer,
.compr_get_dai_frame_counter = hda_dsp_compr_get_stream_llp,

.get_dai_frame_counter = hda_dsp_get_stream_llp,
.get_host_byte_counter = hda_dsp_get_stream_ldp,

Expand Down
Loading
Loading