aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0221-drm-amdgpu-implement-VCE-two-instances-support.patch
blob: 91a563db34334f20a7ef33a7bbe05633acd1453e (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
From 5bbc553a1acce5d1792ba778273ffbea5af1695d Mon Sep 17 00:00:00 2001
From: Leo Liu <leo.liu@amd.com>
Date: Wed, 6 May 2015 15:20:41 -0400
Subject: [PATCH 0221/1050] drm/amdgpu: implement VCE two instances support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

VCE 3.0 has two indentical instances in the engine, they share
the same registers name in differrent memory block distinguished
by the grbm_gfx_index, we set to master instance after init, it
will dispatch task to slave instance. These two instances will
share the same firmware, but have their own stacks and heaps.

v2: add mutex for using grbm_gfx_index

Signed-off-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 141 +++++++++++++++++++++-------------
 1 file changed, 87 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index ee29436f..57e0e16 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -34,12 +34,16 @@
 #include "vce/vce_3_0_sh_mask.h"
 #include "oss/oss_2_0_d.h"
 #include "oss/oss_2_0_sh_mask.h"
+#include "gca/gfx_8_0_d.h"
+
+#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
+#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
 
 #define VCE_V3_0_FW_SIZE	(384 * 1024)
 #define VCE_V3_0_STACK_SIZE	(64 * 1024)
 #define VCE_V3_0_DATA_SIZE	((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))
 
-static void vce_v3_0_mc_resume(struct amdgpu_device *adev);
+static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
 
@@ -104,12 +108,70 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
 static int vce_v3_0_start(struct amdgpu_device *adev)
 {
 	struct amdgpu_ring *ring;
-	int i, j, r;
+	int idx, i, j, r;
+
+	mutex_lock(&adev->grbm_idx_mutex);
+	for (idx = 0; idx < 2; ++idx) {
+		if(idx == 0)
+			WREG32_P(mmGRBM_GFX_INDEX, 0,
+				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
+		else
+			WREG32_P(mmGRBM_GFX_INDEX,
+				GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
+				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
+
+		vce_v3_0_mc_resume(adev, idx);
+
+		/* set BUSY flag */
+		WREG32_P(mmVCE_STATUS, 1, ~1);
+
+		WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
+			~VCE_VCPU_CNTL__CLK_EN_MASK);
+
+		WREG32_P(mmVCE_SOFT_RESET,
+			 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
+			 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
+
+		mdelay(100);
+
+		WREG32_P(mmVCE_SOFT_RESET, 0,
+			~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
+
+		for (i = 0; i < 10; ++i) {
+			uint32_t status;
+			for (j = 0; j < 100; ++j) {
+				status = RREG32(mmVCE_STATUS);
+				if (status & 2)
+					break;
+				mdelay(10);
+			}
+			r = 0;
+			if (status & 2)
+				break;
+
+			DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
+			WREG32_P(mmVCE_SOFT_RESET,
+				VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
+				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
+			mdelay(10);
+			WREG32_P(mmVCE_SOFT_RESET, 0,
+				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
+			mdelay(10);
+			r = -1;
+		}
+
+		/* clear BUSY flag */
+		WREG32_P(mmVCE_STATUS, 0, ~1);
 
-	vce_v3_0_mc_resume(adev);
+		if (r) {
+			DRM_ERROR("VCE not responding, giving up!!!\n");
+			mutex_unlock(&adev->grbm_idx_mutex);
+			return r;
+		}
+	}
 
-	/* set BUSY flag */
-	WREG32_P(mmVCE_STATUS, 1, ~1);
+	WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
+	mutex_unlock(&adev->grbm_idx_mutex);
 
 	ring = &adev->vce.ring[0];
 	WREG32(mmVCE_RB_RPTR, ring->wptr);
@@ -125,45 +187,6 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
 	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
 	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
 
-	WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK);
-
-	WREG32_P(mmVCE_SOFT_RESET,
-		 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
-		 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
-
-	mdelay(100);
-
-	WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
-
-	for (i = 0; i < 10; ++i) {
-		uint32_t status;
-		for (j = 0; j < 100; ++j) {
-			status = RREG32(mmVCE_STATUS);
-			if (status & 2)
-				break;
-			mdelay(10);
-		}
-		r = 0;
-		if (status & 2)
-			break;
-
-		DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
-		WREG32_P(mmVCE_SOFT_RESET, VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
-				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
-		mdelay(10);
-		WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
-		mdelay(10);
-		r = -1;
-	}
-
-	/* clear BUSY flag */
-	WREG32_P(mmVCE_STATUS, 0, ~1);
-
-	if (r) {
-		DRM_ERROR("VCE not responding, giving up!!!\n");
-		return r;
-	}
-
 	return 0;
 }
 
@@ -292,7 +315,7 @@ static int vce_v3_0_resume(struct amdgpu_device *adev)
 	return r;
 }
 
-static void vce_v3_0_mc_resume(struct amdgpu_device *adev)
+static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
 {
 	uint32_t offset, size;
 
@@ -313,15 +336,25 @@ static void vce_v3_0_mc_resume(struct amdgpu_device *adev)
 	WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
 	WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
 
-	offset += size;
-	size = VCE_V3_0_STACK_SIZE;
-	WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
-	WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
-
-	offset += size;
-	size = VCE_V3_0_DATA_SIZE;
-	WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
-	WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
+	if (idx == 0) {
+		offset += size;
+		size = VCE_V3_0_STACK_SIZE;
+		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
+		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
+		offset += size;
+		size = VCE_V3_0_DATA_SIZE;
+		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
+		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
+	} else {
+		offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
+		size = VCE_V3_0_STACK_SIZE;
+		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
+		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
+		offset += size;
+		size = VCE_V3_0_DATA_SIZE;
+		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
+		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
+	}
 
 	WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
 
-- 
1.9.1