summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorHardik T Shah <hardik.t.shah@intel.com>2017-03-24 20:40:32 +0300
committerMark Brown <broonie@kernel.org>2017-03-29 14:53:39 +0300
commitfdd85a054b850db43c6abe39c1da28b581be5e93 (patch)
tree32c288f9d0d1c97831b2c1c3a8e2fe30148343b1 /sound
parentb26199eae86f7a1c2363d049249c3be33694f93b (diff)
downloadlinux-fdd85a054b850db43c6abe39c1da28b581be5e93.tar.xz
ASoC: Intel: Skylake: Fix DMA position reporting for capture stream
As per hardware recommendation, for every capture stream completion following operations need to be done in order to reflect the actual data that is received in position buffer. 1. Wait for 20us before reading the DMA position in buffer once the interrupt is generated for stream completion. 2. Read any of the register to flush the DMA position value. This is dummy read operation. Signed-off-by: Dharageswari R <dharageswari.r@intel.com> Signed-off-by: Hardik T Shah <hardik.t.shah@intel.com> Signed-off-by: Jeeja KP <jeeja.kp@intel.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c
index ef440d8629e8..1823197c15c8 100644
--- a/sound/soc/intel/skylake/skl-pcm.c
+++ b/sound/soc/intel/skylake/skl-pcm.c
@@ -21,6 +21,7 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
+#include <linux/delay.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "skl.h"
@@ -1063,13 +1064,31 @@ static snd_pcm_uframes_t skl_platform_pcm_pointer
* HAD space reflects the actual data that is transferred.
* Use the position buffer for capture, as DPIB write gets
* completed earlier than the actual data written to the DDR.
+ *
+ * For capture stream following workaround is required to fix the
+ * incorrect position reporting.
+ *
+ * 1. Wait for 20us before reading the DMA position in buffer once
+ * the interrupt is generated for stream completion as update happens
+ * on the HDA frame boundary i.e. 20.833uSec.
+ * 2. Read DPIB register to flush the DMA position value. This dummy
+ * read is required to flush DMA position value.
+ * 3. Read the DMA Position-in-Buffer. This value now will be equal to
+ * or greater than period boundary.
*/
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pos = readl(ebus->bus.remap_addr + AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hdac_stream(hstream)->index));
- else
+ } else {
+ udelay(20);
+ readl(ebus->bus.remap_addr +
+ AZX_REG_VS_SDXDPIB_XBASE +
+ (AZX_REG_VS_SDXDPIB_XINTERVAL *
+ hdac_stream(hstream)->index));
pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
+ }
if (pos >= hdac_stream(hstream)->bufsize)
pos = 0;