|
@@ -1031,10 +1031,24 @@ static snd_pcm_uframes_t skl_platform_pcm_pointer
|
|
|
(struct snd_pcm_substream *substream)
|
|
|
{
|
|
|
struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
|
|
|
+ struct hdac_ext_bus *ebus = get_bus_ctx(substream);
|
|
|
unsigned int pos;
|
|
|
|
|
|
- /* use the position buffer as default */
|
|
|
- pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
|
|
|
+ /*
|
|
|
+ * Use DPIB for Playback stream as the periodic DMA Position-in-
|
|
|
+ * Buffer Writes may be scheduled at the same time or later than
|
|
|
+ * the MSI and does not guarantee to reflect the Position of the
|
|
|
+ * last buffer that was transferred. Whereas DPIB register in
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+ 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
|
|
|
+ pos = snd_hdac_stream_get_pos_posbuf(hdac_stream(hstream));
|
|
|
|
|
|
if (pos >= hdac_stream(hstream)->bufsize)
|
|
|
pos = 0;
|