diff options
author | Tomasz Figa <tomasz.figa@gmail.com> | 2013-08-11 19:59:21 +0200 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-08-08 15:19:34 +0900 |
commit | fb94b1b349c25305f0b3ac31acd2fedaa4e23121 (patch) | |
tree | d041e42367f5634e53df548cf3d0efdfac7741c7 /sound | |
parent | 6fc852cce56b85bcef6086a4e509d5705f24409a (diff) | |
download | linux-3.10-fb94b1b349c25305f0b3ac31acd2fedaa4e23121.tar.gz linux-3.10-fb94b1b349c25305f0b3ac31acd2fedaa4e23121.tar.bz2 linux-3.10-fb94b1b349c25305f0b3ac31acd2fedaa4e23121.zip |
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.
Change-Id: Ib9e656c40ef71e2e90af3f008959eeae19ce7d7e
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')
-rw-r--r-- | sound/soc/samsung/dma.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index 21b79262010..6e2b2b4dca5 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); |