Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
91eae13
Revert "ASoC: SOF: ipc4/Intel: Rename dsp_max_burst_size_in_ms to dsp…
ujfalusi Apr 24, 2026
9fdc25f
Revert "ASoC: SOF: ipc4-topology: Change DeepBuffer from static to dy…
ujfalusi Apr 24, 2026
fd9d0c8
-- dynamic deepbuffer revert --
ujfalusi Apr 24, 2026
1fcbe3f
ASoC: SOF: Intel: hda: Fold mlink enumeration into hda_dsp_ctrl_init_…
ujfalusi Apr 17, 2026
32920e4
ASoC: SOF: Intel: hda: Keep non-alt mlinks powered at probe on ACE2+
ujfalusi Apr 17, 2026
3f2cad6
ASoC: SOF: Intel: hda: Remove unused hda_bus_ml_put_all()
ujfalusi Apr 22, 2026
9cc3697
ASoC: SOF: Intel: hda: Avoid ACE2+ link DMA stream allocation hazards
ujfalusi Apr 20, 2026
7af7d8d
-- PPLC_LLP fix --
ujfalusi Apr 24, 2026
f99a68a
ASoC: SOF: Intel: hda-stream: clear hstream->running flag in hw_params
ujfalusi Mar 5, 2026
69d967a
ASoC: SOF: ipc4-pcm: Continue the pipeline trigger in case of IPC tim…
ujfalusi Mar 17, 2026
aee133a
ASoC: SOF: ipc4-control: Use local copy of IPC message for sending
ujfalusi Apr 16, 2026
fa8343d
-- misc --
ujfalusi Apr 24, 2026
26e68fd
ALSA: compress: pin card module while stream is open
ujfalusi Apr 24, 2026
ac343ad
ALSA: compress: stop active streams on disconnect
ujfalusi Apr 24, 2026
02a51d0
ASoC: soc-pcm: Allocate be_substream->runtime for compressed streams
ujfalusi Jan 13, 2026
60eb0fc
ASoC: soc-compress: Implement trigger FE-BE sequencing as with normal…
ujfalusi Jan 27, 2026
3d47839
ASoC: soc-compress: Stop running dpcm on free
ujfalusi Feb 3, 2026
c0da003
ASoC: SOF: compress: Rename compress ops with ipc3 prefix
ranj063 Dec 9, 2025
f48bee9
ASoC: SOF: ipc4-pcm: harden pipeline teardown races
ujfalusi Apr 24, 2026
dc0ac13
ASoC: SOF: sof-audio: harden recursive widget free walk
ujfalusi Apr 24, 2026
9d10af5
ASoC: SOF: sof-audio: Expose a couple of functions
ranj063 Dec 9, 2025
7d17445
ASoC: SOF: pcm: Modify the signature of a couple of PCM IPC ops
ranj063 Dec 9, 2025
825e07c
ASoC: SOF: intel: hda-stream: Clear the current position when releasi…
ranj063 Dec 9, 2025
a715cc5
ASoC: SOF: ops: Add new platform-specific ops for compress
ranj063 Dec 9, 2025
7cde159
ASoC: SOF: ipc4: Add definition of module data in init_ext object type
ujfalusi Jan 12, 2026
e4e3125
ASoC: SOF: ipc4-topology: Support init_ext_module_data for process mo…
ujfalusi Jan 13, 2026
b10581e
ASoC: SOF: ipc4-pcm: Make the timestamp info usable outside of ipc4-p…
ujfalusi Jan 13, 2026
4638433
ASoC: SOF: ipc4/ipc4-loader: Add SOF_INFO and CODEC_INFO to fw_config…
ujfalusi Jan 14, 2026
7cced90
ASoC: SOF: ipc4-pcm: Handle COMPR DRAIN triggers as EOS pipeline state
ujfalusi Jan 30, 2026
edbb149
ASoC: SOF: ipc4-topology: Set FAST_MODE for host copier in compr mode
ujfalusi Jan 30, 2026
7a10972
ASoC: SOF: Add support for IPC4 compressed
ranj063 Dec 9, 2025
3858a27
ASoC: SOF: ipc4: Handle compressed drain done notification from firmware
ujfalusi Jan 30, 2026
a787ffc
ASoC: SOF: Intel: Kconfig: Remove redundant IPC version selects
ujfalusi Dec 31, 2025
7f929df
ASoC: SOF: Intel: Kconfig: Select compress support for TGL+ platforms
ujfalusi Dec 31, 2025
e5d28c6
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
2 changes: 2 additions & 0 deletions include/sound/compress_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ struct snd_compr_ops {
* @card: sound card pointer
* @direction: Playback or capture direction
* @lock: device lock
* @open_list: list of open compress files
* @device: device id
* @use_pause_in_draining: allow pause in draining, true when set
*/
Expand All @@ -199,6 +200,7 @@ struct snd_compr {
struct snd_card *card;
unsigned int direction;
struct mutex lock;
struct list_head open_list;
int device;
bool use_pause_in_draining;
#ifdef CONFIG_SND_VERBOSE_PROCFS
Expand Down
23 changes: 21 additions & 2 deletions include/sound/hda-mlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@
struct hdac_bus;
struct hdac_ext_link;

/**
* enum hda_bus_ml_link_type - mlink link type, used by SOF link DMA
* allocator constraints (see struct sof_intel_hda_dev).
*
* @HDA_BUS_ML_LINK_HDA: non-alt link, i.e. HDA codec or iDisp
* @HDA_BUS_ML_LINK_SDW: alt link, SoundWire
* @HDA_BUS_ML_LINK_UAOL: alt link, USB Audio Offload
* @HDA_BUS_ML_LINK_OTHER: alt link, SSP or DMIC
*/
enum hda_bus_ml_link_type {
HDA_BUS_ML_LINK_HDA,
HDA_BUS_ML_LINK_SDW,
HDA_BUS_ML_LINK_UAOL,
HDA_BUS_ML_LINK_OTHER,
};

#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_MLINK)

int hda_bus_ml_init(struct hdac_bus *bus);
Expand Down Expand Up @@ -49,11 +65,12 @@ int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num);
int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
int channel_mask, int stream_id, int dir);

