aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/5727-amd-i2s-dma-pointer-uses-Link-position-counter.This-.patch
blob: 3ce63541f67a3e98859105a6405e14d98af904e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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