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
3 changes: 3 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
if(CONFIG_COMP_TONE)
add_subdirectory(tone)
endif()
if(CONFIG_UAOL_INTEL_ADSP)
add_local_sources(sof uaol.c)
endif()
if(CONFIG_ZEPHYR_NATIVE_DRIVERS)
list(APPEND base_files host-zephyr.c)
sof_list_append_ifdef(CONFIG_COMP_DAI base_files dai-zephyr.c)
Expand Down
79 changes: 4 additions & 75 deletions src/audio/base_fw_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@
#include <sof/lib/memory.h>
#include <sof/lib_manager.h>

#if CONFIG_UAOL_INTEL_ADSP
#include <zephyr/drivers/uaol.h>
#endif

#include <ipc4/base_fw.h>
#include <ipc4/alh.h>
#include <rimage/sof/user/manifest.h>
Expand All @@ -37,6 +33,10 @@
#include <sof/audio/mic_privacy_manager.h>
#endif

#if CONFIG_UAOL_INTEL_ADSP
#include <sof/audio/uaol.h>
#endif

struct ipc4_modules_info {
uint32_t modules_count;
struct sof_man_module modules[0];
Expand All @@ -46,22 +46,6 @@ struct ipc4_modules_info {
STATIC_ASSERT(sizeof(struct ipc4_modules_info) < SOF_IPC_MSG_MAX_SIZE,
invalid_modules_info_struct_size);

#if CONFIG_UAOL_INTEL_ADSP
struct ipc4_uaol_link_capabilities {
uint32_t input_streams_supported : 4;
uint32_t output_streams_supported : 4;
uint32_t bidirectional_streams_supported : 5;
uint32_t rsvd : 19;
uint32_t max_tx_fifo_size;
uint32_t max_rx_fifo_size;
} __packed __aligned(4);

struct ipc4_uaol_capabilities {
uint32_t link_count;
struct ipc4_uaol_link_capabilities link_caps[];
} __packed __aligned(4);
#endif /* CONFIG_UAOL_INTEL_ADSP */

/*
* TODO: default to value of ACE1.x platforms. This is defined
* in multiple places in Zephyr, mm_drv_intel_adsp.h and
Expand Down Expand Up @@ -103,61 +87,6 @@ __cold int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
return 0;
}

#if CONFIG_UAOL_INTEL_ADSP
#define DEV_AND_COMMA(node) DEVICE_DT_GET(node),
static const struct device *uaol_devs[] = {
DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, DEV_AND_COMMA)
};

#if !CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY
__cold static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type)
{
const size_t dev_count = ARRAY_SIZE(uaol_devs);
struct uaol_capabilities dev_cap;
struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value;
size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]);
size_t i;
int ret;

assert_can_be_cold();

memset(caps, 0, caps_size);

caps->link_count = dev_count;
for (i = 0; i < dev_count; i++) {
ret = uaol_get_capabilities(uaol_devs[i], &dev_cap);
if (ret)
continue;

caps->link_caps[i].input_streams_supported = dev_cap.input_streams;
caps->link_caps[i].output_streams_supported = dev_cap.output_streams;
caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams;
caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size;
caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size;
}

tlv_value_set(tuple, type, caps_size, caps);
}
#endif /* CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY */

__cold static int uaol_stream_id_to_hda_link_stream_id(int uaol_stream_id)
{
size_t dev_count = ARRAY_SIZE(uaol_devs);
size_t i;

assert_can_be_cold();

for (i = 0; i < dev_count; i++) {
int hda_link_stream_id = uaol_get_mapped_hda_link_stream_id(uaol_devs[i],
uaol_stream_id);
if (hda_link_stream_id >= 0)
return hda_link_stream_id;
}

return -1;
}
#endif /* CONFIG_UAOL_INTEL_ADSP */

__cold int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
{
struct sof_tlv *tuple = (struct sof_tlv *)data;
Expand Down
2 changes: 1 addition & 1 deletion src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ __cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
dai.type = SOF_DAI_INTEL_UAOL;
dai.is_config_blob = true;
cd->gtw_type = ipc4_gtw_alh;
ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_size);
ret = ipc4_find_dma_config_tlv(&dai, gtw_cfg_data, gtw_cfg_size);
if (ret != IPC4_SUCCESS) {
comp_err(dev, "No uaol dma_config found in blob!");
return -EINVAL;
Expand Down
7 changes: 0 additions & 7 deletions src/audio/mixin_mixout/mixin_mixout.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,6 @@ struct ipc4_mixer_mode_config {
struct ipc4_mixer_mode_sink_config mixer_mode_sink_configs[1];
} __packed __aligned(4);

/* Pointer to data in circular buffer together with buffer boundaries */
struct cir_buf_ptr {
void *buf_start;
void *buf_end;
void *ptr;
};

/**
* \brief mixin processing function interface
*/
Expand Down
79 changes: 79 additions & 0 deletions src/audio/uaol.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2026 Intel Corporation. All rights reserved.
*/

#include <zephyr/drivers/uaol.h>
#include <rtos/string.h>
#include <sof/tlv.h>
#include <sof/audio/component_ext.h>
#include <sof/audio/uaol.h>

LOG_MODULE_REGISTER(uaol, CONFIG_SOF_LOG_LEVEL);

struct ipc4_uaol_link_capabilities {
uint32_t input_streams_supported : 4;
uint32_t output_streams_supported : 4;
uint32_t bidirectional_streams_supported : 5;
uint32_t rsvd : 19;
uint32_t max_tx_fifo_size;
uint32_t max_rx_fifo_size;
} __packed __aligned(4);

struct ipc4_uaol_capabilities {
uint32_t link_count;
struct ipc4_uaol_link_capabilities link_caps[];
} __packed __aligned(4);

#define DEV_AND_COMMA(node) DEVICE_DT_GET(node),
static const struct device *uaol_devs[] = {
DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, DEV_AND_COMMA)
};

#if !CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY
__cold void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type)
{
const size_t dev_count = ARRAY_SIZE(uaol_devs);
struct uaol_capabilities dev_cap;
struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value;
size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]);
size_t i;
int ret;