void hda_bus_ml_put_all(struct hdac_bus *bus);
void hda_bus_ml_reset_losidv(struct hdac_bus *bus);
int hda_bus_ml_resume(struct hdac_bus *bus);
int hda_bus_ml_suspend(struct hdac_bus *bus);

enum hda_bus_ml_link_type hda_bus_ml_link_get_type(struct hdac_ext_link *hlink);

struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus);
struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus);
struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus);
Expand Down Expand Up @@ -169,11 +186,13 @@ hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
return 0;
}

static inline void hda_bus_ml_put_all(struct hdac_bus *bus) { }
static inline void hda_bus_ml_reset_losidv(struct hdac_bus *bus) { }
static inline int hda_bus_ml_resume(struct hdac_bus *bus) { return 0; }
static inline int hda_bus_ml_suspend(struct hdac_bus *bus) { return 0; }

static inline enum hda_bus_ml_link_type
hda_bus_ml_link_get_type(struct hdac_ext_link *hlink) { return HDA_BUS_ML_LINK_HDA; }

static inline struct hdac_ext_link *
hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus) { return NULL; }

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: 58 additions & 19 deletions sound/core/compress_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#endif

struct snd_compr_file {
struct list_head list;
unsigned long caps;
struct snd_compr_stream stream;
};
Expand Down Expand Up @@ -75,11 +76,11 @@ static inline void snd_compr_task_free_all(struct snd_compr_stream *stream) { }
static int snd_compr_open(struct inode *inode, struct file *f)
{
struct snd_compr *compr;
struct snd_compr_file *data;
struct snd_compr_runtime *runtime;
struct snd_compr_file *data = NULL;
struct snd_compr_runtime *runtime = NULL;
enum snd_compr_direction dirn;
int maj = imajor(inode);
int ret;
int ret = 0;

if ((f->f_flags & O_ACCMODE) == O_WRONLY)
dirn = SND_COMPRESS_PLAYBACK;
Expand All @@ -101,17 +102,23 @@ static int snd_compr_open(struct inode *inode, struct file *f)
return -ENODEV;
}

