diff options
author | Stephen Warren <swarren@nvidia.com> | 2011-04-19 14:23:53 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:43:19 -0800 |
commit | e04e8672a0d90fddf2519aa9f845c5db38baa787 (patch) | |
tree | 7a42034b5a7315a6fecb14da97684e3b769b061b /sound/soc/tegra/tegra_pcm.c | |
parent | 79911866d84738242f547120ebe4eac3d42bf69d (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.c | 2 |
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; |