summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorAkshu Agrawal <akshu.agrawal@amd.com>2018-09-10 04:06:30 -0400
committerMark Brown <broonie@kernel.org>2018-09-10 07:20:52 -0400
commit2a665dba016d5493c7d826fec82b0cb643b30d42 (patch)
tree40d1b5d7a8266516c8bf0eb7feae21a72ae98913 /sound
parent6c92d5a2744e27619a8fcc9d74b91ee9f1cdebd1 (diff)
ASoC: AMD: Ensure reset bit is cleared before configuring
HW register descriptions says: "DMA Channel Reset...Software must confirm that this bit is cleared before reprogramming any of the channel configuration registers." There could be cases where dma stop errored out leaving dma channel in reset state. We need to ensure that before the start of another dma, channel is out of the reset state. Signed-off-by: Akshu Agrawal <akshu.agrawal@amd.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/amd/acp-pcm-dma.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index e359938e3d7e..77b265bd0505 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -16,6 +16,7 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/iopoll.h>
19#include <linux/sizes.h> 20#include <linux/sizes.h>
20#include <linux/pm_runtime.h> 21#include <linux/pm_runtime.h>
21 22
@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
184 acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data); 185 acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
185} 186}
186 187
188static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
189{
190 u32 dma_ctrl;
191 int ret;
192
193 /* clear the reset bit */
194 dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
195 dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
196 acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
197 /* check the reset bit before programming configuration registers */
198 ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4),
199 dma_ctrl,
200 !(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK),
201 100, ACP_DMA_RESET_TIME);
202 if (ret < 0)
203 pr_err("Failed to clear reset of channel : %d\n", ch_num);
204}
205
187/* 206/*
188 * Initialize the DMA descriptor information for transfer between 207 * Initialize the DMA descriptor information for transfer between
189 * system memory <-> ACP SRAM 208 * system memory <-> ACP SRAM
@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
236 config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, 255 config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
237 &dmadscr[i]); 256 &dmadscr[i]);
238 } 257 }
258 pre_config_reset(acp_mmio, ch);
239 config_acp_dma_channel(acp_mmio, ch, 259 config_acp_dma_channel(acp_mmio, ch,
240 dma_dscr_idx - 1, 260 dma_dscr_idx - 1,
241 NUM_DSCRS_PER_CHANNEL, 261 NUM_DSCRS_PER_CHANNEL,
@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
275 config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, 295 config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
276 &dmadscr[i]); 296 &dmadscr[i]);
277 } 297 }
298 pre_config_reset(acp_mmio, ch);
278 /* Configure the DMA channel with the above descriptore */ 299 /* Configure the DMA channel with the above descriptore */
279 config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1, 300 config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
280 NUM_DSCRS_PER_CHANNEL, 301 NUM_DSCRS_PER_CHANNEL,