assert_can_be_cold();

memset(caps, 0, caps_size);

caps->link_count = dev_count;
for (i = 0; i < dev_count; i++) {
ret = uaol_get_capabilities(uaol_devs[i], &dev_cap);
if (ret)
continue;

caps->link_caps[i].input_streams_supported = dev_cap.input_streams;
caps->link_caps[i].output_streams_supported = dev_cap.output_streams;
caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams;
caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size;
caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size;
}

tlv_value_set(tuple, type, caps_size, caps);
}
#endif /* !CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY */

__cold int uaol_stream_id_to_hda_link_stream_id(int uaol_stream_id)
{
size_t dev_count = ARRAY_SIZE(uaol_devs);
size_t i;

assert_can_be_cold();

for (i = 0; i < dev_count; i++) {
int hda_link_stream_id = uaol_get_mapped_hda_link_stream_id(uaol_devs[i],
uaol_stream_id);
if (hda_link_stream_id >= 0)
return hda_link_stream_id;
}

return -1;
}
9 changes: 9 additions & 0 deletions src/include/sof/audio/audio_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ struct audio_stream {
struct sof_audio_stream_params runtime_stream_params;
};

/* A pointer to data in a ring buffer. Just for convenience to reduce the number of typical
* processing function parameters: e.g., just 3 parameters (in, out ptr, and size) instead of 7.
*/
struct cir_buf_ptr {
void *buf_start;
void *buf_end;
void *ptr;
};

void audio_stream_recalc_align(struct audio_stream *stream);

static inline void *audio_stream_get_rptr(const struct audio_stream *buf)
Expand Down
20 changes: 20 additions & 0 deletions src/include/sof/audio/uaol.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2026 Intel Corporation. All rights reserved.
*/

#ifndef __SOF_AUDIO_UAOL_H__
#define __SOF_AUDIO_UAOL_H__

#include <stdint.h>
#include <sof/lib/memory.h>

struct sof_tlv;

#if !CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY
__cold void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type);
#endif /* !CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY */

__cold int uaol_stream_id_to_hda_link_stream_id(int uaol_stream_id);

#endif /* __SOF_AUDIO_UAOL_H__ */
1 change: 1 addition & 0 deletions src/include/sof/ipc/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *d
int ipc4_process_on_core(uint32_t core, bool blocking);
int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id, uint32_t cmd);
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size);
int ipc4_find_dma_config_tlv(struct ipc_config_dai *dai, uint8_t *data_buffer, size_t size);
int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd);
int ipc4_pipeline_trigger(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *delayed);
int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer,
Expand Down
37 changes: 37 additions & 0 deletions src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,43 @@ int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint3
return IPC4_SUCCESS;
}

/* Unlike the above ipc4_find_dma_config(), this can find multiple DMA configs.
* For example, a UAOL copier may use two DMA channels: one for audio and one
* for clock feedback. This function can only work when all data in data_buffer
* is in TLV format; however, this is not always the case for all gateway types.
* Therefore, the above ipc4_find_dma_config() is still used as it can skip non-TLV
* blob data at the beginning of data_buffer.
*/
int ipc4_find_dma_config_tlv(struct ipc_config_dai *dai, uint8_t *data_buffer, size_t size)
{
uint8_t *end_addr = data_buffer + size;
struct sof_tlv *tlvs;
struct ipc_dma_config *dma_cfg;
int count = 0;

for (tlvs = (struct sof_tlv *)data_buffer; tlvs && (uint8_t *)tlvs < end_addr;
tlvs = tlv_next(tlvs)) {
dma_cfg = tlv_value_ptr_get(tlvs, GTW_DMA_CONFIG_ID);
if (!dma_cfg)
continue;

if (count >= GTW_DMA_DEVICE_MAX_COUNT) {
tr_err(&ipc_tr, "Unexpected DMA config count %d, max %d",
count, GTW_DMA_DEVICE_MAX_COUNT);
return IPC4_INVALID_REQUEST;
}

dai->host_dma_config[count++] = dma_cfg;
}

if (count == 0) {
tr_err(&ipc_tr, "No DMA config found");
return IPC4_INVALID_REQUEST;
}

return IPC4_SUCCESS;
}

int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer,
uint32_t size, uint32_t device_id, int dma_cfg_idx)
{
Expand Down
Loading