Skip to content

ASoC: SOF: Initial support for IPC4 compress offload#5647

Draft
ujfalusi wants to merge 35 commits intothesofproject:topic/sof-devfrom
ujfalusi:peter/topic/ipc4_compr
Draft

ASoC: SOF: Initial support for IPC4 compress offload#5647
ujfalusi wants to merge 35 commits intothesofproject:topic/sof-devfrom
ujfalusi:peter/topic/ipc4_compr

Conversation

@ujfalusi
Copy link
Copy Markdown
Collaborator

@ujfalusi ujfalusi commented Jan 14, 2026

Hi,

Support for compress offload with IPC4 on Intel platforms (MTL+).

This initial version supports basic features, like PAUSE PUSH/RELEASE, DRAIN, progress reporting.
Tested with PCM, MP3, AAC and VORBIS codecs so far with firmware built from the following repo (will be making it's way to sof:main): https://github.com/ujfalusi/sof/commits/peter/topic/ipc4_compr

@dbaluta, if you could be able to test that, we would really appreciate it.

firmware PR (without topology changes): thesofproject/sof#10492 (merged), thesofproject/sof#10534 (open)

@ujfalusi
Copy link
Copy Markdown
Collaborator Author

I don't see these errors with gcc (GCC) 15.2.1 20251112 locally, hrm.

@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch from cea54e7 to c3f4c47 Compare January 14, 2026 14:08
@ujfalusi ujfalusi changed the title ASoC: SOF: Initial support for IPCV4 compress offload ASoC: SOF: Initial support for IPC4 compress offload Jan 19, 2026
@dbaluta
Copy link
Copy Markdown
Collaborator

dbaluta commented Jan 19, 2026

Will test this on IMX platforms, but we are only using IPC3 so not sure how much it helps. I'm not working on moving IMX to IPC4 but it will take a while.

Will be back with the results asap.

@ujfalusi
Copy link
Copy Markdown
Collaborator Author

Will test this on IMX platforms, but we are only using IPC3 so not sure how much it helps. I'm not working on moving IMX to IPC4 but it will take a while.

@dbaluta, we want to make sure that we don't break iMX (IPC3) and we are on reverse grounds that we can only test the new IPC4 support.

Will be back with the results asap.

Thank you!

Copy link
Copy Markdown
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, some minor opens, some rebasing/squashing probably needed.

Comment thread sound/soc/soc-pcm.c
Comment thread sound/soc/sof/ipc4-priv.h
Comment thread sound/soc/sof/ipc4-compress.c
Comment thread sound/soc/sof/ipc4-compress.c Outdated
Comment thread sound/soc/sof/ipc4-compress.c
Comment thread sound/soc/sof/ipc4-compress.c Outdated
/*
* stream_start_offset is updated to memory window by FW based on
* pipeline statistics and it may be invalid if host query happens before
* the statistics is complete. And it will not change after the first initiailization.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may need a comment on whether header is included or not.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header has no meaning in here, this is pure PCM data, exactly like normal PCMs, we count the samples played out.

Comment thread sound/soc/sof/ipc4-compress.c Outdated

out:
caps->direction = cstream->direction;
caps->min_fragment_size = 3 * 1024;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on any particular format ? Maybe worth a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gut feeling ;) I will add defines :D

@dbaluta
Copy link
Copy Markdown
Collaborator

dbaluta commented Jan 20, 2026

@ujfalusi Tested this today with sof-dev branch and I get some problems but could be unrelated to the change. Need to check if we have some internal patches not upstreamed.

@dbaluta
Copy link
Copy Markdown
Collaborator

dbaluta commented Jan 21, 2026

@ujfalusi Tested the patches with IMX8MP using IPC3 compress implementation with MP3 and AAC and it works fine. I will add my comments to the code later.

Comment thread sound/soc/sof/ipc4-compress.c
@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch 3 times, most recently from 228cd7c to a57957e Compare January 22, 2026 12:36
@ujfalusi
Copy link
Copy Markdown
Collaborator Author

Changes since v2:

  • rewrite how we report the min fragment size to handle deep buffer on host side

@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch 2 times, most recently from 52d57d7 to f992ff0 Compare January 22, 2026 15:04
@ujfalusi
Copy link
Copy Markdown
Collaborator Author

Changes since v3:

  • fix ERROR: modpost: "__udivdi3" [sound/soc/sof/snd-sof.ko] undefined! in x86_32 build

@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch from f992ff0 to f16f40d Compare January 23, 2026 08:37
@ujfalusi
Copy link
Copy Markdown
Collaborator Author

Changes since v4:
Drop the min_fragment_size storage in sof_compr_stream and remove the use of it in ipc4 code:
It was allocated and stored behind cstream->runtime->private_data, but that pointer is also used by the Intel platform code and it was overtaken on open.
So, (1) we were leaking memory, (2) we were accessing cstream->runtime->private_data data which points to a completely different struct.

It is a surprise that this did not blow up, but it somehow managed to 'work', just that the min_fragment_size turned 0 after the compr_open (as we used the data for read only).

Added a helper to calculate on spot the minimal fragment size instead, it is used only during open operation.

@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch from f16f40d to fadeee4 Compare January 23, 2026 14:42
@ujfalusi
Copy link
Copy Markdown
Collaborator Author

Changes since v5:

  • small tidy-ups in ipc4-compress.c and print out the fragments in set_params - so whoever is debugging does not need to reach for calculator ;)

lgirdwood
lgirdwood previously approved these changes Jan 26, 2026
Copy link
Copy Markdown
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@ujfalusi
Copy link
Copy Markdown
Collaborator Author

Changes since v6:

  • support for DRAIN trigger
  • correct the call sequences to match with PCM handling to align with hardware programming flows
  • Set FAST_MODE for host copier in case of compr device

There is not yet corresponding firmware PR, the WIP branch for testing is https://github.com/ujfalusi/sof/commits/peter/topic/ipc4_compr

@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch from e22d68e to bc8f6ba Compare February 2, 2026 10:25
@ujfalusi
Copy link
Copy Markdown
Collaborator Author

ujfalusi commented Feb 2, 2026

Changes since v7:

  • New patch to ALSA compr to add a flag to keep the RUNNING state after drain
  • Block compressed use if the booted firmware is missing compr support (codec info or num_codecs are NULL or 0)
  • Set the flag to require the RUNNING state after drain for SOF

With this version end of file drain works correctly without errors from BE.

@ujfalusi
Copy link
Copy Markdown
Collaborator Author

ujfalusi commented Feb 3, 2026

Changes since v8:

  • revert the flag for keeping the compr in RUNNING state in ALSA core and replace it with a patch soc-compress to send a trigger STOP in case the stream has not been stopped. Like after DRAIN.

Copy link
Copy Markdown
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its looking good @ujfalusi any final things todo ?

@ujfalusi
Copy link
Copy Markdown
Collaborator Author

ujfalusi commented Feb 5, 2026

Its looking good @ujfalusi any final things todo ?

I need to move patches around and squash them, also aligning on the param ids in firmware config, plus the notification magic for EOS completion.
and I'm experimenting on something else to simplify the host side topology.

@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch from f21f5f1 to b7122bb Compare February 6, 2026 12:59
ujfalusi and others added 29 commits April 24, 2026 16:28
On ACE2+ platforms the link DMA stream allocator must avoid two
hardware errata in mlink-capable systems:

- Concurrent (cross-direction) hazard: when SoundWire shares a physical
  link DMA stream index with HDaudio, iDisp or UAOL across the two
  directions, the LLP and timestamp values for the affected stream are
  wrong. SSP and DMIC are not affected because every DMA request from
  those links carries one sample block.

- Sequential (playback only) hazard: once a HDaudio or iDisp link has
  used a playback stream index, that index cannot drive any non
  HDA/iDisp link in the same direction until the next controller
  reset (CRST#).

Track the active link type per direction in two masks (one for SoundWire,
one for HDA/iDisp/UAOL) and the persistent set of playback stream
indices touched by HDA/iDisp in a third mask. The link DMA allocator
skips streams that would violate either rule. Streams are released from
the active masks when the stream is released; all masks are cleared in
hda_dsp_ctrl_init_chip() because the CRST# performed there clears the
hardware state as well.

A new helper hda_bus_ml_link_get_type() returns the link type from the
existing extended link descriptor so the SOF allocator can tell
SoundWire, HDA/iDisp and UAOL apart without duplicating the parsing.

The implementation is generic. On platforms older than ACE2 every link
is reported as HDA, only the sequential mask is ever set and it has no
effect because no other link types are present, so behavior is
unchanged.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
During hw_params call we make sure that the host DMA is stopped but the
hstream->running flag is not explicitly cleared at the same time.

If the host DMA fails to stop during previous use then the flag is left
set and on next start the host DMA will be left disabled since the
trigger:STOP will skip the DMA enable.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…eout

Ignore IPC errors for pipeline state change if the firmware state is
crashed or the IPC has timed out.

If the firmware has crashed the kernel still needs to go through the state
changes to reset its internal to be able to correctly work the next time
the DSP is booted up.

The case with IPC timeout is a bit more problematic, but it has been
rootcaused to be the result of system scheduling blockage and the firmware
did actually received and handled the message, but the reply handling got
blocked by issues outside of the SOF stack.
So far the best way to handle this is to continue with setting the state.

Fixes: c40aad7 ("ASoC: SOF: ipc4-pcm: Workaround for crashed firmware on system suspend")
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
If a kcontrol update comes to a control right at the same time when the
PCM containing the control is started up then there is a small window when
a race can happen:
while the widget is set up the swidget->setup_mutex is taken in topology
level and if the control update comes at this point, it will be stopped
within sof_ipc4_set_get_kcontrol_data() with the mutex and it will be
blocked until the swidget setup is done, which will clear the control's
IPC message payload.

To avoid such race, use local copy of the template IPC message instead of
the template directly. This will ensure data integrity in case of
concurrent updates during initialization.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Take a module reference in snd_compr_open() and release it in
snd_compr_free(). This pins the card driver module for the
lifetime of an open compress stream and prevents card removal
while the stream file is still in use.

Adjust the open() cleanup paths to drop the added module
reference only when it was acquired, and keep release ordering
safe by dropping the module reference before freeing stream
data.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Track open compressed streams per device so disconnect can stop
active streams and wake waiters before snd_unregister_device().

This aligns compressed stream teardown with PCM disconnect behavior
and prevents active userspace streams from running into unregister
races.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
With DPCM when compr is used on FE side, the BE is still running as
'normal' PCM.
It is expected that the be_substream->runtime on the BE is not NULL, for
example some codec drivers expect to have the substream->runtime valid, to
store configuration for example.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
… PCMs

The FE-BE trigger sequence should be dynamic, similarly how soc-pcm.c
dpcm_fe_dai_do_trigger() does it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
If the last trigger that the compr device received is a DRAIN then the
DPCM is left in running state (no stop trigger is sent).
Before we execute the free we need to send a STOP trigger to make sure that
both BE and FE is in expected state and prepared for closing.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
In preparation for adding support for compressed offload support for
IPC4, rename the current compress implementation with the IPC3 prefix.
Introduce a new field in struct sof_ipc_pcm_ops to save the
IPC-specific compressed ops pointer. This should be set when the
component driver ops are assigned during SOF device probe. Expose a couple
of common functions that will be used by both IPC-specific implementations
and rename the compress.c file to ipc3-compress.c

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Serialize trigger/free with pipeline_state_mutex and validate
pipeline entries before use.

Also clear pipeline_list->count when freeing lists to avoid stale
entries during concurrent teardown.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
During widget FREE traversal, SOF walks DAPM sink paths recursively while
widgets and paths can be torn down. This can lead to stale pointer usage in
sof_free_widgets_in_path() when path entries disappear during recursion.

Harden the FREE path by:
- validating scheduler/pipeline pointers before recursive free
- using a safe DAPM path iterator for sink traversal
- carrying a stable widget-list snapshot through recursion
- skipping NULL sink edges during traversal

The safe traversal can leave path->walking set on surviving edges after FREE,
which may short-circuit later DAPM walks and break consecutive playback
open/stop cycles. Reset walking flags for widgets in the current DAPM list
after FREE walks (including error paths) to keep subsequent traversals clean.

This keeps teardown robust for module-remove race scenarios while preserving
normal consecutive playback behavior.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
These are common functions that will also be needed for the IPC4
compressed support.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
In order to reuse the pipeline triggering logic for compressed support
with IPC4, modify the signature of the trigger and hw_free PCM IPC ops
so that they can be reused.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…ng stream

After the host DMA IID is released, reset the curr_pos to 0 for a clean
start for subsequent stream starts. This is not needed for PCM streams
but for compressed streams.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Add new ops in the struct snd_sof_ops for platform-specific ops for
compresssed streams. Also, define and set them for the HDA platforms.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The SOF_IPC4_MOD_INIT_DATA_ID_MODULE_DATA type within the module_init_ext
area is module specific init data.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…dules

Add support for handling init_ext_module_data for process modules, which is
going to be used by decoder and encoder type of process mdoules.
The support is generic and it can be extended to other type of process
modules or other module types than process with a small update of
sof_ipc4_add_init_ext_module_data() function.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…cm.c

The support for compressed stream will also need to have access to the
same information which is used for delay reporting for DAI data
progression tracking.

Make the necessary struct and functions to be available and premare them to
be called without a valid substream.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
…_params

SOF_INFO (id == 35) tuple holds tuple structured information about SOF
features.

The first entry in SOF_INFO is the SOF_CODEC_INFO (id == 0) which contains
information about the supported codecs for decode/encode in the booted
firmware.

If present in the fw_config payload, make a copy of it and store it
sof_ipc4_fw_data->codec_info to be used by the compressed code.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The DRAIN trigger is received by a compr device when user space wrote the
all data to the buffer and it is waiting for the decoding to be completed.

Set the pipeline state to EOS in firmware so it can expect the stream to
be stopping anytime soon.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
FAST_MODE allows the host DMA to work in opportunistic, free running mode,
which matches with the bitstream nature of compressed devices.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Set and define the compressed ops for IPC4.
The initial implementation supports basic features: PAUSE PUSH/RELEASE,
DRAIN and progress reporting.
Tested with PCM, MP3, AAC and VORBIS codec.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The decoder module sends a drain done notification when the last chunk of
the stream after the EOS from host has been decoded.

The notification is a module notification with 0xc0c0 as magic number in
event_id upper 16 bit.

Call sof_ipc4_compr_drain_done() when the notification arrives to handle
it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
There is no need to select IPC3 and IPC4 along with INTEL_CNL as INTEL_CNL
selects both.

Similarly, INTEL_MTL selects IPC4, so there is no need to do that for LNL,
PTL and NVL.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Select SOF_COMPRESS for TGL and newer platforms, on Intel devices the
compressed support is available with IPC4 only.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Decoder and encoder modules fall under process modules in SOF.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Co-developed-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
@ujfalusi ujfalusi force-pushed the peter/topic/ipc4_compr branch from 520962b to e5d28c6 Compare April 24, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants