Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions app/compr_overlay.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# the cadence_libs directory should be in one level up from the sof
# project dir: sof/../cadence_libs/
# which is zephyr/../cadence_libs/

CONFIG_CADENCE_CODEC=y
CONFIG_CADENCE_CODEC_MP3_DEC=y
CONFIG_CADENCE_CODEC_MP3_DEC_LIB="../cadence_libs/xa_mp3_dec.a"
CONFIG_CADENCE_CODEC_MP3_ENC=y
CONFIG_CADENCE_CODEC_MP3_ENC_LIB="../cadence_libs/xa_mp3_enc.a"
CONFIG_CADENCE_CODEC_AAC_DEC=y
CONFIG_CADENCE_CODEC_AAC_DEC_LIB="../cadence_libs/xa_aac_dec.a"
CONFIG_CADENCE_CODEC_VORBIS_DEC=y
CONFIG_CADENCE_CODEC_VORBIS_DEC_LIB="../cadence_libs/xa_vorbis_dec.a"
Comment on lines +5 to +13
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

This overlay relies on relative library paths (e.g., ../cadence_libs/...) but doesn’t document the expected directory layout or where the paths are resolved from during builds. Add brief comments at the top of the file explaining the expected location of cadence_libs/ relative to the build/app directory, and how users should adjust these paths for their environment.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I'll add a comment to the compr_overlay.conf file as well.


60 changes: 60 additions & 0 deletions src/audio/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <ipc4/pipeline.h>
#include <ipc4/logging.h>
#include <ipc/topology.h>
#include <ipc/compress_params.h>
#include <sof_versions.h>
#include <sof/lib/cpu-clk-manager.h>
#include <sof/lib/cpu.h>
Expand Down Expand Up @@ -65,6 +66,63 @@ __cold static uint32_t get_host_buffer_size(void)
return periods;
}

struct sof_ipc4_codec_info_data {
uint32_t count;
uint32_t items[32];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why 32? Future-proofing or aligning to some existing spec/convention?

} __packed __aligned(4);

#define SET_CODEC_INFO_ITEM(codec, dir) (((codec) & 0xff) | (((dir) & 0xff) << 16))
Copy link
Collaborator

Choose a reason for hiding this comment

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

internally 16 bits would be enough, I presume 32 bits are used for compatibility with external standards?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The codec ID (lower 16bit) is actually defined in compress_params.h to be stored as __u32, max is 0x11 atm, so 8bit should be fine with bit7 as direction, but if I recall the fw_config itself have 32bit alignment requirement, all other flags are also stored as u32, so we follow this through
Is this acceptable answer @lyakh, @kv2019i ?

Copy link
Member

Choose a reason for hiding this comment

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

any reason we are trying to save here, why not just go for 31bits ID and 1 bit direction to start with ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that would make more sense I guess, need ot align the kernel PR as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

compress direction have 3 values:

enum snd_compr_direction {
        SND_COMPRESS_PLAYBACK = 0,
        SND_COMPRESS_CAPTURE,
        SND_COMPRESS_ACCEL
};

I guess we could use bit 30-31, that would allow one more value for future proofing.
I'll go with something which is bit more compact:
BIT 0-7 (8 bits): codec_id
BIT 8-11 (4 bits): dir
and we leave BIT 12-31 for future use if needed.


static void get_codec_info(struct sof_tlv **tuple)
{
struct sof_ipc4_codec_info_data codec_info = { 0 };

#ifdef CONFIG_CADENCE_CODEC_AAC_DEC
codec_info.items[codec_info.count++] =
SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_AAC, SOF_IPC_STREAM_PLAYBACK);
#endif
#ifdef CONFIG_CADENCE_CODEC_MP3_DEC
codec_info.items[codec_info.count++] =
SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_MP3, SOF_IPC_STREAM_PLAYBACK);
#endif
#ifdef CONFIG_CADENCE_CODEC_MP3_ENC
codec_info.items[codec_info.count++] =
SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_MP3, SOF_IPC_STREAM_CAPTURE);
#endif
#ifdef CONFIG_CADENCE_CODEC_VORBIS_DEC
codec_info.items[codec_info.count++] =
SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_VORBIS, SOF_IPC_STREAM_PLAYBACK);
#endif

if (!codec_info.count)
return;

tlv_value_set(*tuple, IPC4_SOF_CODEC_INFO, sizeof(codec_info.count) +
sizeof(codec_info.items[0]) * codec_info.count, &codec_info);

*tuple = tlv_next(*tuple);
}

#define SOF_CONFIG_MEMBER_SIZE(struct_name) (sizeof(struct sof_tlv) + \
sizeof(struct struct_name))
#define SOF_CONFIG_SIZE_MAX (SOF_CONFIG_MEMBER_SIZE(sof_ipc4_codec_info_data))

static void base_fw_sof_config(struct sof_tlv **tuple)
{
char sof_config_data[SOF_CONFIG_SIZE_MAX] = { 0 };
struct sof_tlv *sof_config_tuple = (struct sof_tlv *)sof_config_data;
uint32_t sof_config_size;

get_codec_info(&sof_config_tuple);
sof_config_size = (uint32_t)((char *)sof_config_tuple - sof_config_data);
if (sof_config_size == 0)
return;

tlv_value_set(*tuple, IPC4_FW_SOF_INFO, sof_config_size, sof_config_data);

*tuple = tlv_next(*tuple);
}

__cold static int basefw_config(uint32_t *data_offset, char *data)
{
uint16_t version[4] = {SOF_MAJOR, SOF_MINOR, SOF_MICRO, SOF_BUILD};
Expand Down Expand Up @@ -150,6 +208,8 @@ __cold static int basefw_config(uint32_t *data_offset, char *data)

tuple = tlv_next(tuple);

base_fw_sof_config(&tuple);

/* add platform specific tuples */
basefw_vendor_fw_config(&plat_data_offset, (char *)tuple);

Expand Down
37 changes: 20 additions & 17 deletions src/audio/host-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,27 +478,30 @@ static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev
* in order to avoid high load spike
* if FAST_MODE is enabled, then one period limitation is omitted
*/
if (!(hd->ipc_host.feature_mask & BIT(IPC4_COPIER_FAST_MODE)))
dma_copy_bytes = MIN(hd->period_bytes, dma_copy_bytes);

const uint64_t now = k_uptime_get();
const uint64_t delta = now - hd->nobytes_last_logged;
const bool reset_skipped = delta > SOF_MIN_NO_BYTES_INTERVAL_MS;
if (!(hd->ipc_host.feature_mask & BIT(IPC4_COPIER_FAST_MODE))) {
const uint64_t now = k_uptime_get();
const uint64_t delta = now - hd->nobytes_last_logged;
const bool reset_skipped = delta > SOF_MIN_NO_BYTES_INTERVAL_MS;

if (hd->n_skipped > 1 && (dma_copy_bytes || reset_skipped)) {
comp_warn(dev, "Skipped %u no-bytes events in last %llu ms, bytes %u",
hd->n_skipped - 1, delta, dma_copy_bytes);
hd->n_skipped = 0;
}
dma_copy_bytes = MIN(hd->period_bytes, dma_copy_bytes);

if (!dma_copy_bytes) {
if (!hd->n_skipped || reset_skipped) {
hd->nobytes_last_logged = now;
if (hd->n_skipped > 1 && (dma_copy_bytes || reset_skipped)) {
comp_warn(dev,
"Skipped %u no-bytes events in last %llu ms, bytes %u",
hd->n_skipped - 1, delta, dma_copy_bytes);
hd->n_skipped = 0;
comp_warn(dev, "no bytes to copy, available samples: %u, free_samples: %u",
avail_samples, free_samples);
}
hd->n_skipped++;

if (!dma_copy_bytes) {
if (!hd->n_skipped || reset_skipped) {
hd->nobytes_last_logged = now;
hd->n_skipped = 0;
comp_warn(dev,
"no bytes to copy, available samples: %u, free_samples: %u",
avail_samples, free_samples);
}
hd->n_skipped++;
}
}

/* dma_copy_bytes should be aligned to minimum possible chunk of
Expand Down
4 changes: 4 additions & 0 deletions src/audio/module_adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ endif()
zephyr_library_import(xa_aac_dec ${CONFIG_CADENCE_CODEC_AAC_DEC_LIB})
endif()

if (CONFIG_CADENCE_CODEC_VORBIS_DEC)
zephyr_library_import(xa_vorbis_dec ${CONFIG_CADENCE_CODEC_VORBIS_DEC_LIB})
endif()

if (CONFIG_CADENCE_CODEC_MP3_DEC)
zephyr_library_import(xa_mp3_dec ${CONFIG_CADENCE_CODEC_MP3_DEC_LIB})
endif()
Expand Down
13 changes: 13 additions & 0 deletions src/audio/module_adapter/module/cadence.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ int cadence_codec_init_process(struct processing_module *mod)
struct cadence_codec_data *cd = codec->private;
struct comp_dev *dev = mod->dev;

codec->mpd.eos_reached = false;
codec->mpd.eos_notification_sent = false;

API_CALL(cd, XA_API_CMD_SET_INPUT_BYTES, 0, &codec->mpd.avail, ret);
if (ret != LIB_NO_ERROR) {
comp_err(dev, "error %x: failed to set size of input data",
Expand Down Expand Up @@ -475,6 +478,13 @@ int cadence_codec_process_data(struct processing_module *mod)
struct comp_dev *dev = mod->dev;
int ret;

if (codec->mpd.eos_reached) {
codec->mpd.produced = 0;
codec->mpd.consumed = 0;

return 0;
}

API_CALL(cd, XA_API_CMD_SET_INPUT_BYTES, 0, &codec->mpd.avail, ret);
if (ret != LIB_NO_ERROR) {
comp_err(dev, "failed to set size of input data with error: %x:", ret);
Expand Down Expand Up @@ -503,5 +513,8 @@ int cadence_codec_process_data(struct processing_module *mod)
return ret;
}

if (!codec->mpd.produced && dev->pipeline->expect_eos)
codec->mpd.eos_reached = true;

return 0;
}
35 changes: 35 additions & 0 deletions src/audio/module_adapter/module/cadence_ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#include <sof/audio/cadence/mp3_dec/xa_mp3_dec_api.h>
#include <sof/audio/cadence/mp3_enc/xa_mp3_enc_api.h>
#include <sof/audio/cadence/aac_dec/xa_aac_dec_api.h>
#include <sof/ipc/msg.h>
#include <sof/schedule/ll_schedule_domain.h>
#include <ipc/compress_params.h>
#include <ipc4/notification.h>
#include <rtos/init.h>

SOF_DEFINE_REG_UUID(cadence_codec);
Expand Down Expand Up @@ -204,6 +206,9 @@ static int cadence_configure_codec_params(struct processing_module *mod)
return cadence_configure_mp3_enc_params(mod);
case CADENCE_CODEC_AAC_DEC_ID:
return cadence_configure_aac_dec_params(mod);
case CADENCE_CODEC_VORBIS_DEC_ID:
/* No configuration needed for Vorbis */
return 0;
default:
break;
}
Expand Down Expand Up @@ -465,6 +470,36 @@ static int cadence_codec_process(struct processing_module *mod, struct sof_sourc
return ret;
}

if (codec->mpd.eos_reached && !codec->mpd.eos_notification_sent) {
struct ipc_msg msg_proto;
struct comp_ipc_config *ipc_config = &dev->ipc_config;
union ipc4_notification_header *primary =
(union ipc4_notification_header *)&msg_proto.header;
struct sof_ipc4_notify_module_data *msg_module_data;
struct ipc_msg *msg;

memset_s(&msg_proto, sizeof(msg_proto), 0, sizeof(msg_proto));
primary->r.notif_type = SOF_IPC4_MODULE_NOTIFICATION;
primary->r.type = SOF_IPC4_GLB_NOTIFICATION;
primary->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST;
primary->r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG;
msg = ipc_msg_w_ext_init(msg_proto.header, msg_proto.extension,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like a good place to use ipc_notification_pool_get

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would a followup patch do?
All module messages are using this mode and it will be better to update them with a single PR.
We can most likely also add helper to src/ipc/ipc4/notification.c for these at the same round?

sizeof(*msg_module_data));
if (msg) {
msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data;
msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id);
msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id);
msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL;
msg_module_data->event_data_size = 0;

ipc_msg_send(msg, NULL, false);
codec->mpd.eos_notification_sent = true;
}

/* Set EOS for the sink as we are not going to produce more data */
audio_buffer_set_eos(sof_audio_buffer_from_sink(sinks[0]));
}

