summaryrefslogtreecommitdiff
path: root/sound/soc/tegra/tegra_pcm.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-04-19 14:23:53 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:43:19 -0800
commite04e8672a0d90fddf2519aa9f845c5db38baa787 (patch)
tree7a42034b5a7315a6fecb14da97684e3b769b061b /sound/soc/tegra/tegra_pcm.c
parent79911866d84738242f547120ebe4eac3d42bf69d (diff)
CHROMIUM: ASoC: Tegra: Double-buffer DMA in HW
Avoid audio FIFO underflow due to DMA ISR latency. MODE_ONESHOT works like this: * CPU tells DMA HW to make a transfer . * DMA HW performs the transfer, fires an interrupt, and goes idle. * Interrupt latency (including e.g. LP2 exit time) is seen here. * DMA driver ISR programs the next transfer, from a SW transfer queue. In that model, the interrupt latency must be hidden by the I2S FIFO, which is 16 samples IIRC, i.e. a very short time (~0.3mS @ 48KHz). MODE_CONTINUOUS_SINGLE works like this: * CPU tells DMA HW to make a transfer . * CPU tells DMA HW to make a second transfer. * DMA HW performs the transfer, fires an interrupt, and starts the second transfer immediately. * DMA driver ISR programs the next (third) transfer, while the second is in progress, from a SW transfer queue. Thus any DMA ISR latency is seen between transfer N completing and transfer N+2 starting (rather than N+1), since the HW itself already knows how to perform transfer N+1 before transfer N completes. Hence, the system is tolerant of much larger latencies. BUG=chromium-os-partner:3294 TEST=Seaboard clamshell: "aplay sin-500hz-48000-60s.wav" multiple times while system idle and power LED flickering indicating CPU power saving. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Olof Johansson <olofj@chromium.org> Rebase-Id: R4063e2abdf57f47ebe4dc63488056268747bea82
Diffstat (limited to 'sound/soc/tegra/tegra_pcm.c')
-rw-r--r--sound/soc/tegra/tegra_pcm.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index b265c2e0ad0d..d0d9f730018f 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -161,7 +161,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
prtd->dma_req[1].dev = prtd;
prtd->dma_chan = tegra_dma_allocate_channel(
- TEGRA_DMA_MODE_ONESHOT, "pcm");
+ TEGRA_DMA_MODE_CONTINUOUS_SINGLE, "pcm");
if (prtd->dma_chan == NULL) {
ret = -ENOMEM;
goto err;