Skip to content

Commit

Permalink
platform: amd: Add support for One Shot DMA configuration
Browse files Browse the repository at this point in the history
Support for One Shot DMA configuration for AMD Platforms.

Signed-off-by: BANDA MADHU <[email protected]>
  • Loading branch information
bandamadhu authored and kv2019i committed Nov 13, 2023
1 parent 925a486 commit dc6770d
Show file tree
Hide file tree
Showing 14 changed files with 274 additions and 99 deletions.
6 changes: 6 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/audio/host-legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 11 additions & 17 deletions src/drivers/amd/common/acp_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down
20 changes: 17 additions & 3 deletions src/drivers/amd/rembrandt/acp_bt_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
64 changes: 44 additions & 20 deletions src/drivers/amd/rembrandt/acp_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
19 changes: 16 additions & 3 deletions src/drivers/amd/rembrandt/acp_hs_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 16 additions & 3 deletions src/drivers/amd/rembrandt/acp_sp_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
20 changes: 17 additions & 3 deletions src/drivers/amd/renoir/acp_bt_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit dc6770d

Please sign in to comment.