summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2011-04-19 14:23:53 -0700
committerStephen Warren <swarren@nvidia.com>2011-08-04 22:57:53 -0600
commit890e3f0efe94eca870c836b2df4f6478a2c40c0b (patch)
tree687f038735f4db0c998301cf2904e157184dbbea /sound
parent2e39114fff798e8904f4c51877ff426799bf0101 (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>
Diffstat (limited to 'sound')
-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 4524b0f88ef8..dde24b42483b 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;