summaryrefslogtreecommitdiff
path: root/sound/soc/samsung
diff options
context:
space:
mode:
authorTomasz Figa <tomasz.figa@gmail.com>2013-08-11 21:59:21 +0400
committerMark Brown <broonie@linaro.org>2013-08-29 20:31:02 +0400
commit9b9ae16a97e08bdc4fd5e726a4d17119dbae5d8a (patch)
tree560f45835378128d12f4c4a54365d2eb04464aec /sound/soc/samsung
parent06b10ff913f4d6b3e659e365ce5f70e82cca353c (diff)
downloadlinux-9b9ae16a97e08bdc4fd5e726a4d17119dbae5d8a.tar.xz
ASoC: Samsung: Do not queue cyclic buffers multiple times
The legacy S3C-DMA API required every period of a cyclic buffer to be queued separately. After conversion of Samsung ASoC to Samsung DMA wrappers somebody made an assumption that the same is needed for DMA engine API, which is not true. In effect, Samsung ASoC DMA code was queuing the whole cyclic buffer multiple times with a shift of one period per iteration, leading to: a) severe memory waste - up to 13x times more DMA transfer descriptors are allocated than needed, b) possible memory corruption, because further cyclic buffers were out of the original buffers, due to the offset. This patch fixes this problem by making the legacy S3C-DMA API use the same semantics as DMA engine (the whole cyclic buffer is enqueued at once) and modifying users of Samsung DMA wrappers in cyclic mode to behave appropriately. Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/samsung')
-rw-r--r--sound/soc/samsung/dma.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index a0c67f60f594..9338d11e9216 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -90,6 +90,13 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
dma_info.period = prtd->dma_period;
dma_info.len = prtd->dma_period*limit;
+ if (dma_info.cap == DMA_CYCLIC) {
+ dma_info.buf = pos;
+ prtd->params->ops->prepare(prtd->params->ch, &dma_info);
+ prtd->dma_loaded += limit;
+ return;
+ }
+
while (prtd->dma_loaded < limit) {
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);