diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 91ba9aef3a01..db106efbaa8b 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -95,6 +95,11 @@ if(NOT CONFIG_LIBRARY) if(CONFIG_COMP_RTNR) add_subdirectory(rtnr) endif() + if(CONFIG_COMP_BASEFW_IPC4) + add_local_sources(sof + base_fw.c + ) + endif() subdirs(pipeline) diff --git a/src/audio/Kconfig b/src/audio/Kconfig index 088f6c107c44..ebc703ca6893 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -2,6 +2,12 @@ menu "Audio components" +config COMP_BASEFW_IPC4 + bool "BASEFW component" + default y + depends on IPC_MAJOR_4 + help + Select for BASEFW component config COMP_COPIER bool "COPIER component" default y diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c new file mode 100644 index 000000000000..7d6c5901ec68 --- /dev/null +++ b/src/audio/base_fw.c @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: BSD-3-Clause +// + +#include +#include +#include +#include +#include +#include + +/* 0e398c32-5ade-ba4b-93b1-c50432280ee4 */ +DECLARE_SOF_RT_UUID("basefw", basefw_comp_uuid, 0xe398c32, 0x5ade, 0xba4b, + 0x93, 0xb1, 0xc5, 0x04, 0x32, 0x28, 0x0e, 0xe4); +DECLARE_TR_CTX(basefw_comp_tr, SOF_UUID(basefw_comp_uuid), LOG_LEVEL_INFO); + +static inline void set_tuple(struct ipc4_tuple *tuple, uint32_t type, uint32_t length, void *data) +{ + tuple->type = type; + tuple->length = length; + memcpy_s(tuple->data, length, data, length); +} + +static inline void set_tuple_uint32(struct ipc4_tuple *tuple, uint32_t type, uint32_t value) +{ + tuple->type = type; + tuple->length = sizeof(uint32_t); + memcpy_s(tuple->data, tuple->length, &value, tuple->length); +} + +/* tuple is a variable length struct and the length of + * the last variable field is saved in tuple->length. + */ +static inline struct ipc4_tuple *next_tuple(struct ipc4_tuple *tuple) +{ + return (struct ipc4_tuple *)((char *)(tuple) + sizeof(*tuple) + tuple->length); +} + +static int basefw_config(uint32_t *data_offset, char *data) +{ + uint32_t version[4] = {SOF_MAJOR, SOF_MINOR, SOF_MICRO, SOF_BUILD}; + struct ipc4_tuple *tuple = (struct ipc4_tuple *)data; + struct ipc4_scheduler_config sche_cfg; + + set_tuple(tuple, IPC4_FW_VERSION_FW_CFG, sizeof(version), version); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MEMORY_RECLAIMED_FW_CFG, 1); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_FAST_CLOCK_FREQ_HZ_FW_CFG, CLK_MAX_CPU_HZ); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, clock_get_freq(CPU_LPRO_FREQ_IDX)); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_UAOL_SUPPORT, 0); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_DL_MAILBOX_BYTES_FW_CFG, MAILBOX_HOSTBOX_SIZE); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_UL_MAILBOX_BYTES_FW_CFG, MAILBOX_DSPBOX_SIZE); + + /* TODO: add log support */ + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_TRACE_LOG_BYTES_FW_CFG, 0); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_PPL_CNT_FW_CFG, IPC4_MAX_PPL_COUNT); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_ASTATE_COUNT_FW_CFG, IPC4_MAX_CLK_STATES); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_MODULE_PIN_COUNT_FW_CFG, IPC4_MAX_SRC_QUEUE); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_MOD_INST_COUNT_FW_CFG, IPC4_MAX_MODULE_INSTANCES); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_LL_TASKS_PER_PRI_COUNT_FW_CFG, + IPC4_MAX_LL_TASKS_PER_PRI_COUNT); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_LL_PRI_COUNT, SOF_IPC4_MAX_PIPELINE_PRIORITY + 1); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_DP_TASKS_COUNT_FW_CFG, IPC4_MAX_DP_TASKS_COUNT); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MODULES_COUNT_FW_CFG, 5); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MAX_LIBS_COUNT_FW_CFG, IPC4_MAX_LIBS_COUNT); + + tuple = next_tuple(tuple); + sche_cfg.sys_tick_cfg_length = 0; + sche_cfg.sys_tick_divider = 1; + sche_cfg.sys_tick_multiplier = 1; + sche_cfg.sys_tick_source = SOF_SCHEDULE_LL_TIMER; + set_tuple(tuple, IPC4_SCHEDULER_CONFIGURATION, sizeof(sche_cfg), &sche_cfg); + + tuple = next_tuple(tuple); + *data_offset = (int)((char *)tuple - data); + + return 0; +} + +static int basefw_hw_config(uint32_t *data_offset, char *data) +{ + struct ipc4_tuple *tuple = (struct ipc4_tuple *)data; + uint32_t value; + + set_tuple_uint32(tuple, IPC4_CAVS_VER_HW_CFG, CAVS_VERSION); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_DSP_CORES_HW_CFG, MAX_CORE_COUNT); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_MEM_PAGE_BYTES_HW_CFG, HOST_PAGE_SIZE); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_EBB_SIZE_BYTES_HW_CFG, SRAM_BANK_SIZE); + + tuple = next_tuple(tuple); + value = DIV_ROUND_UP(EBB_BANKS_IN_SEGMENT * SRAM_BANK_SIZE, HOST_PAGE_SIZE); + set_tuple_uint32(tuple, IPC4_TOTAL_PHYS_MEM_PAGES_HW_CFG, value); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_HP_EBB_COUNT_HW_CFG, PLATFORM_HPSRAM_EBB_COUNT); + + tuple = next_tuple(tuple); + /* 2 DMIC dais */ + value = DAI_NUM_SSP_BASE + DAI_NUM_HDA_IN + DAI_NUM_HDA_OUT + + DAI_NUM_ALH_BI_DIR_LINKS + 2; + set_tuple_uint32(tuple, IPC4_GATEWAY_COUNT_HW_CFG, value); + + tuple = next_tuple(tuple); + set_tuple_uint32(tuple, IPC4_LP_EBB_COUNT_HW_CFG, PLATFORM_LPSRAM_EBB_COUNT); + + tuple = next_tuple(tuple); + *data_offset = (int)((char *)tuple - data); + + return 0; +} + +/* There are two types of sram memory : high power mode sram and + * low power mode sram. This function retures memory size in page + * , memory bank power and usage status of each sram to host driver + */ +static int basefw_mem_state_info(uint32_t *data_offset, char *data) +{ + struct ipc4_tuple *tuple = (struct ipc4_tuple *)data; + struct ipc4_sram_state_info info; + uint32_t *tuple_data; + uint32_t index; + uint32_t size; + uint16_t *ptr; + int i; + + /* set hpsram */ + info.free_phys_mem_pages = SRAM_BANK_SIZE * PLATFORM_HPSRAM_EBB_COUNT / HOST_PAGE_SIZE; + info.ebb_state_dword_count = DIV_ROUND_UP(PLATFORM_HPSRAM_EBB_COUNT, 32); + info.page_alloc_struct.page_alloc_count = PLATFORM_HPSRAM_EBB_COUNT; + size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + + info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); + size = ALIGN(size, 4); + /* size is also saved as tuple length */ + tuple_data = rballoc(0, SOF_MEM_CAPS_RAM, size); + + /* save memory info in data array since info length is variable */ + index = 0; + tuple_data[index++] = info.free_phys_mem_pages; + tuple_data[index++] = info.ebb_state_dword_count; + for (i = 0; i < info.ebb_state_dword_count; i++) + tuple_data[index + i] = io_reg_read(SHIM_HSPGCTL(i)); + index += info.ebb_state_dword_count; + + tuple_data[index++] = info.page_alloc_struct.page_alloc_count; + /* TLB is not supported now, so all pages are marked as occupied + * TODO: add page-size allocator and TLB support + */ + ptr = (uint16_t *)(tuple_data + index); + for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) + ptr[i] = 0xfff; + + set_tuple(tuple, IPC4_HPSRAM_STATE, size, tuple_data); + + /* set lpsram */ + info.free_phys_mem_pages = 0; + info.ebb_state_dword_count = DIV_ROUND_UP(PLATFORM_LPSRAM_EBB_COUNT, 32); + info.page_alloc_struct.page_alloc_count = PLATFORM_LPSRAM_EBB_COUNT; + size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + + info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); + size = ALIGN(size, 4); + + index = 0; + tuple_data[index++] = info.free_phys_mem_pages; + tuple_data[index++] = info.ebb_state_dword_count; + tuple_data[index++] = io_reg_read(LSPGCTL); + tuple_data[index++] = info.page_alloc_struct.page_alloc_count; + ptr = (uint16_t *)(tuple_data + index); + for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) + ptr[i] = 0xfff; + + tuple = next_tuple(tuple); + set_tuple(tuple, IPC4_LPSRAM_STATE, size, tuple_data); + + /* calculate total tuple size */ + tuple = next_tuple(tuple); + *data_offset = (int)((char *)tuple - data); + + rfree(tuple_data); + return 0; +} + +static int basefw_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data) +{ + switch (param_id) { + case IPC4_PERF_MEASUREMENTS_STATE: + case IPC4_GLOBAL_PERF_DATA: + break; + default: + if (!first_block) + return -EINVAL; + } + + switch (param_id) { + case IPC4_FW_CONFIG: + return basefw_config(data_offset, data); + case IPC4_HW_CONFIG_GET: + return basefw_hw_config(data_offset, data); + case IPC4_MEMORY_STATE_INFO_GET: + return basefw_mem_state_info(data_offset, data); + /* TODO: add more support */ + case IPC4_DSP_PROPERTIES: + case IPC4_DSP_RESOURCE_STATE: + case IPC4_NOTIFICATION_MASK: + case IPC4_MODULES_INFO_GET: + case IPC4_PIPELINE_LIST_INFO_GET: + case IPC4_PIPELINE_PROPS_GET: + case IPC4_SCHEDULERS_INFO_GET: + case IPC4_GATEWAYS_INFO_GET: + case IPC4_POWER_STATE_INFO_GET: + case IPC4_LIBRARIES_INFO_GET: + case IPC4_PERF_MEASUREMENTS_STATE: + case IPC4_GLOBAL_PERF_DATA: + COMPILER_FALLTHROUGH; + default: + break; + } + + return -EINVAL; +}; + +static int basefw_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + char *data) +{ + return 0; +}; + +static const struct comp_driver comp_basefw = { + .uid = SOF_RT_UUID(basefw_comp_uuid), + .tctx = &basefw_comp_tr, + .ops = { + .get_large_config = basefw_get_large_config, + .set_large_config = basefw_set_large_config, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_basefw_info = { + .drv = &comp_basefw, +}; + +UT_STATIC void sys_comp_basefw_init(void) +{ + comp_register(platform_shared_get(&comp_basefw_info, + sizeof(comp_basefw_info))); +} + +DECLARE_MODULE(sys_comp_basefw_init); diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h new file mode 100644 index 000000000000..9fb859566b93 --- /dev/null +++ b/src/include/ipc4/base_fw.h @@ -0,0 +1,659 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/base_fw.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +/* Three clk src states :low power XTAL, low power ring + * and high power ring oscillator + */ +#define IPC4_MAX_CLK_STATES 3 + +/* Max src queue count count supported by ipc4 */ +#define IPC4_MAX_SRC_QUEUE 8 + +/* Max module instance for single module count supported by ipc4 */ +#define IPC4_MAX_MODULE_INSTANCES 256 + +/* Max ll tasks for a schedule priority count supported by ipc4 */ +#define IPC4_MAX_LL_TASKS_PER_PRI_COUNT 16 + +/* Max dp tasks count supported by ipc4 */ +#define IPC4_MAX_DP_TASKS_COUNT 16 + +/* Max external libraries count supported by ipc4 */ +#define IPC4_MAX_LIBS_COUNT 16 + +/* Max pipeline count supported by ipc4 */ +#define IPC4_MAX_PPL_COUNT 16 + +enum ipc4_basefw_properties { + IPC4_FW_VERSION, /**< Firmware version */ + IPC4_DSP_CORES, /**< dsp cores count in audio subsystem */ + IPC4_MEM_PAGE_SIZE, /**< memory page size */ + IPC4_TOTAL_PHYS_MEM_PAGES, /**< total memory in page size */ + IPC4_DL_MAILBOX_SIZE, /**< download mailbox size */ + IPC4_UL_MAILBOX_SIZE, /**< uplaod mailbox size */ + IPC4_TRACE_LOG_SIZE, /**< trace log buffer size */ + IPC4_MAX_PPL_CNT /**< max pipleine count */ +}; + +enum ipc4_basefw_params { + /* Use LARGE_CONFIG_GET to retrieve fw properties as TLV structure + * with typeof AdspProperties. + */ + IPC4_DSP_PROPERTIES = 0, + + IPC4_DSP_RESOURCE_STATE = 1, + + /* Use LARGE_CONFIG_SET to prepare core(s) for new DX state. + * Ipc mailbox must contain properly built DxStateInfo struct + */ + IPC4_DX_STATE = 2, + + /* Driver sends this request to enable/disable notifications. This message + * should be used by the driver in debug mode to avoid flooding host with + * underrun notifications when driver is stopped by breakpoint for example. + */ + IPC4_NOTIFICATION_MASK = 3, + + /* Driver sends A-State Table data right after the Base FW is up and ready to + * handle IPC communication. The table is forwarded to the Power Manager to + * configure available power states according to the underlying platform. + */ + IPC4_ASTATE_TABLE = 4, + + /* Driver sends the DMA Control parameter in order to initialize or modify + * DMA gateway configuration outside of a stream lifetime. Typically a DMA + * gateway is initialized during pipeline creation when a Copier module is + * instantiated and attached to that gateway. Similarly the gateway is + * de-initialized when the Copiers parent pipeline is being destroyed. + * However sometimes the driver may want to control the gateway before or + * after a stream is being attached to it. + * + * The data of DMA Control parameter starts with DmaControl structure + * optionally followed by the target gateway specific data (that may consist + * of two parts, the former coming from NHLT BIOS tables and the latter + * aux_config in form of TLV list provided by the driver). + */ + IPC4_DMA_CONTROL = 5, + + /* Driver sets this parameter to control state of FW logging. Driver may + * enable logging for each core and specify logging level. Driver also + * configures period of aging and FIFO full timers. Aging timer period + * specifies how frequently FW sends Log Buffer Status notification for new + * entries in case the usual notification sending criteria are not met + * (half of the buffer is full). Fifo full timer period specifies the latency + * of logging "dropped log entries" information after the content is consumed + * by the driver but no new log entry appears (which would trigger logging + * "dropped entries" as well). + * + * SystemTime property must be provided by the driver prior to enabling + *the logs for the first time, otherwise error is raised by FW since + * it will not be able to translate log event timestamps into the host + * CPU clock domain. + * + * Log FIFO content is reset on logs enabled by the driver, so the RP + * is expected to be 0, however the driver should not assume that value + * but just read the RP from FW Registers instead. + */ + IPC4_ENABLE_LOGS = 6, + + /* Use LARGE_CONFIG_SET/LARGE_CONFIG_GET to write/read FW configuration. + * + * Driver requests value of this Base FW property to discover FW configuration. + * Configuration data is returned in form of TLV list and contains items as + * defined in the next table. + * + * Driver may also set values of parameters that are marked as RW in the table. + * FirmwareConfig is expected to be queried/set once at the FW + * initialization time. Properties that are expected to be changed more + * frequently (e.g. current number of modules descriptors loaded or + * performance measurements state) are moved and became separate + * parameters. + */ + IPC4_FW_CONFIG = 7, + + /* Use LARGE_CONFIG_GET to read HW configuration. + * + * Driver requests value of this Base FW property to discover underlying HW + * configuration. Configuration data is returned in form of TLV list. + */ + IPC4_HW_CONFIG_GET = 8, + + /* Use LARGE_CONFIG_GET to read modules configuration. + * + * Driver requests value of this Base FW property to retrieve list of the + * module entries loaded into the FW memory space (as part of either the + * image manifest or library manifest). + * + * The response may be too large to fit into a single message. The driver + * must be prepared to handle multiple fragments. + */ + IPC4_MODULES_INFO_GET = 9, + + /* Use LARGE_CONFIG_GET to read pipeline list. + * + * Driver requests value of this Base FW property to retrieve list of + * pipelines IDs. Once the list is received driver may retrieve properties of + * each pipeline by querying Pipeline Info specifying IDs from the list. + */ + IPC4_PIPELINE_LIST_INFO_GET = 10, + + /* Use LARGE_CONFIG_GET to read pipelines properties. + * + * Driver requests value of this Base FW property to retrieve properties of a + * pipeline. Full parameter id wrapped by APPLICATION_PARAM into the request + * payload is of ExtendedParameterId type where parameter_type is set to + * PIPELINE_PROPS and parameter_instance is set to the target pipeline id. + * + * Properties of a single pipeline are expected to fit into a single IPC + * response as there is a room for ~1K of IDs of tasks and modules instances. + */ + IPC4_PIPELINE_PROPS_GET = 11, + + /* Use SCHEDULERS_INFO_GET to read schedulers configuration. + * + * Driver requests value of this Base FW property to retrieve list of task + * schedulers and tasks created inside the FW and being executed on a core. + * Full parameter id wrapped by APPLICATION_PARAM into the request payload + * is of ExtendedParameterId type where parameter_type is set to + * SCHEDULERS_INFO and parameter_instance is set to the target core id. + */ + IPC4_SCHEDULERS_INFO_GET = 12, + + /* Use LARGE_CONFIG_GET to read gateway configuration */ + IPC4_GATEWAYS_INFO_GET = 13, + + /* Use LARGE_CONFIG_GET to get information on memory state. + * + * Driver requests value of this Base FW property to retrieve information + * about current DSP memory state. Configuration data is returned in form of + * TLV list and contains items as defined in the next table. + */ + IPC4_MEMORY_STATE_INFO_GET = 14, + + /* Use LARGE_CONFIG_GET to get information on power state. + * + * Driver requests value of this Base FW property to retrieve information + * about current DSP power state. Configuration data is returned in form of + * TLV list and contains items as defined in the next table. + */ + IPC4_POWER_STATE_INFO_GET = 15, + + /* Use LARGE_CONFIG_GET to get information about libraries + * loaded into the ADSP memory. + */ + IPC4_LIBRARIES_INFO_GET = 16, + + /* Use LARGE_CONFIG_SET to set value of this Base FW property to control + * performance measurements state. There is one global flag that controls the + * state of performance measurements process globally. + * + * Driver may set value of this Base FW property to control state of + * performance measurements process in the DSP FW. + * + * This state is applied to MCPS monitoring only. Memory allocation + * state is always available. + */ + IPC4_PERF_MEASUREMENTS_STATE = 17, + + /* Use LARGE_CONFIG_GET to retrieve retrieve global performance data. FW + * sends a list of captured performance data per enabled core and power mode. + * MCPS are sampled each DSP system tick (1ms in D0) and used to compute peak + * and average values. + * + * Driver requests value of this Base FW property to retrieve performance data + * captured on the DSP. FW sends a list of items reported by FW components. + * KCPS are sampled either each DSP system tick (1ms in D0) for low latency + * and infrastructure components, or each processed frame otherwise. The KCPS + * are used to compute reported peak and average values by FW. + * + * Data items reported for resource_id = {module_id = 0, instance_id = + * core_id} contain total KCPS spent on each active core. + * + *This parameter reports only KCPS, while the memory state is reported + * by Memory State Info parameter. + */ + IPC4_GLOBAL_PERF_DATA = 18, + + /* Use LARGE_CONFIG_GET to get information on l2 cache state. + * + * Driver requests value of this Base FW property to retrieve information + * about current state of L2 Cache. Available on platforms where L2 cache is + * in use, otherwise ADSP_IPC_UNAVAILABLE is returned. + */ + IPC4_L2_CACHE_INFO_GET = 19, + + /* Driver sets this property to pass down information about host system time. + * + * Driver sets this property to pass down information about current system + * time. It is used by FW to translate event timestamps (Logs, Probes packets + * for example) to the system time (current host time) domain. + * + * The value of system time is expressed in us + * Time is in UTC + * Epoch is 1601-01-01T00:00:00Z + */ + IPC4_SYSTEM_TIME = 20, + + /* Use LARGE_CONFIG_SET to configure firmware for performance */ + IPC4_PERFORMANCE_CONFIGURATION = 21, + + /* Use LARGE_CONFIG_SET to register KCPS into power manager + * service per core 0. Negative numbers are allowed. + */ + IPC4_REGISTER_KCPS = 22, + + /* Use LARGE_CONFIG_SET to request additional resource allocation */ + IPC4_RESOURCE_ALLOCATION_REQUEST = 23, + + /* Driver may set value of this Base FW property to control state of + * I/o performance measurements process in the DSP FW. + */ + IPC4_IO_PERF_MEASUREMENTS_STATE = 24, + + /* The command returns I/O statistics when they are enabled */ + IPC4_IO_GLOBAL_PERF_DATA = 25, + + /* The command is shorter version of Modules Info command. + * It is used to retrieve module ID for a specified module UUID. + */ + IPC4_GET_MODULE_ID = 26, + + /* EXTENDED_SYSTEM_TIME command returns current value of UTC, RTC and HH. + * The system time must be set first via SYSTEM_TIME command before + * EXTENDED_SYSTEM_TIME can be used. + */ + IPC4_EXTENDED_SYSTEM_TIME = 27, + + /* Driver may set value of this Base FW property to control state + * of telemetry collection process in the DSP FW. + * In started state, TELEMETRY_STATE command is used to change threshold + * and aging timer depend on system state. + */ + IPC4_TELEMETRY_STATE = 28, + + /* The command to read data from the telemetry circular buffer. + * The telemetry data can be produced by firmware modules using + * System Service APIand then all telemetry is collected via one + * common mechanism provided by the base firmware. + */ + IPC4_TELEMETRY_DATA = 29, + + /* This command is extended version of Global Performance Data which + * provides more details information about total number of + * cycles consumed by each of the modules. + */ + IPC4_EXTENDED_GLOBAL_PERF_DATA = 30, + + /* Use LARGE_CONFIG_SET to change SDW ownership */ + IPC4_SDW_OWNERSHIP = 31, +}; + +enum ipc4_fw_config_params { + /* Firmware version */ + IPC4_FW_VERSION_FW_CFG = 0, + /* Indicates whether legacy DMA memory is managed by FW */ + IPC4_MEMORY_RECLAIMED_FW_CFG = 1, + /* Frequency of oscillator clock */ + IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG = 2, + /* Frequency of PLL clock */ + IPC4_FAST_CLOCK_FREQ_HZ_FW_CFG = 3, + /* List of static and dynamic DMA buffer sizes. + * SW may configure minimum and maximum size for each buffer. + */ + IPC4_DMA_BUFFER_CONFIG_FW_CFG = 4, + /* Audio Hub Link support level. + * Note: Lower 16-bits may be used in future to indicate + * implementation revision if necessary. + */ + IPC4_ALH_SUPPORT_LEVEL_FW_CFG = 5, + /* Size of IPC downlink mailbox */ + IPC4_DL_MAILBOX_BYTES_FW_CFG = 6, + /* Size of IPC uplink mailbox */ + IPC4_UL_MAILBOX_BYTES_FW_CFG = 7, + /* Size of trace log buffer */ + IPC4_TRACE_LOG_BYTES_FW_CFG = 8, + /* Maximum number of pipelines that may be instantiated at the same time */ + IPC4_MAX_PPL_CNT_FW_CFG = 9, + /* Maximum number of A-state table entries that may be configured by the driver. + * Driver may also use this value to estimate the size of data retrieved as + * ASTATE_TABLE property. + */ + IPC4_MAX_ASTATE_COUNT_FW_CFG = 10, + /* Maximum number of input or output pins supported by a module */ + IPC4_MAX_MODULE_PIN_COUNT_FW_CFG = 11, + /* Current total number of module entries loaded into the DSP */ + IPC4_MODULES_COUNT_FW_CFG = 12, + /* Maximum number of module instances supported by FW */ + IPC4_MAX_MOD_INST_COUNT_FW_CFG = 13, + /* Maximum number of LL tasks that may be allocated with + * the same priority (specified by a priority of the parent pipeline). + */ + IPC4_MAX_LL_TASKS_PER_PRI_COUNT_FW_CFG = 14, + /* Number of LL priorities */ + IPC4_LL_PRI_COUNT = 15, + /* Maximum number of DP tasks that may be allocated on a single core */ + IPC4_MAX_DP_TASKS_COUNT_FW_CFG = 16, + /* Maximum number of libraries that can be loaded into the ADSP memory */ + IPC4_MAX_LIBS_COUNT_FW_CFG = 17, + /* Configuration of system tick source and period */ + IPC4_SCHEDULER_CONFIGURATION = 18, + /* Frequency of xtal oscillator clock */ + IPC4_XTAL_FREQ_HZ_FW_CFG = 19, + /* Configuration of clocks */ + IPC4_CLOCKS_CONFIGURATION = 20, + /* USB Audio Offload support */ + IPC4_UAOL_SUPPORT = 21, + /* Configuration of Dynamic Power Gating Policy */ + IPC4_POWER_GATING_POLICY = 22, + /* Configuration of assert mode + * Run-time asserts requires special handling by decoder. + * Asserts will be in format: "%passert", ptr_to_assert_desc. + * + * ptr_to_assert_desc will point to place in .asserts_desc section in ELF. + * Data must be cased to struct: struct assert_entry + */ + IPC4_ASSERT_MODE = 23, + /* Size of telemetry buffer in bytes. The default size is 4KB */ + IPC4_TELEMETRY_BUFFER_SIZE = 24, + /* HW version information */ + IPC4_BUS_HARDWARE_ID = 25, + /* 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, +}; + +enum ipc4_hw_config_params { + /* Version of cAVS implemented by FW (from ROMInfo) */ + IPC4_CAVS_VER_HW_CFG = 0, + /* How many dsp cores are available in current audio subsystem */ + IPC4_DSP_CORES_HW_CFG = 1, + /* Size of a single memory page */ + IPC4_MEM_PAGE_BYTES_HW_CFG = 2, + /* Total number of physical pages available for allocation */ + IPC4_TOTAL_PHYS_MEM_PAGES_HW_CFG = 3, + /* + * Number of items in controller_base_addr array is specified by + * controller_count. note Lower 16 bits of I2sVersion may be used + * in future to indicate implementation revision if necessary. + */ + IPC4_I2S_CAPS_HW_CFG = 4, + /* GPDMA capabilities */ + IPC4_GPDMA_CAPS_HW_CFG = 5, + /*Total number of DMA gateways of all types */ + IPC4_GATEWAY_COUNT_HW_CFG = 6, + /* Number of HP SRAM memory banks manageable by DSP */ + IPC4_HP_EBB_COUNT_HW_CFG = 7, + /* Number of LP SRAM memory banks manageable by DSP */ + IPC4_LP_EBB_COUNT_HW_CFG = 8, + /* Size of a single memory bank (EBB) in bytes */ + IPC4_EBB_SIZE_BYTES_HW_CFG = 9, + /* UAOL capabilities */ + IPC4_UAOL_CAPS_HW_CFG = 10 +}; + +struct ipc4_tuple { + uint32_t type; + uint32_t length; + char data[0]; +} __attribute__((packed, aligned(4))); + +enum ipc4_memory_type { + /* High power sram memory */ + IPC4_HP_SRAM_MEMORY = 0, + /*Low power sram memory */ + IPC4_LP_SRAM_MEMORY = 1 +}; + +enum ipc4_resource_state_request { + /* + * This type is used to inform about free physical HP sram memory pages + * available. + */ + IPC4_FREE_PHYS_MEM_PAGES = 0 +}; + +/* PhysMemPages describes current free phys memory pages */ +struct ipc4_phys_mem_pages { + uint32_t mem_type; + /* Number of pages */ + uint32_t pages; +} __attribute__((packed, aligned(4))); + +/*TODO: how do we enter D0i3 */ +enum ipc4_dx_states { + /*D0 state means that dsp in this state is powered up and ready for processing */ + IPC4_D0_STATE = 0, + /* D3 state means that dsp in this state is powered down or not yet + * ready for processing. No idc/ipc should be send to core in this state. + */ + IPC4_D3_STATE = 3, +}; + +struct ipc4_dx_state_info { + /* Indicates which cores are subject to change the power state */ + uint32_t core_mask; + /* Indicates core state. + * bit[core_id] = 0 -> put core_id to D3 + * bit[core_id] = 1 -> put core_id to D0 + */ + uint32_t dx_mask; +} __attribute__((packed, aligned(4))); + +#define IPC4_UNDERRUN_AT_GATEWAY_NOTIFICATION_MASK_IDX 0 +#define IPC4_UNDERRUN_AT_MIXER_NOTIFICATION_MASK_IDX 1 +#define IPC4_BUDGET_VIOLATION_NOTIFICATION_MASK_IDX 2 +#define IPC4_OVERRUN_AT_GATEWAY_NOTIFICATION_MASK_IDX 3 + +struct ipc4_notification_mask_info { + /* Indicates which notifications are begin enabled/disabled */ + uint32_t ntfy_mask; + /* Indicates if notifications indicated by corresponding bits in ntfy_mask + * are enabled (b'1) or disabled (b'0). + */ + uint32_t enabled_mask; +} __attribute__((packed, aligned(4))); + +enum ipc4_clock_src { + /* Low Power XTAL (oscillator) clock source */ + IPC4_CLOCK_SRC_XTAL = 0, + + /* Low Power Ring Oscillator */ + IPC4_CLOCK_SRC_LP_RING_OSC, + /* High Power Ring Oscillator */ + IPC4_CLOCK_SRC_HP_RING_OSC, + /* Low Power XTAL (oscillator) clock source + * Frequency depends on platform. This XTAL is different from CLOCK_SRC_XTAL + * because it is generate in IP (not given from platform), saving more power. + */ + IPC4_CLOCK_SRC_WOV_XTAL, + IPC4_CLOCK_SRC_INVALID, + IPC4_CLOCK_SRC_MAX_IDX = IPC4_CLOCK_SRC_INVALID - 1, +}; + +struct ipc4_astate { + /* Kilo Cycles Per Second. + * Specifies core load threshold (expressed in kilo cycles per second). When + * load is below this threshold DSP is clocked from source specified by clk_src. + * + * Configuring 0 kcps in the first entry means that this clock source will be + * used in idle state only. + */ + uint32_t kcps; + /* Clock source associated with kcps threshold */ + enum ipc4_clock_src clock_src; +} __attribute__((packed, aligned(4))); + +/* Power Manager Astate Table */ +struct ipc4_astate_table { + /* Number of entries in astates_ array. The value does not exceed maximum + * number specified by MAX_ASTATE_COUNT member of Base FWs + * FIRMWARE_CONFIG parameter. + */ + uint32_t astates_count_; + /* Array of states. */ + struct ipc4_astate astates_[3]; +} __attribute__((packed, aligned(4))); + +/* All members have the same meaning as in the CopierGatewayCfg structure + * (except for the dma_buffer_size that is not used here). + */ +struct ipc4_dma_control { + uint32_t node_id; + uint32_t config_length; + uint32_t config_data[1]; +} __attribute__((packed, aligned(4))); + +enum ipc4_perf_measurements_state_set { + IPC4_PERF_MEASUREMENTS_DISABLED = 0, + IPC4_PERF_MEASUREMENTS_STOPPED = 1, + IPC4_PERF_MEASUREMENTS_STARTED = 2, + IPC4_PERF_MEASUREMENTS_PAUSED = 3, +}; + +struct ipc4_perf_data_item { + /*ID of the core running the load being reported */ + uint32_t resource_id; + /* + * 0 - D0, + * 1 - D0i3, + */ + uint32_t power_mode : 1; + uint32_t rsvd : 30; + uint32_t is_removed : 1; + /* Peak KCPS (Kilo Cycles Per Second) captured */ + uint32_t peak_kcps; + /* Average KCPS (Kilo Cycles Per Second) measured */ + uint32_t avg_kcps; +} __attribute__((packed, aligned(4))); + +/* + * PerfDataItem with additional fields required by module + * instance to properly calculate its performance data. + * NOTE: Only PerfDataItem is part of GlobalPerfData. + */ +struct ipc4_perf_data_item_mi { + struct ipc4_perf_data_item item; + /* Total iteration count of module instance */ + uint32_t total_iteration_count; + /* Total cycles consumed by module instance */ + uint64_t total_cycles_consumed; +} __attribute__((packed, aligned(4))); + +struct ipc4_global_perf_data { + /* Specifies number of items in perf_items array */ + uint32_t perf_item_count; + /* Array of global performance measurements */ + struct ipc4_perf_data_item perf_items[1]; +} __attribute__((packed, aligned(4))); + +enum ipc4_low_latency_interrupt_source { + IPC4_LOW_POWER_TIMER_INTERRUPT_SOURCE = 1, + IPC4_DMA_GATEWAY_INTERRUPT_SOURCE = 2 +}; + +struct ipc4_scheduler_config { + uint32_t sys_tick_multiplier; + uint32_t sys_tick_divider; + uint32_t sys_tick_source; + uint32_t sys_tick_cfg_length; + uint32_t sys_tick_cfg[1]; +} __attribute__((packed, aligned(4))); + +struct ipc4_system_time { + /* Lower DWORD of current system time value */ + uint32_t val_l; + /* Upper DWORD of current system time value */ + uint32_t val_u; +} __attribute__((packed, aligned(4))); + +struct ipc4_system_time_info { + struct ipc4_system_time host_time; + struct ipc4_system_time dsp_time; +} __attribute__((packed, aligned(4))); + +enum ipc4_pipeline_attributes { + /* Determines whether on pipeline will be allocated module(s) with ULP capability */ + IPC4_ULTRA_LOW_POWER = 0, + /* Determines whether on pipeline will be allocated + * module(s) that can report autonomous reset. + */ + IPC4_AUTONOMOUS_RESET = 1, +}; + +enum ipc4_resource_allocation_type { + /* Allocate KCPS */ + IPC4_RAT_DSP_KCPS = 0, + IPC4_RAT_MEMORY = 1, +}; + +struct ipc4_resource_kcps { + uint32_t core_id; + int32_t kcps; +} __attribute__((packed, aligned(4))); + +struct ipc4_resource_memory { + /* base address to allocate */ + uint32_t address; + /* size of allocate */ + uint32_t size; +} __attribute__((packed, aligned(4))); + +struct ipc4_resource_request { + /* Type of resource to allocate */ + uint32_t ra_type; + union { + /* Valid for ra_type == RAT_DSP_KCPS */ + struct ipc4_resource_kcps kcps; + /* Valid for ra_type == RAT_MEMORY */ + struct ipc4_resource_memory memory; + } ra_data; +} __attribute__((packed, aligned(4))); + +#define IPC4_LPSRAM_STATE 0 +#define IPC4_HPSRAM_STATE 1 + +struct ipc4_sram_state_page_alloc { + /* Number of items in page_alloc array */ + uint32_t page_alloc_count; + /* State of memory page allocation. + * bit[i] indicates whether i-th page is allocated. + */ + uint16_t page_alloc[1]; +} __attribute__((packed, aligned(4))); + +struct ipc4_sram_state_info { + /* Number of free memory pages */ + uint32_t free_phys_mem_pages; + /* Number of items in ebb_state array */ + uint32_t ebb_state_dword_count; + /* State of EBBs (memory banks) */ + /* bit[i] indicates whether i-th EBB is in use (1) or powered down (0) */ + uint32_t ebb_state[1]; + struct ipc4_sram_state_page_alloc page_alloc_struct; +} __attribute__((packed, aligned(4))); + +enum ipc4_alh_version { + IPC4_ALH_NO_SUPPORT, + IPC4_ALH_CAVS_1_8 = 0x10000, +}; diff --git a/src/include/ipc4/module.h b/src/include/ipc4/module.h index b0bfeaaeae39..3c72d257ca1d 100644 --- a/src/include/ipc4/module.h +++ b/src/include/ipc4/module.h @@ -209,6 +209,39 @@ struct ipc4_module_large_config { uint32_t instance_id : 8; /**< ModuleMsg::LARGE_CONFIG_GET / LARGE_CONFIG_SET */ uint32_t type : 5; + /**< Msg::MSG_REQUEST or Msg::MSG_REPLY */ + uint32_t rsp : 1; + /**< Msg::MODULE_MSG or Msg::FW_GEN_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } header; + + union { + uint32_t dat; + + struct { + /**< data size for single block, offset for multiple block case */ + uint32_t data_off_size : 20; + /**< param type : VENDOR_CONFIG_PARAM / GENERIC_CONFIG_PARAM */ + uint32_t large_param_id : 8; + /**< 1 if final block */ + uint32_t final_block : 1; + /**< 1 if init block */ + uint32_t init_block : 1; + uint32_t _reserved_2 : 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_large_config_reply { + union { + uint32_t dat; + + struct { + uint32_t status :IPC4_IXC_STATUS_BITS; + /**< ModuleMsg::LARGE_CONFIG_GET / LARGE_CONFIG_SET */ + uint32_t type : 5; /**< Msg::MSG_REQUEST */ uint32_t rsp : 1; /**< Msg::MODULE_MSG */ diff --git a/src/ipc/ipc4/CMakeLists.txt b/src/ipc/ipc4/CMakeLists.txt index 5cea199b3d06..7324c8cf4b30 100644 --- a/src/ipc/ipc4/CMakeLists.txt +++ b/src/ipc/ipc4/CMakeLists.txt @@ -5,3 +5,5 @@ add_local_sources(sof handler.c helper.c ) + +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/rimage/src/include) diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index 423e97dc4882..36e6d1769528 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -364,26 +364,108 @@ static int ipc4_unbind_module_instance(union ipc4_message_header *ipc4) return ipc_comp_disconnect(ipc, (ipc_pipe_comp_connect *)&bu); } +static int ipc4_get_large_config_module_instance(union ipc4_message_header *ipc4) +{ + struct ipc4_module_large_config_reply reply; + struct ipc4_module_large_config config; + char *data = ipc_get()->comp_data; + const struct comp_driver *drv; + struct comp_dev *dev = NULL; + uint32_t data_offset; + int ret; + + memcpy_s(&config, sizeof(config), ipc4, sizeof(config)); + tr_dbg(&ipc_tr, "ipc4_get_large_config_module_instance %x : %x with %x : %x", + (uint32_t)config.header.r.module_id, (uint32_t)config.header.r.instance_id); + + drv = ipc4_get_comp_drv(config.header.r.module_id); + if (!drv) + return IPC4_MOD_INVALID_ID; + + if (!drv->ops.get_large_config) + return IPC4_INVALID_REQUEST; + + /* get component dev for non-basefw since there is no + * component dev for basefw + */ + if (config.header.r.module_id) { + uint32_t comp_id; + + comp_id = IPC4_COMP_ID(config.header.r.module_id, config.header.r.instance_id); + dev = ipc4_get_comp_dev(comp_id); + if (!dev) + return IPC4_MOD_INVALID_ID; + } + + data_offset = config.data.r.data_off_size; + ret = drv->ops.get_large_config(dev, config.data.r.large_param_id, config.data.r.init_block, + config.data.r.final_block, &data_offset, + data + sizeof(reply.data.dat)); + + /* set up ipc4 error code for reply data */ + if (ret < 0) + ret = IPC4_MOD_INVALID_ID; + + /* Copy host config and overwrite */ + reply.data.dat = config.data.dat; + reply.data.r.data_off_size = data_offset; + + /* The last block, no more data */ + if (!config.data.r.final_block && data_offset < SOF_IPC_MSG_MAX_SIZE) + reply.data.r.final_block = 1; + + /* Indicate last block if error occurs */ + if (ret) + reply.data.r.final_block = 1; + + *(uint32_t *)data = reply.data.dat; + + /* no need to allocate memory for reply msg */ + if (ret) + return ret; + + msg_reply.tx_size = data_offset + sizeof(reply.data.dat); + msg_reply.tx_data = rballoc(0, SOF_MEM_CAPS_RAM, msg_reply.tx_size); + if (!msg_reply.tx_data) { + tr_err(&ipc_tr, "error: failed to allocate tx_data"); + ret = IPC4_OUT_OF_MEMORY; + } + + return ret; +} + static int ipc4_set_large_config_module_instance(union ipc4_message_header *ipc4) { struct ipc4_module_large_config config; - struct comp_dev *dev; - int comp_id; + struct comp_dev *dev = NULL; + const struct comp_driver *drv; int ret; memcpy_s(&config, sizeof(config), ipc4, sizeof(config)); tr_dbg(&ipc_tr, "ipc4_set_large_config_module_instance %x : %x with %x : %x", (uint32_t)config.header.r.module_id, (uint32_t)config.header.r.instance_id); - comp_id = IPC4_COMP_ID(config.header.r.module_id, config.header.r.instance_id); - dev = ipc4_get_comp_dev(comp_id); - if (!dev) + drv = ipc4_get_comp_drv(config.header.r.module_id); + if (!drv) return IPC4_MOD_INVALID_ID; - ret = comp_cmd(dev, config.data.r.large_param_id, (void *)MAILBOX_HOSTBOX_BASE, - config.data.dat); + if (!drv->ops.set_large_config) + return IPC4_INVALID_REQUEST; + + if (config.header.r.module_id) { + uint32_t comp_id; + + comp_id = IPC4_COMP_ID(config.header.r.module_id, config.header.r.instance_id); + dev = ipc4_get_comp_dev(comp_id); + if (!dev) + return IPC4_MOD_INVALID_ID; + } + + ret = drv->ops.set_large_config(dev, config.data.r.large_param_id, config.data.r.init_block, + config.data.r.final_block, config.data.r.data_off_size, + (char *)MAILBOX_HOSTBOX_BASE); if (ret < 0) { - tr_dbg(&ipc_tr, "failed to set large_config_module_instance %x : %x with %x : %x", + tr_err(&ipc_tr, "failed to set large_config_module_instance %x : %x with %x : %x", (uint32_t)config.header.r.module_id, (uint32_t)config.header.r.instance_id); ret = IPC4_INVALID_RESOURCE_ID; } @@ -428,7 +510,7 @@ static int ipc4_process_module_message(union ipc4_message_header *ipc4) case SOF_IPC4_MOD_CONFIG_GET: case SOF_IPC4_MOD_CONFIG_SET: case SOF_IPC4_MOD_LARGE_CONFIG_GET: - ret = IPC4_UNAVAILABLE; + ret = ipc4_get_large_config_module_instance(ipc4); break; case SOF_IPC4_MOD_LARGE_CONFIG_SET: ret = ipc4_set_large_config_module_instance(ipc4); @@ -484,6 +566,10 @@ ipc_cmd_hdr *ipc_prepare_to_send(struct ipc_msg *msg) if (msg->tx_size) mailbox_dspbox_write(0, (uint32_t *)msg->tx_data + 1, msg->tx_size); + /* free memory for get config function */ + if (msg_reply.tx_size) + rfree(msg_reply.tx_data); + return ipc_to_hdr(msg_data.msg_out); } @@ -497,7 +583,6 @@ void ipc_msg_reply(struct sof_ipc_reply *reply) { struct ipc4_message_reply reply_msg; struct ipc *ipc = ipc_get(); - uint32_t msg_reply_data; bool skip_first_entry; uint32_t flags; int error = 0; @@ -522,23 +607,21 @@ void ipc_msg_reply(struct sof_ipc_reply *reply) spin_unlock_irq(&ipc->lock, flags); if (!skip_first_entry) { - /* copy contents of message received */ + char *data = ipc_get()->comp_data; + + /* set error status */ reply_msg.header.dat = msg_reply.header; reply_msg.header.r.status = error; - reply_msg.data.dat = 0; - msg_reply_data = 0; - msg_reply.header = reply_msg.header.dat; - msg_reply.tx_data = &msg_reply_data; - msg_reply.tx_size = sizeof(msg_reply_data); - ipc_msg_send(&msg_reply, &reply_msg.data.dat, true); + ipc_msg_send(&msg_reply, data, true); } } void ipc_cmd(ipc_cmd_hdr *_hdr) { union ipc4_message_header *in = ipc_from_hdr(_hdr); + uint32_t *data = ipc_get()->comp_data; enum ipc4_message_target target; int err = -EINVAL; @@ -547,6 +630,15 @@ void ipc_cmd(ipc_cmd_hdr *_hdr) msg_data.delayed_reply = false; + /* Common reply msg only sends back ipc extension register */ + msg_reply.tx_size = sizeof(uint32_t); + /* msg_reply data is stored in msg_out[1] */ + msg_reply.tx_data = msg_data.msg_out + 1; + /* Ipc extension register is stored in in[1]. + * Save it for reply msg + */ + data[0] = in[1].dat; + target = in->r.msg_tgt; switch (target) { @@ -569,22 +661,14 @@ void ipc_cmd(ipc_cmd_hdr *_hdr) if (in->r.rsp == SOF_IPC4_MESSAGE_DIR_MSG_REQUEST) { struct ipc4_message_reply reply; struct sof_ipc_reply rep; - uint32_t msg_reply_data; /* copy contents of message received */ reply.header.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; - reply.header.r.status = err; reply.header.r.msg_tgt = in->r.msg_tgt; reply.header.r.type = in->r.type; - reply.data.dat = 0; - - msg_reply_data = 0; - msg_reply.header = reply.header.dat; - msg_reply.tx_data = &msg_reply_data; - msg_reply.tx_size = sizeof(msg_reply_data); - rep.error = err; + ipc_msg_reply(&rep); } } diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index a3cffd31e5b6..6afd3efe0507 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -365,11 +365,17 @@ const struct comp_driver *ipc4_get_drv(uint8_t *uuid) const struct comp_driver *ipc4_get_comp_drv(int module_id) { struct sof_man_fw_desc *desc = (struct sof_man_fw_desc *)IMR_BOOT_LDR_MANIFEST_BASE; - struct sof_man_module *mod; const struct comp_driver *drv; + struct sof_man_module *mod; + int entry_index; + + /* module_id 0 is used for base fw which is in entry 1 */ + if (!module_id) + entry_index = 1; + else + entry_index = module_id; - /* skip basefw of module 0 in manifest */ - mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(module_id)); + mod = (struct sof_man_module *)((char *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); drv = ipc4_get_drv(mod->uuid); return drv;