From dc6770d8ba239b23c3287cb3b8459c38615875b3 Mon Sep 17 00:00:00 2001 From: BANDA MADHU Date: Mon, 6 Nov 2023 15:07:38 +0530 Subject: [PATCH] platform: amd: Add support for One Shot DMA configuration Support for One Shot DMA configuration for AMD Platforms. Signed-off-by: BANDA MADHU --- src/audio/Kconfig | 6 +++ src/audio/host-legacy.c | 2 +- src/drivers/amd/common/acp_dma.c | 28 ++++------- src/drivers/amd/rembrandt/acp_bt_dma.c | 20 ++++++-- src/drivers/amd/rembrandt/acp_dma.c | 64 +++++++++++++++-------- src/drivers/amd/rembrandt/acp_hs_dma.c | 19 +++++-- src/drivers/amd/rembrandt/acp_sp_dma.c | 19 +++++-- src/drivers/amd/renoir/acp_bt_dma.c | 20 ++++++-- src/drivers/amd/renoir/acp_dma.c | 50 ++++++++++++------ src/drivers/amd/renoir/acp_sp_dma.c | 17 +++++-- src/drivers/amd/vangogh/acp_bt_dma.c | 20 ++++++-- src/drivers/amd/vangogh/acp_dma.c | 70 ++++++++++++++++++-------- src/drivers/amd/vangogh/acp_hs_dma.c | 19 +++++-- src/drivers/amd/vangogh/acp_sp_dma.c | 19 +++++-- 14 files changed, 274 insertions(+), 99 deletions(-) diff --git a/src/audio/Kconfig b/src/audio/Kconfig index b05957a835d3..1ea03b65e603 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -725,4 +725,10 @@ config COMP_MODULE_SHARED_LIBRARY_BUILD Select if you want to build modules as shared objects that can be used to run pipelines on the host with the testbench or the ALSA plugin. +config DISABLE_DESCRIPTOR_SPLIT + bool "Disable descriptor split" + default n + help + This option disbale the descriptor split for host p-table. + endmenu diff --git a/src/audio/host-legacy.c b/src/audio/host-legacy.c index bd418c0fe5f2..a6531186ad23 100644 --- a/src/audio/host-legacy.c +++ b/src/audio/host-legacy.c @@ -180,7 +180,7 @@ static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd, struct comp_d copy_bytes = ALIGN_DOWN(copy_bytes, hd->dma_copy_align); split_value = host_dma_get_split(hd, copy_bytes); - if (split_value) + if (!IS_ENABLED(CONFIG_DISABLE_DESCRIPTOR_SPLIT) && split_value) copy_bytes -= split_value; local_elem->size = copy_bytes; diff --git a/src/drivers/amd/common/acp_dma.c b/src/drivers/amd/common/acp_dma.c index f71020ba74ad..551bd66c55ac 100644 --- a/src/drivers/amd/common/acp_dma.c +++ b/src/drivers/amd/common/acp_dma.c @@ -72,6 +72,7 @@ static struct dma_chan_data *acp_dma_channel_get(struct dma *dma, acp_dma_chan->config[req_chan].rd_size = 0; acp_dma_chan->config[req_chan].wr_size = 0; + acp_dma_chan->config[req_chan].size = 0; return channel; } @@ -207,24 +208,17 @@ static int acp_dma_copy(struct dma_chan_data *channel, int bytes, uint32_t flags uint32_t dmach_mask = (1 << channel->index); int ret = 0; - if (flags & DMA_COPY_ONE_SHOT) { - ret = acp_dma_start(channel); - if (ret < 0) - return ret; - ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); - while (ch_sts.bits.dmachrunsts & dmach_mask) - ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); - ret = acp_dma_stop(channel); - } - /* Reconfigure dma descriptors for stream channels only */ - if (channel->index != DMA_TRACE_CHANNEL) { - /* Reconfigure the dma descriptors for next buffer of data after the call back */ + if (channel->index != DMA_TRACE_CHANNEL) amd_dma_reconfig(channel, bytes); - /* Start the dma for requested channel */ - acp_dma_start(channel); - /* Stop the dma for requested channel */ - acp_dma_stop(channel); - } + + ret = acp_dma_start(channel); + if (ret < 0) + return ret; + ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + while (ch_sts.bits.dmachrunsts & dmach_mask) + ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + ret = acp_dma_stop(channel); + notifier_event(channel, NOTIFIER_ID_DMA_COPY, NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); return ret; diff --git a/src/drivers/amd/rembrandt/acp_bt_dma.c b/src/drivers/amd/rembrandt/acp_bt_dma.c index 1bc5aec6051e..93c9dc5b0427 100644 --- a/src/drivers/amd/rembrandt/acp_bt_dma.c +++ b/src/drivers/amd/rembrandt/acp_bt_dma.c @@ -120,6 +120,7 @@ static int acp_dai_bt_dma_start(struct dma_chan_data *channel) io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_ITER), bt_tdm_iter.u32all); } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; bt_ier = (acp_bttdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IER); bt_ier.bits.bttdm_ien = 1; io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); @@ -329,27 +330,40 @@ static int acp_dai_bt_dma_remove(struct dma *dma) static int acp_dai_bt_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > bt_buff_size ? + (curr_tx_pos - prev_tx_pos) % bt_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = bt_buff_size - *free; prev_tx_pos = curr_tx_pos; +#else *free = bt_buff_size >> 1; *avail = bt_buff_size >> 1; +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > bt_buff_size ? + (curr_rx_pos - prev_rx_pos) % bt_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = bt_buff_size - *free; prev_rx_pos = curr_rx_pos; +#else *free = bt_buff_size >> 1; *avail = bt_buff_size >> 1; +#endif } else { tr_err(&acp_bt_dma_tr, "Channel direction Not defined %d", channel->direction); diff --git a/src/drivers/amd/rembrandt/acp_dma.c b/src/drivers/amd/rembrandt/acp_dma.c index 940ba1392077..bd6530341ee6 100644 --- a/src/drivers/amd/rembrandt/acp_dma.c +++ b/src/drivers/amd/rembrandt/acp_dma.c @@ -74,6 +74,25 @@ void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes) dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); dma_cfg->rd_size = 0; } + /* Check for wrap-around case for host buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->size) { + tail = dma_cfg->size - dma_cfg->wr_size; + head = bytes - tail; + + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + + psrc_dscr[strt_idx + 1].dest_addr = + ((dma_cfg->base & ACP_DRAM_ADDRESS_MASK) | ACP_SRAM); + + src1 = src + tail; + psrc_dscr[strt_idx + 1].src_addr = src1; + + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + dma_cfg->rd_size += head; dma_cfg->rd_size %= dma_cfg->sys_buff_size; dma_cfg->wr_size += bytes; @@ -197,26 +216,31 @@ int dma_setup(struct dma_chan_data *channel, tc = dma_config_dscr[dscr_strt_idx].trns_cnt.bits.trns_cnt; /* DMA configuration for stream */ if (channel->index != DMA_TRACE_CHANNEL) { - acp_dma_chan->dir = dir; - acp_dma_chan->idx = channel->index; - dma_cfg->phy_off = phy_off[channel->index]; - dma_cfg->size = tc * dscr_cnt; - dma_cfg->sys_buff_size = syst_buff_size[channel->index]; + if (!dma_cfg->size) { + acp_dma_chan->dir = dir; + acp_dma_chan->idx = channel->index; + dma_cfg->phy_off = phy_off[channel->index]; + dma_cfg->size = tc * dscr_cnt; + dma_cfg->sys_buff_size = syst_buff_size[channel->index]; - if (dir == DMA_DIR_HMEM_TO_LMEM) { - /* Playback */ - dma_config_dscr[dscr_strt_idx].dest_addr = - (dma_config_dscr[dscr_strt_idx].dest_addr & ACP_DRAM_ADDRESS_MASK); - dma_cfg->base = dma_config_dscr[dscr_strt_idx].dest_addr | ACP_SRAM; - dma_cfg->wr_size = 0; - dma_cfg->rd_size = dma_cfg->size; - } else { - /* Capture */ - dma_config_dscr[dscr_strt_idx].src_addr = - (dma_config_dscr[dscr_strt_idx].src_addr & ACP_DRAM_ADDRESS_MASK); - dma_cfg->base = dma_config_dscr[dscr_strt_idx].src_addr | ACP_SRAM; - dma_cfg->wr_size = dma_cfg->size; - dma_cfg->rd_size = 0; + if (dir == DMA_DIR_HMEM_TO_LMEM) { + /* Playback */ + dma_config_dscr[dscr_strt_idx].dest_addr = + (dma_config_dscr[dscr_strt_idx].dest_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = + dma_config_dscr[dscr_strt_idx].dest_addr | ACP_SRAM; + dma_cfg->wr_size = 0; + dma_cfg->rd_size = dma_cfg->size; + } else { + /* Capture */ + dma_config_dscr[dscr_strt_idx].src_addr = + (dma_config_dscr[dscr_strt_idx].src_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = dma_config_dscr[dscr_strt_idx].src_addr | ACP_SRAM; + dma_cfg->wr_size = dma_cfg->size; + dma_cfg->rd_size = 0; + } } } /* clear the dma channel control bits */ @@ -244,7 +268,7 @@ int acp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) switch (type) { case DMA_ATTR_BUFFER_ALIGNMENT: case DMA_ATTR_COPY_ALIGNMENT: - *value = ACP_DMA_BUFFER_ALIGN_128; + *value = ACP_DMA_BUFFER_ALIGN; break; case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: *value = PLATFORM_DCACHE_ALIGN; diff --git a/src/drivers/amd/rembrandt/acp_hs_dma.c b/src/drivers/amd/rembrandt/acp_hs_dma.c index e49fca13615e..cf2bbe3d2689 100644 --- a/src/drivers/amd/rembrandt/acp_hs_dma.c +++ b/src/drivers/amd/rembrandt/acp_hs_dma.c @@ -327,27 +327,40 @@ static int acp_dai_hs_dma_remove(struct dma *dma) static int acp_dai_hs_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high<<32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > hs_buff_size_playback ? + (curr_tx_pos - prev_tx_pos) % hs_buff_size_playback : + (curr_tx_pos - prev_tx_pos); + *avail = hs_buff_size_playback - *free; prev_tx_pos = curr_tx_pos; +#else *free = (hs_buff_size_playback >> 1); *avail = (hs_buff_size_playback >> 1); +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high<<32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > hs_buff_size_capture ? + (curr_rx_pos - prev_rx_pos) % hs_buff_size_capture : + (curr_rx_pos - prev_rx_pos); + *avail = hs_buff_size_capture - *free; prev_rx_pos = curr_rx_pos; +#else *free = (hs_buff_size_capture >> 1); *avail = (hs_buff_size_capture >> 1); +#endif } else { tr_err(&acp_hs_tr, "Channel direction not defined %d", channel->direction); return -EINVAL; diff --git a/src/drivers/amd/rembrandt/acp_sp_dma.c b/src/drivers/amd/rembrandt/acp_sp_dma.c index 912e626d727c..008a8e41f736 100644 --- a/src/drivers/amd/rembrandt/acp_sp_dma.c +++ b/src/drivers/amd/rembrandt/acp_sp_dma.c @@ -212,27 +212,40 @@ int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high<<32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > sp_buff_size ? + (curr_tx_pos - prev_tx_pos) % sp_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = sp_buff_size - *free; prev_tx_pos = curr_tx_pos; +#else *free = (sp_buff_size >> 1); *avail = (sp_buff_size >> 1); +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high<<32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > sp_buff_size ? + (curr_rx_pos - prev_rx_pos) % sp_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = sp_buff_size - *free; prev_rx_pos = curr_rx_pos; +#else *free = (sp_buff_size >> 1); *avail = (sp_buff_size >> 1); +#endif } else { tr_err(&acp_sp_rmb_tr, "Channel direction not defined %d", channel->direction); return -EINVAL; diff --git a/src/drivers/amd/renoir/acp_bt_dma.c b/src/drivers/amd/renoir/acp_bt_dma.c index 85373e4521ba..0d061fb57210 100644 --- a/src/drivers/amd/renoir/acp_bt_dma.c +++ b/src/drivers/amd/renoir/acp_bt_dma.c @@ -119,6 +119,7 @@ static int acp_dai_bt_dma_start(struct dma_chan_data *channel) io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_ITER), bt_tdm_iter.u32all); } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; bt_ier = (acp_bttdm_ier_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_IER)); bt_ier.bits.bttdm_ien = 1; io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); @@ -325,27 +326,40 @@ static int acp_dai_bt_dma_remove(struct dma *dma) static int acp_dai_bt_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > bt_buff_size ? + (curr_tx_pos - prev_tx_pos) % bt_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = bt_buff_size - *free; prev_tx_pos = curr_tx_pos; +#else *free = bt_buff_size >> 1; *avail = bt_buff_size >> 1; +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > bt_buff_size ? + (curr_rx_pos - prev_rx_pos) % bt_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = bt_buff_size - *free; prev_rx_pos = curr_rx_pos; +#else *free = bt_buff_size >> 1; *avail = bt_buff_size >> 1; +#endif } else { tr_err(&acp_bt_dma_tr, "Channel direction Not defined %d", channel->direction); diff --git a/src/drivers/amd/renoir/acp_dma.c b/src/drivers/amd/renoir/acp_dma.c index c21775692ff3..11aff5bcb271 100644 --- a/src/drivers/amd/renoir/acp_dma.c +++ b/src/drivers/amd/renoir/acp_dma.c @@ -69,6 +69,24 @@ void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes) dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); dma_cfg->rd_size = 0; } + /* Check for wrap-around case for host buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->size) { + tail = dma_cfg->size - dma_cfg->wr_size; + head = bytes - tail; + + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + + /* start from "0" like starting address of buffer */ + psrc_dscr[strt_idx + 1].dest_addr = dma_cfg->base; + + psrc_dscr[strt_idx + 1].src_addr = src + tail; + + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + dma_cfg->rd_size += head; dma_cfg->rd_size %= dma_cfg->sys_buff_size; dma_cfg->wr_size += bytes; @@ -168,22 +186,24 @@ int dma_setup(struct dma_chan_data *channel, tc = dma_config_dscr[dscr_strt_idx].trns_cnt.bits.trns_cnt; /* DMA configuration for stream */ if (channel->index != DMA_TRACE_CHANNEL) { - acp_dma_chan->dir = dir; - acp_dma_chan->idx = channel->index; - dma_cfg->phy_off = phy_off[channel->index]; - dma_cfg->size = tc * dscr_cnt; - dma_cfg->sys_buff_size = syst_buff_size[channel->index]; + if (!dma_cfg->size) { + acp_dma_chan->dir = dir; + acp_dma_chan->idx = channel->index; + dma_cfg->phy_off = phy_off[channel->index]; + dma_cfg->size = tc * dscr_cnt; + dma_cfg->sys_buff_size = syst_buff_size[channel->index]; - if (dir == DMA_DIR_HMEM_TO_LMEM) { - /* Playback */ - dma_cfg->base = dma_config_dscr[dscr_strt_idx].dest_addr; - dma_cfg->wr_size = 0; - dma_cfg->rd_size = dma_cfg->size; - } else { - /* Capture */ - dma_cfg->base = dma_config_dscr[dscr_strt_idx].src_addr; - dma_cfg->wr_size = dma_cfg->size; - dma_cfg->rd_size = 0; + if (dir == DMA_DIR_HMEM_TO_LMEM) { + /* Playback */ + dma_cfg->base = dma_config_dscr[dscr_strt_idx].dest_addr; + dma_cfg->wr_size = 0; + dma_cfg->rd_size = dma_cfg->size; + } else { + /* Capture */ + dma_cfg->base = dma_config_dscr[dscr_strt_idx].src_addr; + dma_cfg->wr_size = dma_cfg->size; + dma_cfg->rd_size = 0; + } } } /* clear the dma channel control bits */ diff --git a/src/drivers/amd/renoir/acp_sp_dma.c b/src/drivers/amd/renoir/acp_sp_dma.c index 9000657aa998..4cddabba2486 100644 --- a/src/drivers/amd/renoir/acp_sp_dma.c +++ b/src/drivers/amd/renoir/acp_sp_dma.c @@ -210,19 +210,26 @@ int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high<<32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > sp_buff_size_playback ? + (curr_tx_pos - prev_tx_pos) % sp_buff_size_playback : + (curr_tx_pos - prev_tx_pos); + *avail = sp_buff_size_playback - *free; prev_tx_pos = curr_tx_pos; +#else *free = (sp_buff_size_playback >> 1); *avail = (sp_buff_size_playback >> 1); +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + @@ -231,8 +238,12 @@ int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, *free = (curr_rx_pos - prev_rx_pos) > sp_buff_size_capture ? (curr_rx_pos - prev_rx_pos) % sp_buff_size_capture : (curr_rx_pos - prev_rx_pos); + *avail = sp_buff_size_capture - *free; + prev_rx_pos = curr_rx_pos; +#else *avail = (sp_buff_size_capture >> 1); *free = (sp_buff_size_capture >> 1); +#endif } else { tr_err(&acp_sp_rn_tr, "Channel direction not defined %d", channel->direction); return -EINVAL; diff --git a/src/drivers/amd/vangogh/acp_bt_dma.c b/src/drivers/amd/vangogh/acp_bt_dma.c index 92ba4b86d2f7..b65c7c4c9ec9 100644 --- a/src/drivers/amd/vangogh/acp_bt_dma.c +++ b/src/drivers/amd/vangogh/acp_bt_dma.c @@ -116,6 +116,7 @@ static int acp_dai_bt_dma_start(struct dma_chan_data *channel) io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_ITER), bt_tdm_iter.u32all); } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; bt_ier = (acp_bttdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IER); bt_ier.bits.bttdm_ien = 1; io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); @@ -324,27 +325,40 @@ static int acp_dai_bt_dma_remove(struct dma *dma) static int acp_dai_bt_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > bt_buff_size ? + (curr_tx_pos - prev_tx_pos) % bt_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = bt_buff_size - *free; prev_tx_pos = curr_tx_pos; +#else *free = bt_buff_size >> 1; *avail = bt_buff_size >> 1; +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > bt_buff_size ? + (curr_rx_pos - prev_rx_pos) % bt_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = bt_buff_size - *free; prev_rx_pos = curr_rx_pos; +#else *free = bt_buff_size >> 1; *avail = bt_buff_size >> 1; +#endif } else { tr_err(&acp_bt_dma_tr, "Channel direction Not defined %d", channel->direction); diff --git a/src/drivers/amd/vangogh/acp_dma.c b/src/drivers/amd/vangogh/acp_dma.c index aed98db5726d..1f37dd828118 100644 --- a/src/drivers/amd/vangogh/acp_dma.c +++ b/src/drivers/amd/vangogh/acp_dma.c @@ -73,6 +73,26 @@ void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes) dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); dma_cfg->rd_size = 0; } + /* Check for wrap-around case for host buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->size) { + tail = dma_cfg->size - dma_cfg->wr_size; + head = bytes - tail; + + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + + /* start from "0" like starting address of buffer */ + psrc_dscr[strt_idx + 1].dest_addr = + ((dma_cfg->base & ACP_DRAM_ADDRESS_MASK) | ACP_DRAM_ADDR_TRNS); + + src1 = src + tail; + psrc_dscr[strt_idx + 1].src_addr = src1; + + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + dma_cfg->rd_size += head; dma_cfg->rd_size %= dma_cfg->sys_buff_size; dma_cfg->wr_size += bytes; @@ -197,28 +217,34 @@ int dma_setup(struct dma_chan_data *channel, tc = dma_config_dscr[dscr_strt_idx].trns_cnt.bits.trns_cnt; /* DMA configuration for stream */ if (channel->index != DMA_TRACE_CHANNEL) { - acp_dma_chan->dir = dir; - acp_dma_chan->idx = channel->index; - dma_cfg->phy_off = phy_off[channel->index]; - dma_cfg->size = tc * dscr_cnt; - dma_cfg->sys_buff_size = syst_buff_size[channel->index]; + if (!dma_cfg->size) { + acp_dma_chan->dir = dir; + acp_dma_chan->idx = channel->index; + dma_cfg->phy_off = phy_off[channel->index]; + dma_cfg->size = tc * dscr_cnt; + dma_cfg->sys_buff_size = syst_buff_size[channel->index]; - if (dir == DMA_DIR_HMEM_TO_LMEM) { - /* Playback */ - dma_config_dscr[dscr_strt_idx].dest_addr = - (dma_config_dscr[dscr_strt_idx].dest_addr & ACP_DRAM_ADDRESS_MASK); - dma_cfg->base = - dma_config_dscr[dscr_strt_idx].dest_addr | ACP_DRAM_ADDR_TRNS; - dma_cfg->wr_size = 0; - dma_cfg->rd_size = dma_cfg->size; - } else { - /* Capture */ - dma_config_dscr[dscr_strt_idx].src_addr = - (dma_config_dscr[dscr_strt_idx].src_addr & ACP_DRAM_ADDRESS_MASK); - dma_cfg->base = - dma_config_dscr[dscr_strt_idx].src_addr | ACP_DRAM_ADDR_TRNS; - dma_cfg->wr_size = dma_cfg->size; - dma_cfg->rd_size = 0; + if (dir == DMA_DIR_HMEM_TO_LMEM) { + /* Playback */ + dma_config_dscr[dscr_strt_idx].dest_addr = + (dma_config_dscr[dscr_strt_idx].dest_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = + dma_config_dscr[dscr_strt_idx].dest_addr | + ACP_DRAM_ADDR_TRNS; + dma_cfg->wr_size = 0; + dma_cfg->rd_size = dma_cfg->size; + } else { + /* Capture */ + dma_config_dscr[dscr_strt_idx].src_addr = + (dma_config_dscr[dscr_strt_idx].src_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = + dma_config_dscr[dscr_strt_idx].src_addr | + ACP_DRAM_ADDR_TRNS; + dma_cfg->wr_size = dma_cfg->size; + dma_cfg->rd_size = 0; + } } } /* clear the dma channel control bits */ @@ -246,7 +272,7 @@ int acp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) switch (type) { case DMA_ATTR_BUFFER_ALIGNMENT: case DMA_ATTR_COPY_ALIGNMENT: - *value = ACP_DMA_BUFFER_ALIGN_128; + *value = ACP_DMA_BUFFER_ALIGN; break; case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: *value = PLATFORM_DCACHE_ALIGN; diff --git a/src/drivers/amd/vangogh/acp_hs_dma.c b/src/drivers/amd/vangogh/acp_hs_dma.c index 1244482cf354..9059af896e7d 100644 --- a/src/drivers/amd/vangogh/acp_hs_dma.c +++ b/src/drivers/amd/vangogh/acp_hs_dma.c @@ -326,27 +326,40 @@ static int acp_dai_hs_dma_remove(struct dma *dma) static int acp_dai_hs_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_HS_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > hs_buff_size ? + (curr_tx_pos - prev_tx_pos) % hs_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = hs_buff_size - *free; prev_tx_pos = curr_tx_pos; +#else *free = (hs_buff_size >> 1); *avail = (hs_buff_size >> 1); +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_HS_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > hs_buff_size ? + (curr_rx_pos - prev_rx_pos) % hs_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = hs_buff_size - *free; prev_rx_pos = curr_rx_pos; +#else *free = (hs_buff_size >> 1); *avail = (hs_buff_size >> 1); +#endif } else { tr_err(&acp_hs_tr, "Channel direction not defined %d", channel->direction); return -EINVAL; diff --git a/src/drivers/amd/vangogh/acp_sp_dma.c b/src/drivers/amd/vangogh/acp_sp_dma.c index 00b2dce064b5..8d8d9c7e4f6b 100644 --- a/src/drivers/amd/vangogh/acp_sp_dma.c +++ b/src/drivers/amd/vangogh/acp_sp_dma.c @@ -213,29 +213,42 @@ int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint64_t tx_low, curr_tx_pos, tx_high; - uint64_t rx_low, curr_rx_pos, rx_high; - if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW); tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > sp_buff_size ? + (curr_tx_pos - prev_tx_pos) % sp_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = sp_buff_size - *free; prev_tx_pos = curr_tx_pos; +#else //TODO timer-based scheduling *free = (sp_buff_size >> 1); *avail = (sp_buff_size >> 1); +#endif } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW); rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > sp_buff_size ? + (curr_rx_pos - prev_rx_pos) % sp_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = sp_buff_size - *free; prev_rx_pos = curr_rx_pos; +#else //TODO timer-based scheduling *free = (sp_buff_size >> 1); *avail = (sp_buff_size >> 1); +#endif } else { tr_err(&acp_sp_vgh_tr, "Channel direction not defined %d", channel->direction); return -EINVAL;