/* do not proceed if not enough free space left */
if (out_space < codec->mpd.produced) {
source_release_data(sources[0], 0);
Expand Down
16 changes: 16 additions & 0 deletions src/include/ipc4/base_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,12 +376,28 @@ enum ipc4_fw_config_params {
IPC4_FW_CONTEXT_SAVE = 29,
/* Minimum size of host buffer in ms */
IPC4_FW_MIN_HOST_BUFFER_PERIODS = 33,
/* decoder/encoder codec information */
IPC4_FW_SOF_INFO = 35,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If this ID is good than we need to reserve it...

Copy link
Collaborator

Choose a reason for hiding this comment

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

35 seems free. We need to reserve it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, can we initiate the reservation process?
This will reduce the collision surface for future in both ways.

/* Total number of FW config parameters */
IPC4_FW_CFG_PARAMS_COUNT,
/* Max config parameter id */
IPC4_MAX_FW_CFG_PARAM = IPC4_FW_CFG_PARAMS_COUNT - 1,
};

/*
* tuple based array for SOF specific information under IPC4_FW_SOF_INFO
* tuple of fw_config
*/
enum ipc4_fw_sof_info_params {
/* decoder/encoder codec information */
IPC4_SOF_CODEC_INFO = 0,

/* Total number of SOF config parameters */
IPC4_SOF_CFG_PARAMS_COUNT,
/* Max config parameter id */
IPC4_MAX_SOF_CFG_PARAM = IPC4_SOF_CFG_PARAMS_COUNT - 1,
};

enum ipc4_hw_config_params {
/* Version of cAVS implemented by FW (from ROMInfo) */
IPC4_CAVS_VER_HW_CFG = 0,
Expand Down
1 change: 1 addition & 0 deletions src/include/ipc4/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ struct ipc4_message_reply {
#define SOF_IPC4_ENUM_CONTROL_PARAM_ID 201
#define SOF_IPC4_BYTES_CONTROL_PARAM_ID 202
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL ((uint32_t)(0xA15A << 16))
#define SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL ((uint32_t)(0xC0C0 << 16))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

What about this magic value?
@lgirdwood, @ranj063, @kv2019i

Copy link
Member

Choose a reason for hiding this comment

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

fine by me.


/**
* struct sof_ipc4_ctrl_value_chan: generic channel mapped value data
Expand Down
2 changes: 2 additions & 0 deletions src/include/sof/audio/module_adapter/module/generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ struct module_processing_data {
uint32_t produced; /**< Specifies how much data the module produced in its last task.*/
uint32_t consumed; /**< Specified how much data the module consumed in its last task */
uint32_t init_done; /**< Specifies if the module initialization is finished */
bool eos_reached; /**< End of stream processing is reached */
bool eos_notification_sent; /**< EOS notification is sent to host */
void *in_buff; /**< A pointer to module input buffer. */
void *out_buff; /**< A pointer to module output buffer. */
};
Expand Down
4 changes: 4 additions & 0 deletions tools/rimage/config/lnl.toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
#include <audio/src/src.toml>
#endif

#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/module_adapter/module/cadence.toml>
#endif

#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/selector/selector.toml>
#endif
Expand Down
4 changes: 4 additions & 0 deletions tools/rimage/config/mtl.toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
#include <audio/mux/mux.toml>
#endif

#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/module_adapter/module/cadence.toml>
#endif

#ifdef CONFIG_SAMPLE_KEYPHRASE
#include <samples/audio/detect_test.toml>
#endif
Expand Down
4 changes: 4 additions & 0 deletions tools/rimage/config/nvl.toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ index = __COUNTER__
#include <audio/src/src.toml>
#endif

#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/module_adapter/module/cadence.toml>
#endif

#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/selector/selector.toml>
#endif
Expand Down
4 changes: 4 additions & 0 deletions tools/rimage/config/ptl.toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ index = __COUNTER__
#include <audio/src/src.toml>
#endif

#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/module_adapter/module/cadence.toml>
#endif

#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/selector/selector.toml>
#endif
Expand Down
4 changes: 4 additions & 0 deletions tools/rimage/config/wcl.toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ index = __COUNTER__
#include <audio/src/src.toml>
#endif

#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/module_adapter/module/cadence.toml>
#endif

#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR)
#include <audio/selector/selector.toml>
#endif
Expand Down
Loading