if (!try_module_get(compr->card->module)) {
snd_card_unref(compr->card);
return -EFAULT;
}

if (dirn != compr->direction) {
pr_err("this device doesn't support this direction\n");
snd_card_unref(compr->card);
return -EINVAL;
ret = -EINVAL;
goto __error;
}

data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
snd_card_unref(compr->card);
return -ENOMEM;
ret = -ENOMEM;
goto __error;
}
INIT_LIST_HEAD(&data->list);

INIT_DELAYED_WORK(&data->stream.error_work, error_delayed_work);

Expand All @@ -121,9 +128,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
data->stream.device = compr;
runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
if (!runtime) {
kfree(data);
snd_card_unref(compr->card);
return -ENOMEM;
ret = -ENOMEM;
goto __error;
}
runtime->state = SNDRV_PCM_STATE_OPEN;
init_waitqueue_head(&runtime->sleep);
Expand All @@ -132,11 +138,17 @@ static int snd_compr_open(struct inode *inode, struct file *f)
#endif
data->stream.runtime = runtime;
f->private_data = (void *)data;
scoped_guard(mutex, &compr->lock)
scoped_guard(mutex, &compr->lock) {
ret = compr->ops->open(&data->stream);
if (!ret)
list_add_tail(&data->list, &compr->open_list);
}

__error:
if (ret) {
kfree(runtime);
kfree(data);
module_put(compr->card->module);
}
snd_card_unref(compr->card);
return ret;
Expand All @@ -146,24 +158,31 @@ static int snd_compr_free(struct inode *inode, struct file *f)
{
struct snd_compr_file *data = f->private_data;
struct snd_compr_runtime *runtime = data->stream.runtime;
struct snd_compr *compr = data->stream.device;

cancel_delayed_work_sync(&data->stream.error_work);

switch (runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
break;
default:
break;
scoped_guard(mutex, &compr->lock) {
if (!list_empty(&data->list))
list_del_init(&data->list);

switch (runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
break;
default:
break;
}
}

snd_compr_task_free_all(&data->stream);

data->stream.ops->free(&data->stream);
if (!data->stream.runtime->dma_buffer_p)
kfree(data->stream.runtime->buffer);
module_put(data->stream.device->card->module);
kfree(data->stream.runtime);
kfree(data);
return 0;
Expand Down Expand Up @@ -1415,8 +1434,27 @@ static int snd_compress_dev_register(struct snd_device *device)
static int snd_compress_dev_disconnect(struct snd_device *device)
{
struct snd_compr *compr;
struct snd_compr_file *data;

compr = device->device_data;
scoped_guard(mutex, &compr->lock) {
list_for_each_entry(data, &compr->open_list, list) {
switch (data->stream.runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
case SNDRV_PCM_STATE_PAUSED:
data->stream.ops->trigger(&data->stream,
SNDRV_PCM_TRIGGER_STOP);
break;
default:
break;
}

data->stream.runtime->state = SNDRV_PCM_STATE_DISCONNECTED;
wake_up(&data->stream.runtime->sleep);
}
}

snd_unregister_device(compr->dev);
return 0;
}
Expand Down Expand Up @@ -1524,6 +1562,7 @@ int snd_compress_new(struct snd_card *card, int device,
compr->device = device;
compr->direction = dirn;
mutex_init(&compr->lock);
INIT_LIST_HEAD(&compr->open_list);

snd_compress_set_id(compr, id);

Expand Down
87 changes: 78 additions & 9 deletions sound/soc/soc-compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
struct snd_soc_dpcm *dpcm;
int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */

/*
* The core will not send a STOP trigger on free if the device is in
* DRAIN state, but we need to stop BE and FE before we can proceed to
* free the stream.
* Run the a STOP trigger if the DPCM state is START (DRAIN is not
* changing the DPCM state).
*/
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_START)
cstream->ops->trigger(cstream, SNDRV_PCM_TRIGGER_STOP);

snd_soc_card_mutex_lock(fe->card);

snd_soc_dpcm_mutex_lock(fe);
Expand Down Expand Up @@ -273,31 +283,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
Loading
Loading