summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorMohan Kumar <mkumard@nvidia.com>2020-08-05 11:52:21 +0200
committerTakashi Iwai <tiwai@suse.de>2020-08-05 12:28:14 +0200
commited4d0a4aaf568a4694f6b85c534f31fcb9d7cfbf (patch)
tree9433188cc6381c580f9df8e4fe669a3d80b1617a /sound/pci
parentALSA: hda: Add dma stop delay variable (diff)
downloadlinux-ed4d0a4aaf568a4694f6b85c534f31fcb9d7cfbf.tar.xz
linux-ed4d0a4aaf568a4694f6b85c534f31fcb9d7cfbf.zip
ALSA: hda/tegra: Add 100us dma stop delay
Tegra HDA has audio data buffer for upto tens of frames, this buffer can help to avoid underflow. HW will keep issuing new data fetch request when buffers are not full and current BDL is not done. When SW disable DMA RUN bit for a stream, HW can't cancel the already issued data fetch request and hence it can't stop DMA. HW has to wait for all issued data fetch request get data returned before it stops DMA. This HW behavior is not in sync with HDA spec which says DMA RUN bit should be cleared within 1 audio frame. For Tegra, DMA RUN bit was active for more than one audio frame, due to this the timeout in snd_hdac_stream_sync function is not helping. When Stream reset set and clear happens during DMA RUN bit active state it results in Memory Decode error. Unfortunately, there is no way to detect when these data accesses have completed, but testing has shown that a 100us delay between Stream reset set and clear operation for Tegra avoids the memory decode error. Therefore, adding a 100us dma stop delay. Signed-off-by: Mohan Kumar <mkumard@nvidia.com> Link: https://lore.kernel.org/r/20200805095221.5476-4-mkumard@nvidia.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_tegra.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index ecf98eb9df36..c94553bcca88 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -308,6 +308,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
return err;
}
bus->irq = irq_id;
+ bus->dma_stop_delay = 100;
card->sync_irq = bus->irq;
/*