From 71b73631547a098e2170a5eb06530b0b5d95809b Mon Sep 17 00:00:00 2001 From: Piotr Makaruk Date: Wed, 23 Nov 2022 13:44:26 +0100 Subject: [PATCH 1/5] hda: chain management and logic implementation Hardware HDA chain require manager for controlling multiple streams tasks. Enable support with LL task and DMA mandatory logic. Signed-off-by: Piotr Makaruk --- src/audio/CMakeLists.txt | 3 + src/audio/Kconfig | 6 + src/audio/chain_dma.c | 655 ++++++++++++++++++++++++++++++++ src/include/ipc4/error_status.h | 3 + src/include/sof/ipc/topology.h | 2 + src/ipc/ipc4/helper.c | 54 +++ zephyr/CMakeLists.txt | 4 + zephyr/wrapper.c | 5 + 8 files changed, 732 insertions(+) create mode 100644 src/audio/chain_dma.c diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 2402b4d1bd59..980662edf6d5 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -107,6 +107,9 @@ if(NOT CONFIG_LIBRARY) endif() subdirs(pipeline) add_subdirectory(google) + if(CONFIG_COMP_CHAIN_DMA) + add_local_sources(sof chain_dma.c) + endif() return() endif() diff --git a/src/audio/Kconfig b/src/audio/Kconfig index ebadccfbfdd2..e832a3f8e6ef 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -27,6 +27,12 @@ config COMP_DAI_GROUP Select for grouping physical DAIs into a logical DAI that can be triggered atomically to synchronise stream start and stop operations. +config COMP_CHAIN_DMA + bool "Chain DMA component" + default n + help + Chain DMA support in hardware + config COMP_ARIA bool "ARIA component" default n diff --git a/src/audio/chain_dma.c b/src/audio/chain_dma.c new file mode 100644 index 000000000000..f815b7c6b4f0 --- /dev/null +++ b/src/audio/chain_dma.c @@ -0,0 +1,655 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Piotr Makaruk + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct comp_driver comp_chain_dma; +static const uint32_t max_chain_number = DAI_NUM_HDA_OUT + DAI_NUM_HDA_IN; + +LOG_MODULE_REGISTER(chain_dma, CONFIG_SOF_LOG_LEVEL); + +/* 6a0a274f-27cc-4afb-a3e7-3444723f432e */ +DECLARE_SOF_RT_UUID("chain_dma", chain_dma_uuid, 0x6a0a274f, 0x27cc, 0x4afb, + 0xa3, 0xe7, 0x34, 0x44, 0x72, 0x3f, 0x43, 0x2e); +DECLARE_TR_CTX(chain_dma_tr, SOF_UUID(chain_dma_uuid), LOG_LEVEL_INFO); + +/* chain dma component private data */ +struct chain_dma_data { + bool first_data_received; + /* node id of host HD/A DMA */ + union ipc4_connector_node_id host_connector_node_id; + /* node id of link HD/A DMA */ + union ipc4_connector_node_id link_connector_node_id; + uint32_t *hw_buffer; + struct task chain_task; + enum sof_ipc_stream_direction stream_direction; + /* container size in bytes */ + uint8_t cs; + + /* local host DMA config */ + struct dma *dma_host; + struct dma_chan_data *chan_host; + struct dma_config z_config_host; + struct dma_block_config dma_block_cfg_host; + + /* local link DMA config */ + struct dma *dma_link; + struct dma_chan_data *chan_link; + struct dma_config z_config_link; + struct dma_block_config dma_block_cfg_link; + + struct comp_buffer *dma_buffer; +}; + +static int chain_host_start(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_start(cd->chan_host->dma->z_dev, cd->chan_host->index); + if (err < 0) + return err; + + comp_info(dev, "chain_host_start(): dma_start() host chan_index = %u", + cd->chan_host->index); + return 0; +} + +static int chain_link_start(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_start(cd->chan_link->dma->z_dev, cd->chan_link->index); + if (err < 0) + return err; + + comp_info(dev, "chain_link_start(): dma_start() link chan_index = %u", + cd->chan_link->index); + return 0; +} + +static int chain_link_stop(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_stop(cd->chan_link->dma->z_dev, cd->chan_link->index); + if (err < 0) + return err; + + comp_info(dev, "chain_link_stop(): dma_stop() link chan_index = %u", + cd->chan_link->index); + + return 0; +} + +static int chain_host_stop(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_stop(cd->chan_host->dma->z_dev, cd->chan_host->index); + if (err < 0) + return err; + + comp_info(dev, "chain_host_stop(): dma_stop() host chan_index = %u", + cd->chan_host->index); + + return 0; +} + +static int chain_task_start(struct comp_dev *dev) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct chain_dma_data *cd = comp_get_drvdata(dev); + k_spinlock_key_t key; + int ret; + + comp_info(dev, "chain_task_start(), host_dma_id = 0x%08x", cd->host_connector_node_id.dw); + + key = k_spin_lock(&drivers->lock); + switch (cd->chain_task.state) { + case SOF_TASK_STATE_QUEUED: + k_spin_unlock(&drivers->lock, key); + return 0; + case SOF_TASK_STATE_COMPLETED: + break; + case SOF_TASK_STATE_INIT: + break; + default: + comp_err(dev, "chain_task_start(), bad state transition"); + ret = -EINVAL; + goto error; + } + + if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { + ret = chain_host_start(dev); + if (ret) + goto error; + ret = chain_link_start(dev); + if (ret) { + chain_host_stop(dev); + goto error; + } + } else { + ret = chain_link_start(dev); + if (ret) + goto error; + ret = chain_host_start(dev); + if (ret) { + chain_link_stop(dev); + goto error; + } + } + + pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + + ret = schedule_task(&cd->chain_task, 0, 0); + if (ret) { + chain_host_stop(dev); + chain_link_stop(dev); + goto error; + } + + cd->chain_task.state = SOF_TASK_STATE_INIT; + +error: + k_spin_unlock(&drivers->lock, key); + return ret; +} + +static int chain_task_pause(struct comp_dev *dev) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct chain_dma_data *cd = comp_get_drvdata(dev); + k_spinlock_key_t key; + int ret, ret2; + + if (cd->chain_task.state == SOF_TASK_STATE_FREE) + return 0; + + key = k_spin_lock(&drivers->lock); + cd->first_data_received = false; + if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { + ret = chain_host_stop(dev); + ret2 = chain_link_stop(dev); + } else { + ret = chain_link_stop(dev); + ret2 = chain_host_stop(dev); + } + if (!ret) + ret = ret2; + if (ret < 0) + goto error; + + cd->chain_task.state = SOF_TASK_STATE_COMPLETED; + schedule_task_free(&cd->chain_task); + pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + +error: + k_spin_unlock(&drivers->lock, key); + return ret; +} + +/* Get size of data, which was consumed by link */ +static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const uint32_t in_read_pos, + const size_t buff_size) +{ + if (out_read_pos >= in_read_pos) + return out_read_pos - in_read_pos; + + return buff_size - in_read_pos + out_read_pos; +} + +static enum task_state chain_task_run(void *data) +{ + size_t link_avail_bytes, link_free_bytes, host_avail_bytes, host_free_bytes; + struct chain_dma_data *cd = data; + uint32_t link_read_pos, host_read_pos; + struct dma_status stat; + uint32_t link_type; + int ret; + + /* Link DMA can return -EPIPE and current status if xrun occurs, then it is not critical + * and flow shall continue. Other error values will be treated as critical. + */ + ret = dma_get_status(cd->chan_link->dma->z_dev, cd->chan_link->index, &stat); + switch (ret) { + case 0: + break; + case -EPIPE: + tr_warn(&chain_dma_tr, "chain_task_run(): dma_get_status() link xrun occurred," + " ret = %u", ret); + break; + default: + tr_err(&chain_dma_tr, "chain_task_run(): dma_get_status() error, ret = %u", ret); + return SOF_TASK_STATE_COMPLETED; + } + + link_avail_bytes = stat.pending_length; + link_free_bytes = stat.free; + link_read_pos = stat.read_position; + + /* Host DMA does not report xruns. All error values will be treated as critical. */ + ret = dma_get_status(cd->chan_host->dma->z_dev, cd->chan_host->index, &stat); + if (ret < 0) { + tr_err(&chain_dma_tr, "chain_task_run(): dma_get_status() error, ret = %u", ret); + return SOF_TASK_STATE_COMPLETED; + } + + host_avail_bytes = stat.pending_length; + host_free_bytes = stat.free; + host_read_pos = stat.read_position; + + link_type = cd->link_connector_node_id.f.dma_type; + if (link_type == ipc4_hda_link_input_class) { + /* CAPTURE: + * When chained Link Input with Host Input immediately start transmitting data + * to host. In this mode task will always stream to host as much data as possible + */ + const size_t increment = MIN(host_free_bytes, link_avail_bytes); + + ret = dma_reload(cd->chan_host->dma->z_dev, cd->chan_host->index, 0, 0, increment); + if (ret < 0) { + tr_err(&chain_dma_tr, + "chain_task_run(): dma_reload() host error, ret = %u", ret); + return SOF_TASK_STATE_COMPLETED; + } + + ret = dma_reload(cd->chan_link->dma->z_dev, cd->chan_link->index, 0, 0, increment); + if (ret < 0) { + tr_err(&chain_dma_tr, + "chain_task_run(): dma_reload() link error, ret = %u", ret); + return SOF_TASK_STATE_COMPLETED; + } + } else { + /* PLAYBACK: + * When chained Host Output with Link Output then wait for half buffer full. In this + * mode task will update read position based on transferred data size to avoid + * overwriting valid data and write position by half buffer size. + */ + const size_t half_buff_size = cd->dma_buffer->stream.size / 2; + + if (!cd->first_data_received && host_avail_bytes > half_buff_size) { + ret = dma_reload(cd->chan_link->dma->z_dev, + cd->chan_link->index, 0, 0, + half_buff_size); + if (ret < 0) { + tr_err(&chain_dma_tr, + "chain_task_run(): dma_reload() link error, ret = %u", + ret); + return SOF_TASK_STATE_COMPLETED; + } + cd->first_data_received = true; + + } else if (cd->first_data_received) { + const size_t transferred = + chain_get_transferred_data_size(link_read_pos, + host_read_pos, + cd->dma_buffer->stream.size); + + ret = dma_reload(cd->chan_host->dma->z_dev, cd->chan_host->index, + 0, 0, transferred); + if (ret < 0) { + tr_err(&chain_dma_tr, + "chain_task_run(): dma_reload() host error, ret = %u", ret); + return SOF_TASK_STATE_COMPLETED; + } + + if (host_avail_bytes >= half_buff_size && + link_free_bytes >= half_buff_size) { + ret = dma_reload(cd->chan_link->dma->z_dev, cd->chan_link->index, + 0, 0, half_buff_size); + if (ret < 0) { + tr_err(&chain_dma_tr, "chain_task_run(): dma_reload() " + "link error, ret = %u", ret); + return SOF_TASK_STATE_COMPLETED; + } + } + } + } + return SOF_TASK_STATE_RESCHEDULE; +} + +static void chain_release(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + + dma_release_channel(cd->chan_host->dma->z_dev, cd->chan_host->index); + dma_put(cd->dma_host); + dma_release_channel(cd->chan_link->dma->z_dev, cd->chan_link->index); + dma_put(cd->dma_link); + + if (cd->dma_buffer) { + buffer_free(cd->dma_buffer); + cd->dma_buffer = NULL; + } +} + +/* Retrieves host connector node id from dma id */ +static int get_connector_node_id(uint32_t dma_id, bool host_type, + union ipc4_connector_node_id *connector_node_id) +{ + uint8_t type = host_type ? ipc4_hda_host_output_class : ipc4_hda_link_output_class; + + if (dma_id >= DAI_NUM_HDA_OUT) { + type = host_type ? ipc4_hda_host_input_class : ipc4_hda_link_input_class; + dma_id -= DAI_NUM_HDA_OUT; + if (dma_id >= DAI_NUM_HDA_IN) + return -EINVAL; + } + connector_node_id->dw = 0; + connector_node_id->f.dma_type = type; + connector_node_id->f.v_index = dma_id; + + return 0; +} + +static int chain_init(struct comp_dev *dev, void *addr, size_t length) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + struct dma_block_config *dma_block_cfg_host = &cd->dma_block_cfg_host; + struct dma_block_config *dma_block_cfg_link = &cd->dma_block_cfg_link; + struct dma_config *dma_cfg_host = &cd->z_config_host; + struct dma_config *dma_cfg_link = &cd->z_config_link; + int channel; + int err; + + memset(dma_cfg_host, 0, sizeof(*dma_cfg_host)); + memset(dma_block_cfg_host, 0, sizeof(*dma_block_cfg_host)); + dma_cfg_host->block_count = 1; + dma_cfg_host->source_data_size = cd->cs; + dma_cfg_host->dest_data_size = cd->cs; + dma_cfg_host->head_block = dma_block_cfg_host; + dma_block_cfg_host->block_size = length; + + memset(dma_cfg_link, 0, sizeof(*dma_cfg_link)); + memset(dma_block_cfg_link, 0, sizeof(*dma_block_cfg_link)); + dma_cfg_link->block_count = 1; + dma_cfg_link->source_data_size = cd->cs; + dma_cfg_link->dest_data_size = cd->cs; + dma_cfg_link->head_block = dma_block_cfg_link; + dma_block_cfg_link->block_size = length; + + switch (cd->stream_direction) { + case SOF_IPC_STREAM_PLAYBACK: + dma_cfg_host->channel_direction = HOST_TO_MEMORY; + dma_block_cfg_host->dest_address = (uint32_t)addr; + dma_cfg_link->channel_direction = MEMORY_TO_PERIPHERAL; + dma_block_cfg_link->source_address = (uint32_t)addr; + break; + case SOF_IPC_STREAM_CAPTURE: + dma_cfg_host->channel_direction = MEMORY_TO_HOST; + dma_block_cfg_host->source_address = (uint32_t)addr; + dma_cfg_link->channel_direction = PERIPHERAL_TO_MEMORY; + dma_block_cfg_link->dest_address = (uint32_t)addr; + break; + } + + /* get host DMA channel */ + channel = cd->host_connector_node_id.f.v_index; + channel = dma_request_channel(cd->dma_host->z_dev, &channel); + if (channel < 0) { + comp_err(dev, "chain_init(): dma_request_channel() failed"); + return -EINVAL; + } + + cd->chan_host = &cd->dma_host->chan[channel]; + + err = dma_config(cd->dma_host->z_dev, cd->chan_host->index, dma_cfg_host); + if (err < 0) { + comp_err(dev, "chain_init(): dma_config() failed"); + goto error_host; + } + + /* get link DMA channel */ + channel = cd->link_connector_node_id.f.v_index; + channel = dma_request_channel(cd->dma_link->z_dev, &channel); + if (channel < 0) { + comp_err(dev, "chain_init(): dma_request_channel() failed"); + goto error_host; + } + + cd->chan_link = &cd->dma_link->chan[channel]; + + err = dma_config(cd->dma_link->z_dev, cd->chan_link->index, dma_cfg_link); + if (err < 0) { + comp_err(dev, "chain_init(): dma_config() failed"); + goto error_link; + } + return 0; + +error_link: + dma_release_channel(cd->dma_link->z_dev, cd->chan_link->index); + cd->chan_link = NULL; +error_host: + dma_release_channel(cd->dma_host->z_dev, cd->chan_host->index); + cd->chan_host = NULL; + return err; +} + +static int chain_task_init(struct comp_dev *dev, uint8_t host_dma_id, uint8_t link_dma_id, + uint32_t fifo_size) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + struct comp_buffer __sparse_cache *buffer_c; + uint32_t addr_align; + size_t buff_size; + void *buff_addr; + uint32_t dir; + int ret; + + schedule_task_init_ll(&cd->chain_task, SOF_UUID(chain_dma_uuid), + SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_HIGH, + chain_task_run, cd, 0, 0); + + ret = get_connector_node_id(host_dma_id, true, &cd->host_connector_node_id); + if (ret < 0) + return ret; + + ret = get_connector_node_id(link_dma_id, false, &cd->link_connector_node_id); + if (ret < 0) + return ret; + + /* Verify whether HDA gateways can be chained */ + if (cd->host_connector_node_id.f.dma_type == ipc4_hda_host_output_class) { + if (cd->link_connector_node_id.f.dma_type != ipc4_hda_link_output_class) + return -EINVAL; + cd->stream_direction = SOF_IPC_STREAM_PLAYBACK; + } + if (cd->host_connector_node_id.f.dma_type == ipc4_hda_host_input_class) { + if (cd->link_connector_node_id.f.dma_type != ipc4_hda_link_input_class) + return -EINVAL; + cd->stream_direction = SOF_IPC_STREAM_CAPTURE; + } + + /* request HDA DMA with shared access privilege */ + dir = (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) ? + DMA_DIR_HMEM_TO_LMEM : DMA_DIR_LMEM_TO_HMEM; + + cd->dma_host = dma_get(dir, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); + if (!cd->dma_host) { + comp_err(dev, "chain_task_init(): dma_get() returned NULL"); + return -EINVAL; + } + + dir = (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) ? + DMA_DIR_MEM_TO_DEV : DMA_DIR_DEV_TO_MEM; + + cd->dma_link = dma_get(dir, DMA_CAP_HDA, DMA_DEV_HDA, DMA_ACCESS_SHARED); + if (!cd->dma_link) { + dma_put(cd->dma_host); + comp_err(dev, "chain_task_init(): dma_get() returned NULL"); + return -EINVAL; + } + + /* retrieve DMA buffer address alignment */ + ret = dma_get_attribute(cd->dma_host->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (ret < 0) { + comp_err(dev, + "chain_task_init(): could not get dma buffer address alignment, err = %d", + ret); + goto error; + } + + fifo_size = ALIGN_UP_INTERNAL(fifo_size, addr_align); + + switch (cd->link_connector_node_id.f.dma_type) { + case ipc4_hda_link_input_class: + /* Increasing buffer size for capture path as L1SEN exit takes sometimes + * more than expected. To prevent from glitches and DMA overruns buffer + * is increased 5 times. + */ + fifo_size *= 5; + break; + case ipc4_hda_link_output_class: + /* Increasing buffer size for playback path as L1SEN exit takes sometimes + * more that expected + * Note, FIFO size must be smaller than half of host buffer size + * (20ms ping pong) to avoid problems with position reporting + * Size increase from default 2ms to 5ms is enough. + */ + fifo_size *= 5; + fifo_size /= 2; + break; + } + + cd->dma_buffer = buffer_alloc(fifo_size, SOF_MEM_CAPS_DMA, addr_align); + + if (!cd->dma_buffer) { + comp_err(dev, "chain_task_init(): failed to alloc dma buffer"); + ret = -EINVAL; + goto error; + } + + /* clear dma buffer */ + buffer_c = buffer_acquire(cd->dma_buffer); + buffer_zero(buffer_c); + buff_addr = cd->dma_buffer->stream.addr; + buff_size = cd->dma_buffer->stream.size; + buffer_release(buffer_c); + + ret = chain_init(dev, buff_addr, buff_size); + if (ret < 0) { + buffer_free(cd->dma_buffer); + cd->dma_buffer = NULL; + goto error; + } + + cd->chain_task.state = SOF_TASK_STATE_INIT; + + return 0; +error: + dma_put(cd->dma_host); + dma_put(cd->dma_link); + return ret; +} + +static int chain_task_trigger(struct comp_dev *dev, int cmd) +{ + switch (cmd) { + case COMP_TRIGGER_START: + return chain_task_start(dev); + case COMP_TRIGGER_PAUSE: + return chain_task_pause(dev); + default: + return -EINVAL; + } +} + +static struct comp_dev *chain_task_create(const struct comp_driver *drv, + const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config) +{ + const struct ipc4_chain_dma *cdma = (struct ipc4_chain_dma *)ipc_specific_config; + const uint32_t host_dma_id = cdma->primary.r.host_dma_id; + const uint32_t link_dma_id = cdma->primary.r.link_dma_id; + const uint32_t fifo_size = cdma->extension.r.fifo_size; + const bool scs = cdma->primary.r.scs; + struct chain_dma_data *cd; + struct comp_dev *dev; + int ret; + + if (host_dma_id >= max_chain_number) + return NULL; + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + + cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); + if (!cd) + goto error; + + cd->first_data_received = false; + cd->cs = scs ? 2 : 4; + cd->chain_task.state = SOF_TASK_STATE_INIT; + + comp_set_drvdata(dev, cd); + + ret = chain_task_init(dev, host_dma_id, link_dma_id, fifo_size); + if (ret) + goto error_cd; + + return dev; + +error_cd: + rfree(cd); +error: + rfree(dev); + return NULL; +} + +static void chain_task_free(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + + chain_release(dev); + rfree(cd); + rfree(dev); +} + +static const struct comp_driver comp_chain_dma = { + .uid = SOF_RT_UUID(chain_dma_uuid), + .tctx = &chain_dma_tr, + .ops = { + .create = chain_task_create, + .trigger = chain_task_trigger, + .free = chain_task_free, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_chain_dma_info = { + .drv = &comp_chain_dma, +}; + +UT_STATIC void sys_comp_chain_dma_init(void) +{ + comp_register(platform_shared_get(&comp_chain_dma_info, + sizeof(comp_chain_dma_info))); +} + +DECLARE_MODULE(sys_comp_chain_dma_init); diff --git a/src/include/ipc4/error_status.h b/src/include/ipc4/error_status.h index 14eede02a3b7..c3ad27bf2a61 100644 --- a/src/include/ipc4/error_status.h +++ b/src/include/ipc4/error_status.h @@ -124,6 +124,9 @@ enum ipc4_status { /**< Reverted for ULP purposes */ IPC4_PIPELINE_STATE_NOT_SET = 164, + /**< HDA chained gateways wrong state transition*/ + IPC4_INVALID_CHAIN_STATE_TRANSITION = 3018, + IPC4_MAX_STATUS = ((1 << IPC4_IXC_STATUS_BITS) - 1) }; #endif diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index 30adf5ba5824..971be21f29ef 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -50,6 +50,8 @@ const struct comp_driver *ipc4_get_comp_drv(int module_id); struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id); int ipc4_add_comp_dev(struct comp_dev *dev); const struct comp_driver *ipc4_get_drv(uint8_t *uuid); +int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma); +int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma); int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma); int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *delay); int ipc4_process_on_core(uint32_t core, bool blocking); diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 913aa066fdad..6de3e6a71119 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -659,6 +659,60 @@ static int construct_config(struct ipc4_copier_module_cfg *copier_cfg, uint32_t return IPC4_SUCCESS; } +#if CONFIG_COMP_CHAIN_DMA +int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma) +{ + const struct sof_uuid uuid = {0x6a0a274f, 0x27cc, 0x4afb, {0xa3, 0xe7, 0x34, + 0x44, 0x72, 0x3f, 0x43, 0x2e}}; + const struct comp_driver *drv; + struct comp_dev *dev; + + drv = ipc4_get_drv((uint8_t *)&uuid); + if (!drv) + return -EINVAL; + + dev = drv->ops.create(drv, NULL, cdma); + if (!dev) + return -EINVAL; + + /* differentiate instance by unique ids assignment */ + const uint32_t comp_id = IPC4_COMP_ID(cdma->primary.r.host_dma_id + + IPC4_MAX_MODULE_COUNT, 0); + dev->ipc_config.id = comp_id; + dev->ipc_config.pipeline_id = cdma->primary.r.host_dma_id + + IPC4_MAX_MODULE_COUNT; + + return ipc4_add_comp_dev(dev); +} + +int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) +{ + const bool allocate = cdma->primary.r.allocate; + const bool enable = cdma->primary.r.enable; + int ret; + + if (!dev) + return -EINVAL; + + if (allocate) { + if (enable) + ret = comp_trigger(dev, COMP_TRIGGER_START); + else + ret = comp_trigger(dev, COMP_TRIGGER_PAUSE); + } else { + if (enable) + return -EINVAL; + + /* remove chain part */ + ret = comp_trigger(dev, COMP_TRIGGER_PAUSE); + if (ret < 0) + return ret; + comp_free(dev); + } + return ret; +} +#endif + int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma) { struct ipc4_copier_module_cfg copier_cfg; diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b1ec97004e86..478bbf6e95ce 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -776,6 +776,10 @@ zephyr_library_sources_ifdef(CONFIG_PASSTHROUGH_CODEC ) endif() +zephyr_library_sources_ifdef(CONFIG_COMP_CHAIN_DMA + ${SOF_AUDIO_PATH}/chain_dma.c +) + zephyr_library_sources_ifdef(CONFIG_COMP_SRC ${SOF_AUDIO_PATH}/src/src_hifi2ep.c ${SOF_AUDIO_PATH}/src/src_generic.c diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index c7a14801d514..78203251c13a 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -191,6 +191,7 @@ void sys_comp_module_mixout_interface_init(void); void sys_comp_dai_init(void); void sys_comp_src_init(void); void sys_comp_mux_init(void); +void sys_comp_chain_dma_init(void); #if CONFIG_IPC_MAJOR_3 void sys_comp_src_init(void); void sys_comp_selector_init(void); @@ -390,6 +391,10 @@ int task_main_start(struct sof *sof) /* init pipeline position offsets */ pipeline_posn_init(sof); + /* init chain dma manager*/ + if (IS_ENABLED(CONFIG_COMP_CHAIN_DMA)) + sys_comp_chain_dma_init(); + #if defined(CONFIG_IMX) #define SOF_IPC_QUEUED_DOMAIN SOF_SCHEDULE_LL_DMA #else From dc1731be2f4bff2ac279ff0a938451b28747a2e9 Mon Sep 17 00:00:00 2001 From: Piotr Makaruk Date: Wed, 14 Dec 2022 14:54:18 +0100 Subject: [PATCH 2/5] hda: enable handler for hw chain dma HW chain dma support require new logic in handler Signed-off-by: Piotr Makaruk --- src/ipc/ipc4/handler.c | 70 ++++---- src/ipc/ipc4/helper.c | 357 ----------------------------------------- 2 files changed, 38 insertions(+), 389 deletions(-) diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index d1858556a522..9121c86a078f 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -460,49 +460,55 @@ static int ipc4_load_library(struct ipc4_message_request *ipc4) static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4) { - struct ipc4_chain_dma cdma; +#if CONFIG_COMP_CHAIN_DMA + struct ipc_comp_dev *cdma_comp; struct ipc *ipc = ipc_get(); - bool delay = false; - int ret = memcpy_s(&cdma, sizeof(cdma), ipc4, sizeof(*ipc4)); + struct ipc4_chain_dma cdma; + int comp_id; + int ret; + ret = memcpy_s(&cdma, sizeof(cdma), ipc4, sizeof(*ipc4)); if (ret < 0) return IPC4_FAILURE; - if (cdma.primary.r.allocate && cdma.extension.r.fifo_size) { - ret = ipc4_create_chain_dma(ipc, &cdma); - if (ret) { - tr_err(&ipc_tr, "failed to create chain dma %d", ret); - return ret; - } + comp_id = IPC4_COMP_ID(cdma.primary.r.host_dma_id + IPC4_MAX_MODULE_COUNT, 0); + cdma_comp = ipc_get_comp_by_id(ipc, comp_id); - /* if enable is not set, chain dma pipeline is not going to be triggered */ - if (!cdma.primary.r.enable) - return ret; - } + if (!cdma_comp && cdma.primary.r.allocate && cdma.primary.r.enable) { + ret = ipc4_chain_manager_create(&cdma); + if (ret < 0) + return IPC4_FAILURE; - atomic_set(&msg_data.delayed_reply, 1); - ret = ipc4_trigger_chain_dma(ipc, &cdma, &delay); - /* it is not scheduled in another thread */ - if (!delay) { - atomic_set(&msg_data.delayed_reply, 0); - msg_data.delayed_error = 0; - } else if (!cdma.primary.r.allocate) { - uint32_t pipeline_id = IPC4_COMP_ID(cdma.primary.r.host_dma_id - + IPC4_MAX_MODULE_COUNT, - cdma.primary.r.link_dma_id); - - /* waiting for pipeline reset done */ - ipc_wait_for_compound_msg(); - ret = ipc_pipeline_free(ipc, pipeline_id); + cdma_comp = ipc_get_comp_by_id(ipc, comp_id); + if (!cdma_comp) { + comp_free(cdma_comp->cd); + return IPC4_FAILURE; + } + + ret = ipc4_chain_dma_state(cdma_comp->cd, &cdma); if (ret < 0) { - tr_err(&ipc_tr, "failed to free chain dma %d", ret); - ret = IPC4_BAD_STATE; - } else { - ret = IPC4_SUCCESS; + comp_free(cdma_comp->cd); + return IPC4_FAILURE; } + + return IPC4_SUCCESS; } - return ret; + cdma_comp = ipc_get_comp_by_id(ipc, comp_id); + if (!cdma_comp) + return IPC4_FAILURE; + + ret = ipc4_chain_dma_state(cdma_comp->cd, &cdma); + if (ret < 0) + return IPC4_INVALID_CHAIN_STATE_TRANSITION; + + if (!cdma.primary.r.allocate && !cdma.primary.r.enable) + list_item_del(&cdma_comp->list); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif } static int ipc4_process_glb_message(struct ipc4_message_request *ipc4) diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 6de3e6a71119..1827e2baf104 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -514,151 +514,6 @@ static inline int process_dma_index(uint32_t dma_id, uint32_t *dir, uint32_t *ch return IPC4_SUCCESS; } -static struct comp_dev *ipc4_create_host(uint32_t pipeline_id, uint32_t id, uint32_t dir) -{ - struct sof_uuid uuid = {0x8b9d100c, 0x6d78, 0x418f, {0x90, 0xa3, 0xe0, - 0xe8, 0x05, 0xd0, 0x85, 0x2b}}; - struct ipc_config_host ipc_host; - struct comp_ipc_config config; - const struct comp_driver *drv; - struct comp_dev *dev; - - drv = ipc4_get_drv((uint8_t *)&uuid); - if (!drv) - return NULL; - - memset_s(&config, sizeof(config), 0, sizeof(config)); - config.type = SOF_COMP_HOST; - config.pipeline_id = pipeline_id; - config.core = 0; - config.id = id; - - memset(&ipc_host, 0, sizeof(ipc_host)); - ipc_host.direction = dir; - - dev = drv->ops.create(drv, &config, &ipc_host); - if (!dev) - return NULL; - - dev->direction = dir; - list_init(&dev->bsource_list); - list_init(&dev->bsink_list); - - return dev; -} - -static struct comp_dev *ipc4_create_dai(struct pipeline *pipe, uint32_t id, uint32_t dir, - struct ipc4_copier_module_cfg *copier_cfg, - struct sof_ipc_stream_params *params, - uint32_t link_chan) -{ - struct sof_uuid uuid = {0xc2b00d27, 0xffbc, 0x4150, {0xa5, 0x1a, 0x24, - 0x5c, 0x79, 0xc5, 0xe5, 0x4b}}; - const struct comp_driver *drv; - struct comp_ipc_config config; - struct ipc_config_dai dai; - struct comp_dev *dev; - int ret; - - drv = ipc4_get_drv((uint8_t *)&uuid); - if (!drv) - return NULL; - - memset_s(&config, sizeof(config), 0, sizeof(config)); - config.type = SOF_COMP_DAI; - config.frame_fmt = params->frame_fmt; - config.pipeline_id = pipe->pipeline_id; - config.core = 0; - config.id = id; - - memset(&dai, 0, sizeof(dai)); - dai.dai_index = DAI_NUM_HDA_OUT + DAI_NUM_HDA_IN - 1; - dai.type = SOF_DAI_INTEL_HDA; - dai.is_config_blob = true; - dai.direction = dir; - dev = drv->ops.create(drv, &config, &dai); - if (!dev) - return NULL; - - pipe->sched_id = id; - - dev->direction = dir; - list_init(&dev->bsource_list); - list_init(&dev->bsink_list); - - copier_cfg->gtw_cfg.node_id.dw = link_chan; - ret = comp_dai_config(dev, &dai, copier_cfg); - if (ret < 0) - return NULL; - - return dev; -} - -/* host does not send any params to FW since it expects simple copy - * but sof needs hw params to feed pass-through pipeline. This - * function rebuilds the hw params based on fifo_size since only 48K - * and 44.1K sample rate and 16 & 24bit are supported by chain dma. - */ -static int construct_config(struct ipc4_copier_module_cfg *copier_cfg, uint32_t fifo_size, - struct sof_ipc_stream_params *params, uint32_t scs) -{ - uint32_t frame_size; - - /* fifo_size = rate * channel * depth - * support stream format : 48k * n, 44.1k * n, 32k *n and 16k * n. - * Since the chain dma is used to just copy data from host to dai - * without any change, 32k * 1 ch makes the same effect as - * 16k * 2ch - */ - if (fifo_size % 48 == 0) { - copier_cfg->base.audio_fmt.sampling_frequency = IPC4_FS_48000HZ; - frame_size = fifo_size / 48; - } else if (fifo_size % 44 == 0) { - copier_cfg->base.audio_fmt.sampling_frequency = IPC4_FS_44100HZ; - frame_size = fifo_size / 44; - } else if (fifo_size % 32 == 0) { - copier_cfg->base.audio_fmt.sampling_frequency = IPC4_FS_32000HZ; - frame_size = fifo_size / 32; - } else if (fifo_size % 16 == 0) { - copier_cfg->base.audio_fmt.sampling_frequency = IPC4_FS_16000HZ; - frame_size = fifo_size / 16; - } else { - tr_err(&comp_tr, "unsupported fifo_size %d", fifo_size); - return IPC4_ERROR_INVALID_PARAM; - } - - params->rate = copier_cfg->base.audio_fmt.sampling_frequency; - - /* convert double buffer to single buffer */ - frame_size >>= 1; - - /* two cases based on scs : 16 bits or 32 bits sample size */ - if (!scs) { - copier_cfg->base.audio_fmt.depth = 32; - copier_cfg->base.audio_fmt.valid_bit_depth = 32; - params->frame_fmt = SOF_IPC_FRAME_S32_LE; - params->sample_container_bytes = 4; - params->sample_valid_bytes = 4; - } else { - copier_cfg->base.audio_fmt.depth = 16; - copier_cfg->base.audio_fmt.valid_bit_depth = 16; - params->frame_fmt = SOF_IPC_FRAME_S16_LE; - params->sample_container_bytes = 2; - params->sample_valid_bytes = 2; - } - - copier_cfg->base.audio_fmt.channels_count = frame_size / - (copier_cfg->base.audio_fmt.depth / 8); - - params->channels = copier_cfg->base.audio_fmt.channels_count; - params->buffer.size = fifo_size; - - copier_cfg->out_fmt = copier_cfg->base.audio_fmt; - copier_cfg->base.ibs = fifo_size; - copier_cfg->base.obs = fifo_size; - return IPC4_SUCCESS; -} - #if CONFIG_COMP_CHAIN_DMA int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma) { @@ -713,218 +568,6 @@ int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) } #endif -int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma) -{ - struct ipc4_copier_module_cfg copier_cfg; - struct sof_ipc_stream_params params; - struct ipc_comp_dev *ipc_pipe; - struct sof_ipc_buffer ipc_buf; - struct comp_dev *host; - struct comp_dev *dai; - struct comp_buffer *buf; - struct comp_dev *src; - struct comp_dev *sink; - uint32_t pipeline_id; - uint32_t host_id; - uint32_t dai_id; - uint32_t buf_id; - uint32_t dir, host_chan, link_chan; - int ret; - - ret = process_dma_index(cdma->primary.r.host_dma_id, &dir, &host_chan); - if (ret != IPC4_SUCCESS) - return ret; - - ret = process_dma_index(cdma->primary.r.link_dma_id, &dir, &link_chan); - if (ret != IPC4_SUCCESS) - return ret; - - /* build a pipeline id based on dma id */ - pipeline_id = IPC4_COMP_ID(cdma->primary.r.host_dma_id + IPC4_MAX_MODULE_COUNT, - cdma->primary.r.link_dma_id); - ret = ipc4_create_pipeline(pipeline_id, 0, cdma->extension.r.fifo_size, - PLATFORM_PRIMARY_CORE_ID); - if (ret != IPC4_SUCCESS) { - tr_err(&comp_tr, "failed to create pipeline for chain dma"); - return ret; - } - - ipc_pipe = ipc_get_comp_by_id(ipc, pipeline_id); - - host_id = pipeline_id + 1; - host = ipc4_create_host(pipeline_id, host_id, dir); - if (!host) { - tr_err(&comp_tr, "failed to create host for chain dma"); - return IPC4_INVALID_REQUEST; - } - - host->period = ipc_pipe->pipeline->period; - - ret = ipc4_add_comp_dev(host); - if (ret != IPC4_SUCCESS) - return ret; - - memset_s(¶ms, sizeof(params), 0, sizeof(params)); - memset_s(&copier_cfg, sizeof(copier_cfg), 0, sizeof(copier_cfg)); - ret = construct_config(&copier_cfg, cdma->extension.r.fifo_size, ¶ms, - cdma->primary.r.scs); - if (ret != IPC4_SUCCESS) - return ret; - - params.direction = dir; - params.stream_tag = host_chan + 1; - - dai_id = host_id + 1; - dai = ipc4_create_dai(ipc_pipe->pipeline, dai_id, dir, &copier_cfg, ¶ms, link_chan); - if (!dai) { - tr_err(&comp_tr, "failed to create dai for chain dma"); - return IPC4_INVALID_REQUEST; - } - - dai->period = ipc_pipe->pipeline->period; - - ret = ipc4_add_comp_dev(dai); - if (ret != IPC4_SUCCESS) - return ret; - - buf_id = dai_id + 1; - if (dir == SOF_IPC_STREAM_PLAYBACK) { - src = host; - sink = dai; - } else { - src = dai; - sink = host; - } - - memset(&ipc_buf, 0, sizeof(ipc_buf)); - ipc_buf.size = cdma->extension.r.fifo_size; - ipc_buf.comp.id = buf_id; - ipc_buf.comp.pipeline_id = pipeline_id; - ipc_buf.comp.core = src->ipc_config.core; - buf = buffer_new(&ipc_buf); - if (!buf) { - tr_err(&comp_tr, "failed to create buffer for chain dma"); - return IPC4_OUT_OF_MEMORY; - } - - comp_buffer_connect(src, src->ipc_config.core, buf, PPL_CONN_DIR_COMP_TO_BUFFER); - comp_buffer_connect(sink, sink->ipc_config.core, buf, PPL_CONN_DIR_BUFFER_TO_COMP); - - ipc_pipe->pipeline->sched_comp = host; - ipc_pipe->pipeline->source_comp = src; - ipc_pipe->pipeline->sink_comp = sink; - - ret = ipc_pipeline_complete(ipc, pipeline_id); - if (ret < 0) - return IPC4_INVALID_RESOURCE_STATE; - - /* set up host & dai and start pipeline */ - if (cdma->primary.r.enable) { - buf->stream.channels = params.channels; - buf->stream.frame_fmt = params.frame_fmt; - buf->stream.valid_sample_fmt = params.frame_fmt; - buf->stream.rate = params.rate; - - ret = host->drv->ops.params(host, ¶ms); - if (ret < 0) { - tr_err(&ipc_tr, "failed to set host params %d", ret); - return IPC4_ERROR_INVALID_PARAM; - } - - ret = dai->drv->ops.params(dai, ¶ms); - if (ret < 0) { - tr_err(&ipc_tr, "failed to set dai params %d", ret); - return IPC4_ERROR_INVALID_PARAM; - } - - ret = pipeline_prepare(ipc_pipe->pipeline, host); - if (ret < 0) { - tr_err(&ipc_tr, "failed to prepare for chain dma %d", ret); - ret = IPC4_INVALID_RESOURCE_STATE; - } - } - - return ret; -} - -int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, - bool *delay) -{ - struct ipc_comp_dev *ipc_pipe; - struct comp_dev *host; - uint32_t pipeline_id; - int ret = 0; - - pipeline_id = IPC4_COMP_ID(cdma->primary.r.host_dma_id + IPC4_MAX_MODULE_COUNT, - cdma->primary.r.link_dma_id); - ipc_pipe = ipc_get_comp_by_id(ipc, pipeline_id); - if (!ipc_pipe) - return IPC4_INVALID_RESOURCE_ID; - - host = ipc_pipe->pipeline->source_comp; - if (host->direction == SOF_IPC_STREAM_CAPTURE) - host = ipc_pipe->pipeline->sink_comp; - - /* pause or release chain dma */ - if (!cdma->primary.r.enable) { - if (ipc_pipe->pipeline->status == COMP_STATE_ACTIVE) { - ret = pipeline_trigger(ipc_pipe->pipeline, host, COMP_TRIGGER_PAUSE); - if (ret < 0) { - tr_err(&ipc_tr, "failed to disable chain dma %d", ret); - return IPC4_BAD_STATE; - } else if (ret == PPL_STATUS_SCHEDULED) { - /* pipeline reset will be done by schedule thread */ - *delay = true; - return IPC4_SUCCESS; - } - } - - /* release chain dma */ - if (!cdma->primary.r.allocate) { - ret = pipeline_reset(ipc_pipe->pipeline, host); - if (ret < 0) { - tr_err(&ipc_tr, "failed to reset chain dma %d", ret); - return IPC4_BAD_STATE; - } - - ret = ipc_pipeline_free(ipc, pipeline_id); - if (ret < 0) { - tr_err(&ipc_tr, "failed to free chain dma %d", ret); - return IPC4_BAD_STATE; - } - } - - return IPC4_SUCCESS; - } - - if (!cdma->primary.r.allocate) { - tr_err(&ipc_tr, "can't enable chain dma"); - return IPC4_INVALID_REQUEST; - } - - switch (ipc_pipe->pipeline->status) { - case COMP_STATE_PAUSED: - ret = pipeline_trigger(ipc_pipe->pipeline, host, COMP_TRIGGER_PRE_RELEASE); - if (ret < 0) { - tr_err(&ipc_tr, "failed to resume chain dma %d", ret); - return IPC4_BAD_STATE; - } - break; - case COMP_STATE_READY: - case COMP_STATE_PREPARE: - ret = pipeline_trigger(ipc_pipe->pipeline, host, COMP_TRIGGER_PRE_START); - if (ret < 0) { - tr_err(&ipc_tr, "failed to start chain dma %d", ret); - return IPC4_BAD_STATE; - } - } - - if (ret == PPL_STATUS_SCHEDULED) - *delay = true; - - return IPC4_SUCCESS; -} - int ipc4_process_on_core(uint32_t core, bool blocking) { int ret; From c966532762da0bb7a4a055148e327e2a9af147ba Mon Sep 17 00:00:00 2001 From: Piotr Makaruk Date: Tue, 29 Nov 2022 13:35:46 +0100 Subject: [PATCH 3/5] tgl: hda: enable chain dma Enable building chain dma component on TGL platform Signed-off-by: Piotr Makaruk --- app/boards/intel_adsp_cavs25.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/app/boards/intel_adsp_cavs25.conf b/app/boards/intel_adsp_cavs25.conf index c3a6533b6057..45b514f66f8b 100644 --- a/app/boards/intel_adsp_cavs25.conf +++ b/app/boards/intel_adsp_cavs25.conf @@ -1,5 +1,6 @@ CONFIG_TIGERLAKE=y CONFIG_INTEL_DMIC=y +CONFIG_COMP_CHAIN_DMA=y CONFIG_DMIC_HW_IOCLK=38400000 CONFIG_INTEL_SSP=y CONFIG_INTEL_ALH=y From b91cab0ef4cbb70ce88a67821b0ece804efd6283 Mon Sep 17 00:00:00 2001 From: Piotr Makaruk Date: Tue, 29 Nov 2022 13:29:09 +0100 Subject: [PATCH 4/5] mtl: hda: enable chain dma Enable building chain dma component on MTL platform Signed-off-by: Piotr Makaruk --- app/boards/intel_adsp_ace15_mtpm.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index ffdaa7197562..047736942757 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -54,6 +54,7 @@ CONFIG_LOG_MODE_DEFERRED=y CONFIG_LOG_FUNC_NAME_PREFIX_INF=y CONFIG_COMP_VOLUME_WINDOWS_FADE=y CONFIG_COMP_UP_DOWN_MIXER=y +CONFIG_COMP_CHAIN_DMA=y CONFIG_SAMPLE_KEYPHRASE=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=38400000 From 414a12c02274f9697313cb145947a21de513412e Mon Sep 17 00:00:00 2001 From: Piotr Makaruk Date: Wed, 11 Jan 2023 09:27:22 +0100 Subject: [PATCH 5/5] tgl-h: hda: enable chain dma Enable building chain dma component on TGL-H platform Signed-off-by: Piotr Makaruk --- app/boards/intel_adsp_cavs25_tgph.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/app/boards/intel_adsp_cavs25_tgph.conf b/app/boards/intel_adsp_cavs25_tgph.conf index 199ef82ab079..0aaac87a6496 100644 --- a/app/boards/intel_adsp_cavs25_tgph.conf +++ b/app/boards/intel_adsp_cavs25_tgph.conf @@ -1,5 +1,6 @@ CONFIG_TIGERLAKE=y CONFIG_INTEL_DMIC=y +CONFIG_COMP_CHAIN_DMA=y CONFIG_DMIC_HW_IOCLK=38400000 CONFIG_INTEL_SSP=y CONFIG_INTEL_ALH=y