diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/5727-amd-i2s-dma-pointer-uses-Link-position-counter.This-.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/5727-amd-i2s-dma-pointer-uses-Link-position-counter.This-.patch | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/5727-amd-i2s-dma-pointer-uses-Link-position-counter.This-.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/5727-amd-i2s-dma-pointer-uses-Link-position-counter.This-.patch new file mode 100644 index 00000000..3ce63541 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/5727-amd-i2s-dma-pointer-uses-Link-position-counter.This-.patch @@ -0,0 +1,117 @@ +From e0c036d4aad50e29f3a2217324e4faf729f59839 Mon Sep 17 00:00:00 2001 +From: Sudheesh Mavila <sudheesh.mavila@amd.com> +Date: Tue, 8 Jan 2019 12:05:52 +0530 +Subject: [PATCH 5727/5758] amd-i2s dma pointer uses Link position counter.This + has been changed to Linear position counter and this rectifies underruns. + +Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com> +--- + sound/soc/amd/raven/acp3x-pcm-dma.c | 64 ++++++++++++++++++++++++++++++------- + 1 file changed, 53 insertions(+), 11 deletions(-) + +diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c +index 3abdf1f..3bb4ad3 100755 +--- a/sound/soc/amd/raven/acp3x-pcm-dma.c ++++ b/sound/soc/amd/raven/acp3x-pcm-dma.c +@@ -37,12 +37,24 @@ struct i2s_dev_data { + struct snd_pcm_substream *capture_stream; + }; + ++union acp3x_dma_count { ++ struct { ++ u32 low; ++ u32 high; ++ } bcount; ++ u64 bytescount; ++}; ++ ++ + struct i2s_stream_instance { + u16 num_pages; + u16 channels; + u32 xfer_resolution; + u32 val; + dma_addr_t dma_addr; ++ u32 byte_cnt_high_reg_offset; ++ u32 byte_cnt_low_reg_offset; ++ u64 bytescount; + void __iomem *acp3x_base; + }; + +@@ -335,6 +347,25 @@ static int acp3x_dma_open(struct snd_pcm_substream *substream) + return 0; + } + ++static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction) ++{ ++ union acp3x_dma_count byte_count; ++ ++ if (direction == SNDRV_PCM_STREAM_PLAYBACK) { ++ byte_count.bcount.high = rv_readl(rtd->acp3x_base + ++ mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); ++ byte_count.bcount.low = rv_readl(rtd->acp3x_base + ++ mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); ++ } else { ++ byte_count.bcount.high = rv_readl(rtd->acp3x_base + ++ mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); ++ byte_count.bcount.low = rv_readl(rtd->acp3x_base + ++ mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); ++ } ++ return byte_count.bytescount; ++} ++ ++ + static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) + { +@@ -366,18 +397,28 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, + + static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream) + { ++ u64 bytescount = 0; + u32 pos = 0; +- struct i2s_stream_instance *rtd = substream->runtime->private_data; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- pos = rv_readl(rtd->acp3x_base + +- mmACP_BT_TX_LINKPOSITIONCNTR); +- else +- pos = rv_readl(rtd->acp3x_base + +- mmACP_BT_RX_LINKPOSITIONCNTR); +- +- if (pos >= MAX_BUFFER) +- pos = 0; ++ u32 buffersize = 0; ++ struct i2s_stream_instance *rtd = ++ substream->runtime->private_data; ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ buffersize = frames_to_bytes(substream->runtime, ++ substream->runtime->buffer_size); ++ bytescount = acp_get_byte_count(rtd, substream->stream); ++ if (bytescount > rtd->bytescount) ++ bytescount -= rtd->bytescount; ++ pos = do_div(bytescount, buffersize); ++ } else { ++ buffersize = frames_to_bytes(substream->runtime, ++ substream->runtime->buffer_size); ++ bytescount = acp_get_byte_count(rtd, substream->stream); ++ if (bytescount > rtd->bytescount) ++ bytescount -= rtd->bytescount; ++ pos = do_div(bytescount, buffersize); ++ } ++ if (pos >= MAX_BUFFER) ++ pos %= buffersize; + + return bytes_to_frames(substream->runtime, pos); + } +@@ -545,6 +586,7 @@ static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream, + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ rtd->bytescount = acp_get_byte_count(rtd, substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER); + val = val | BIT(0); +-- +2.7.4 + |