• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * The above copyright notice and this permission notice (including the
22  * next paragraph) shall be included in all copies or substantial portions
23  * of the Software.
24  *
25  * Authors: Christian König <christian.koenig@amd.com>
26  */
27 
28 #include <linux/firmware.h>
29 #include <drm/drmP.h>
30 #include "amdgpu.h"
31 #include "amdgpu_vce.h"
32 #include "vid.h"
33 #include "vce/vce_3_0_d.h"
34 #include "vce/vce_3_0_sh_mask.h"
35 #include "oss/oss_3_0_d.h"
36 #include "oss/oss_3_0_sh_mask.h"
37 #include "gca/gfx_8_0_d.h"
38 #include "smu/smu_7_1_2_d.h"
39 #include "smu/smu_7_1_2_sh_mask.h"
40 
41 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
42 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
43 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0 	0x8616
44 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1 	0x8617
45 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2 	0x8618
46 
47 #define VCE_V3_0_FW_SIZE	(384 * 1024)
48 #define VCE_V3_0_STACK_SIZE	(64 * 1024)
49 #define VCE_V3_0_DATA_SIZE	((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))
50 
51 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
52 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
53 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
54 
55 /**
56  * vce_v3_0_ring_get_rptr - get read pointer
57  *
58  * @ring: amdgpu_ring pointer
59  *
60  * Returns the current hardware read pointer
61  */
vce_v3_0_ring_get_rptr(struct amdgpu_ring * ring)62 static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
63 {
64 	struct amdgpu_device *adev = ring->adev;
65 
66 	if (ring == &adev->vce.ring[0])
67 		return RREG32(mmVCE_RB_RPTR);
68 	else
69 		return RREG32(mmVCE_RB_RPTR2);
70 }
71 
72 /**
73  * vce_v3_0_ring_get_wptr - get write pointer
74  *
75  * @ring: amdgpu_ring pointer
76  *
77  * Returns the current hardware write pointer
78  */
vce_v3_0_ring_get_wptr(struct amdgpu_ring * ring)79 static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
80 {
81 	struct amdgpu_device *adev = ring->adev;
82 
83 	if (ring == &adev->vce.ring[0])
84 		return RREG32(mmVCE_RB_WPTR);
85 	else
86 		return RREG32(mmVCE_RB_WPTR2);
87 }
88 
89 /**
90  * vce_v3_0_ring_set_wptr - set write pointer
91  *
92  * @ring: amdgpu_ring pointer
93  *
94  * Commits the write pointer to the hardware
95  */
vce_v3_0_ring_set_wptr(struct amdgpu_ring * ring)96 static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
97 {
98 	struct amdgpu_device *adev = ring->adev;
99 
100 	if (ring == &adev->vce.ring[0])
101 		WREG32(mmVCE_RB_WPTR, ring->wptr);
102 	else
103 		WREG32(mmVCE_RB_WPTR2, ring->wptr);
104 }
105 
106 /**
107  * vce_v3_0_start - start VCE block
108  *
109  * @adev: amdgpu_device pointer
110  *
111  * Setup and start the VCE block
112  */
vce_v3_0_start(struct amdgpu_device * adev)113 static int vce_v3_0_start(struct amdgpu_device *adev)
114 {
115 	struct amdgpu_ring *ring;
116 	int idx, i, j, r;
117 
118 	mutex_lock(&adev->grbm_idx_mutex);
119 	for (idx = 0; idx < 2; ++idx) {
120 
121 		if (adev->vce.harvest_config & (1 << idx))
122 			continue;
123 
124 		if(idx == 0)
125 			WREG32_P(mmGRBM_GFX_INDEX, 0,
126 				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
127 		else
128 			WREG32_P(mmGRBM_GFX_INDEX,
129 				GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
130 				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
131 
132 		vce_v3_0_mc_resume(adev, idx);
133 
134 		/* set BUSY flag */
135 		WREG32_P(mmVCE_STATUS, 1, ~1);
136 		if (adev->asic_type >= CHIP_STONEY)
137 			WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001);
138 		else
139 			WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
140 				~VCE_VCPU_CNTL__CLK_EN_MASK);
141 
142 		WREG32_P(mmVCE_SOFT_RESET,
143 			 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
144 			 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
145 
146 		mdelay(100);
147 
148 		WREG32_P(mmVCE_SOFT_RESET, 0,
149 			~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
150 
151 		for (i = 0; i < 10; ++i) {
152 			uint32_t status;
153 			for (j = 0; j < 100; ++j) {
154 				status = RREG32(mmVCE_STATUS);
155 				if (status & 2)
156 					break;
157 				mdelay(10);
158 			}
159 			r = 0;
160 			if (status & 2)
161 				break;
162 
163 			DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
164 			WREG32_P(mmVCE_SOFT_RESET,
165 				VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
166 				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
167 			mdelay(10);
168 			WREG32_P(mmVCE_SOFT_RESET, 0,
169 				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
170 			mdelay(10);
171 			r = -1;
172 		}
173 
174 		/* clear BUSY flag */
175 		WREG32_P(mmVCE_STATUS, 0, ~1);
176 
177 		if (r) {
178 			DRM_ERROR("VCE not responding, giving up!!!\n");
179 			mutex_unlock(&adev->grbm_idx_mutex);
180 			return r;
181 		}
182 	}
183 
184 	WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
185 	mutex_unlock(&adev->grbm_idx_mutex);
186 
187 	ring = &adev->vce.ring[0];
188 	WREG32(mmVCE_RB_RPTR, ring->wptr);
189 	WREG32(mmVCE_RB_WPTR, ring->wptr);
190 	WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
191 	WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
192 	WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
193 
194 	ring = &adev->vce.ring[1];
195 	WREG32(mmVCE_RB_RPTR2, ring->wptr);
196 	WREG32(mmVCE_RB_WPTR2, ring->wptr);
197 	WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
198 	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
199 	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
200 
201 	return 0;
202 }
203 
204 #define ixVCE_HARVEST_FUSE_MACRO__ADDRESS     0xC0014074
205 #define VCE_HARVEST_FUSE_MACRO__SHIFT       27
206 #define VCE_HARVEST_FUSE_MACRO__MASK        0x18000000
207 
vce_v3_0_get_harvest_config(struct amdgpu_device * adev)208 static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
209 {
210 	u32 tmp;
211 	unsigned ret;
212 
213 	/* Fiji, Stoney are single pipe */
214 	if ((adev->asic_type == CHIP_FIJI) ||
215 	    (adev->asic_type == CHIP_STONEY)){
216 		ret = AMDGPU_VCE_HARVEST_VCE1;
217 		return ret;
218 	}
219 
220 	/* Tonga and CZ are dual or single pipe */
221 	if (adev->flags & AMD_IS_APU)
222 		tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
223 		       VCE_HARVEST_FUSE_MACRO__MASK) >>
224 			VCE_HARVEST_FUSE_MACRO__SHIFT;
225 	else
226 		tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
227 		       CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
228 			CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;
229 
230 	switch (tmp) {
231 	case 1:
232 		ret = AMDGPU_VCE_HARVEST_VCE0;
233 		break;
234 	case 2:
235 		ret = AMDGPU_VCE_HARVEST_VCE1;
236 		break;
237 	case 3:
238 		ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
239 		break;
240 	default:
241 		ret = 0;
242 	}
243 
244 	return ret;
245 }
246 
vce_v3_0_early_init(void * handle)247 static int vce_v3_0_early_init(void *handle)
248 {
249 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
250 
251 	adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
252 
253 	if ((adev->vce.harvest_config &
254 	     (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
255 	    (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
256 		return -ENOENT;
257 
258 	vce_v3_0_set_ring_funcs(adev);
259 	vce_v3_0_set_irq_funcs(adev);
260 
261 	return 0;
262 }
263 
vce_v3_0_sw_init(void * handle)264 static int vce_v3_0_sw_init(void *handle)
265 {
266 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
267 	struct amdgpu_ring *ring;
268 	int r;
269 
270 	/* VCE */
271 	r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
272 	if (r)
273 		return r;
274 
275 	r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
276 		(VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
277 	if (r)
278 		return r;
279 
280 	r = amdgpu_vce_resume(adev);
281 	if (r)
282 		return r;
283 
284 	ring = &adev->vce.ring[0];
285 	sprintf(ring->name, "vce0");
286 	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
287 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
288 	if (r)
289 		return r;
290 
291 	ring = &adev->vce.ring[1];
292 	sprintf(ring->name, "vce1");
293 	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
294 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
295 	if (r)
296 		return r;
297 
298 	return r;
299 }
300 
vce_v3_0_sw_fini(void * handle)301 static int vce_v3_0_sw_fini(void *handle)
302 {
303 	int r;
304 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
305 
306 	r = amdgpu_vce_suspend(adev);
307 	if (r)
308 		return r;
309 
310 	r = amdgpu_vce_sw_fini(adev);
311 	if (r)
312 		return r;
313 
314 	return r;
315 }
316 
vce_v3_0_hw_init(void * handle)317 static int vce_v3_0_hw_init(void *handle)
318 {
319 	struct amdgpu_ring *ring;
320 	int r;
321 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
322 
323 	r = vce_v3_0_start(adev);
324 	if (r)
325 		return r;
326 
327 	ring = &adev->vce.ring[0];
328 	ring->ready = true;
329 	r = amdgpu_ring_test_ring(ring);
330 	if (r) {
331 		ring->ready = false;
332 		return r;
333 	}
334 
335 	ring = &adev->vce.ring[1];
336 	ring->ready = true;
337 	r = amdgpu_ring_test_ring(ring);
338 	if (r) {
339 		ring->ready = false;
340 		return r;
341 	}
342 
343 	DRM_INFO("VCE initialized successfully.\n");
344 
345 	return 0;
346 }
347 
vce_v3_0_hw_fini(void * handle)348 static int vce_v3_0_hw_fini(void *handle)
349 {
350 	return 0;
351 }
352 
vce_v3_0_suspend(void * handle)353 static int vce_v3_0_suspend(void *handle)
354 {
355 	int r;
356 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
357 
358 	r = vce_v3_0_hw_fini(adev);
359 	if (r)
360 		return r;
361 
362 	r = amdgpu_vce_suspend(adev);
363 	if (r)
364 		return r;
365 
366 	return r;
367 }
368 
vce_v3_0_resume(void * handle)369 static int vce_v3_0_resume(void *handle)
370 {
371 	int r;
372 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
373 
374 	r = amdgpu_vce_resume(adev);
375 	if (r)
376 		return r;
377 
378 	r = vce_v3_0_hw_init(adev);
379 	if (r)
380 		return r;
381 
382 	return r;
383 }
384 
vce_v3_0_mc_resume(struct amdgpu_device * adev,int idx)385 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
386 {
387 	uint32_t offset, size;
388 
389 	WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
390 	WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
391 	WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
392 	WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
393 
394 	WREG32(mmVCE_LMI_CTRL, 0x00398000);
395 	WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
396 	WREG32(mmVCE_LMI_SWAP_CNTL, 0);
397 	WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
398 	WREG32(mmVCE_LMI_VM_CTRL, 0);
399 	if (adev->asic_type >= CHIP_STONEY) {
400 		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8));
401 		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8));
402 		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8));
403 	} else
404 		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
405 	offset = AMDGPU_VCE_FIRMWARE_OFFSET;
406 	size = VCE_V3_0_FW_SIZE;
407 	WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
408 	WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
409 
410 	if (idx == 0) {
411 		offset += size;
412 		size = VCE_V3_0_STACK_SIZE;
413 		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
414 		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
415 		offset += size;
416 		size = VCE_V3_0_DATA_SIZE;
417 		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
418 		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
419 	} else {
420 		offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
421 		size = VCE_V3_0_STACK_SIZE;
422 		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
423 		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
424 		offset += size;
425 		size = VCE_V3_0_DATA_SIZE;
426 		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
427 		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
428 	}
429 
430 	WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
431 
432 	WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK,
433 		 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
434 }
435 
vce_v3_0_is_idle(void * handle)436 static bool vce_v3_0_is_idle(void *handle)
437 {
438 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
439 	u32 mask = 0;
440 	int idx;
441 
442 	for (idx = 0; idx < 2; ++idx) {
443 		if (adev->vce.harvest_config & (1 << idx))
444 			continue;
445 
446 		if (idx == 0)
447 			mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
448 		else
449 			mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
450 	}
451 
452 	return !(RREG32(mmSRBM_STATUS2) & mask);
453 }
454 
vce_v3_0_wait_for_idle(void * handle)455 static int vce_v3_0_wait_for_idle(void *handle)
456 {
457 	unsigned i;
458 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
459 	u32 mask = 0;
460 	int idx;
461 
462 	for (idx = 0; idx < 2; ++idx) {
463 		if (adev->vce.harvest_config & (1 << idx))
464 			continue;
465 
466 		if (idx == 0)
467 			mask |= SRBM_STATUS2__VCE0_BUSY_MASK;
468 		else
469 			mask |= SRBM_STATUS2__VCE1_BUSY_MASK;
470 	}
471 
472 	for (i = 0; i < adev->usec_timeout; i++) {
473 		if (!(RREG32(mmSRBM_STATUS2) & mask))
474 			return 0;
475 	}
476 	return -ETIMEDOUT;
477 }
478 
vce_v3_0_soft_reset(void * handle)479 static int vce_v3_0_soft_reset(void *handle)
480 {
481 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
482 	u32 mask = 0;
483 	int idx;
484 
485 	for (idx = 0; idx < 2; ++idx) {
486 		if (adev->vce.harvest_config & (1 << idx))
487 			continue;
488 
489 		if (idx == 0)
490 			mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
491 		else
492 			mask |= SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
493 	}
494 	WREG32_P(mmSRBM_SOFT_RESET, mask,
495 		 ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
496 		   SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
497 	mdelay(5);
498 
499 	return vce_v3_0_start(adev);
500 }
501 
vce_v3_0_print_status(void * handle)502 static void vce_v3_0_print_status(void *handle)
503 {
504 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
505 
506 	dev_info(adev->dev, "VCE 3.0 registers\n");
507 	dev_info(adev->dev, "  VCE_STATUS=0x%08X\n",
508 		 RREG32(mmVCE_STATUS));
509 	dev_info(adev->dev, "  VCE_VCPU_CNTL=0x%08X\n",
510 		 RREG32(mmVCE_VCPU_CNTL));
511 	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
512 		 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
513 	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE0=0x%08X\n",
514 		 RREG32(mmVCE_VCPU_CACHE_SIZE0));
515 	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
516 		 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
517 	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE1=0x%08X\n",
518 		 RREG32(mmVCE_VCPU_CACHE_SIZE1));
519 	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
520 		 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
521 	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE2=0x%08X\n",
522 		 RREG32(mmVCE_VCPU_CACHE_SIZE2));
523 	dev_info(adev->dev, "  VCE_SOFT_RESET=0x%08X\n",
524 		 RREG32(mmVCE_SOFT_RESET));
525 	dev_info(adev->dev, "  VCE_RB_BASE_LO2=0x%08X\n",
526 		 RREG32(mmVCE_RB_BASE_LO2));
527 	dev_info(adev->dev, "  VCE_RB_BASE_HI2=0x%08X\n",
528 		 RREG32(mmVCE_RB_BASE_HI2));
529 	dev_info(adev->dev, "  VCE_RB_SIZE2=0x%08X\n",
530 		 RREG32(mmVCE_RB_SIZE2));
531 	dev_info(adev->dev, "  VCE_RB_RPTR2=0x%08X\n",
532 		 RREG32(mmVCE_RB_RPTR2));
533 	dev_info(adev->dev, "  VCE_RB_WPTR2=0x%08X\n",
534 		 RREG32(mmVCE_RB_WPTR2));
535 	dev_info(adev->dev, "  VCE_RB_BASE_LO=0x%08X\n",
536 		 RREG32(mmVCE_RB_BASE_LO));
537 	dev_info(adev->dev, "  VCE_RB_BASE_HI=0x%08X\n",
538 		 RREG32(mmVCE_RB_BASE_HI));
539 	dev_info(adev->dev, "  VCE_RB_SIZE=0x%08X\n",
540 		 RREG32(mmVCE_RB_SIZE));
541 	dev_info(adev->dev, "  VCE_RB_RPTR=0x%08X\n",
542 		 RREG32(mmVCE_RB_RPTR));
543 	dev_info(adev->dev, "  VCE_RB_WPTR=0x%08X\n",
544 		 RREG32(mmVCE_RB_WPTR));
545 	dev_info(adev->dev, "  VCE_CLOCK_GATING_A=0x%08X\n",
546 		 RREG32(mmVCE_CLOCK_GATING_A));
547 	dev_info(adev->dev, "  VCE_CLOCK_GATING_B=0x%08X\n",
548 		 RREG32(mmVCE_CLOCK_GATING_B));
549 	dev_info(adev->dev, "  VCE_UENC_CLOCK_GATING=0x%08X\n",
550 		 RREG32(mmVCE_UENC_CLOCK_GATING));
551 	dev_info(adev->dev, "  VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
552 		 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
553 	dev_info(adev->dev, "  VCE_SYS_INT_EN=0x%08X\n",
554 		 RREG32(mmVCE_SYS_INT_EN));
555 	dev_info(adev->dev, "  VCE_LMI_CTRL2=0x%08X\n",
556 		 RREG32(mmVCE_LMI_CTRL2));
557 	dev_info(adev->dev, "  VCE_LMI_CTRL=0x%08X\n",
558 		 RREG32(mmVCE_LMI_CTRL));
559 	dev_info(adev->dev, "  VCE_LMI_VM_CTRL=0x%08X\n",
560 		 RREG32(mmVCE_LMI_VM_CTRL));
561 	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL=0x%08X\n",
562 		 RREG32(mmVCE_LMI_SWAP_CNTL));
563 	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL1=0x%08X\n",
564 		 RREG32(mmVCE_LMI_SWAP_CNTL1));
565 	dev_info(adev->dev, "  VCE_LMI_CACHE_CTRL=0x%08X\n",
566 		 RREG32(mmVCE_LMI_CACHE_CTRL));
567 }
568 
vce_v3_0_set_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned type,enum amdgpu_interrupt_state state)569 static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
570 					struct amdgpu_irq_src *source,
571 					unsigned type,
572 					enum amdgpu_interrupt_state state)
573 {
574 	uint32_t val = 0;
575 
576 	if (state == AMDGPU_IRQ_STATE_ENABLE)
577 		val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
578 
579 	WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
580 	return 0;
581 }
582 
vce_v3_0_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)583 static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
584 				      struct amdgpu_irq_src *source,
585 				      struct amdgpu_iv_entry *entry)
586 {
587 	DRM_DEBUG("IH: VCE\n");
588 
589 	WREG32_P(mmVCE_SYS_INT_STATUS,
590 		VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK,
591 		~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK);
592 
593 	switch (entry->src_data) {
594 	case 0:
595 		amdgpu_fence_process(&adev->vce.ring[0]);
596 		break;
597 	case 1:
598 		amdgpu_fence_process(&adev->vce.ring[1]);
599 		break;
600 	default:
601 		DRM_ERROR("Unhandled interrupt: %d %d\n",
602 			  entry->src_id, entry->src_data);
603 		break;
604 	}
605 
606 	return 0;
607 }
608 
vce_v3_0_set_clockgating_state(void * handle,enum amd_clockgating_state state)609 static int vce_v3_0_set_clockgating_state(void *handle,
610 					  enum amd_clockgating_state state)
611 {
612 	return 0;
613 }
614 
vce_v3_0_set_powergating_state(void * handle,enum amd_powergating_state state)615 static int vce_v3_0_set_powergating_state(void *handle,
616 					  enum amd_powergating_state state)
617 {
618 	/* This doesn't actually powergate the VCE block.
619 	 * That's done in the dpm code via the SMC.  This
620 	 * just re-inits the block as necessary.  The actual
621 	 * gating still happens in the dpm code.  We should
622 	 * revisit this when there is a cleaner line between
623 	 * the smc and the hw blocks
624 	 */
625 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
626 
627 	if (state == AMD_PG_STATE_GATE)
628 		/* XXX do we need a vce_v3_0_stop()? */
629 		return 0;
630 	else
631 		return vce_v3_0_start(adev);
632 }
633 
634 const struct amd_ip_funcs vce_v3_0_ip_funcs = {
635 	.early_init = vce_v3_0_early_init,
636 	.late_init = NULL,
637 	.sw_init = vce_v3_0_sw_init,
638 	.sw_fini = vce_v3_0_sw_fini,
639 	.hw_init = vce_v3_0_hw_init,
640 	.hw_fini = vce_v3_0_hw_fini,
641 	.suspend = vce_v3_0_suspend,
642 	.resume = vce_v3_0_resume,
643 	.is_idle = vce_v3_0_is_idle,
644 	.wait_for_idle = vce_v3_0_wait_for_idle,
645 	.soft_reset = vce_v3_0_soft_reset,
646 	.print_status = vce_v3_0_print_status,
647 	.set_clockgating_state = vce_v3_0_set_clockgating_state,
648 	.set_powergating_state = vce_v3_0_set_powergating_state,
649 };
650 
651 static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
652 	.get_rptr = vce_v3_0_ring_get_rptr,
653 	.get_wptr = vce_v3_0_ring_get_wptr,
654 	.set_wptr = vce_v3_0_ring_set_wptr,
655 	.parse_cs = amdgpu_vce_ring_parse_cs,
656 	.emit_ib = amdgpu_vce_ring_emit_ib,
657 	.emit_fence = amdgpu_vce_ring_emit_fence,
658 	.emit_semaphore = amdgpu_vce_ring_emit_semaphore,
659 	.test_ring = amdgpu_vce_ring_test_ring,
660 	.test_ib = amdgpu_vce_ring_test_ib,
661 	.insert_nop = amdgpu_ring_insert_nop,
662 };
663 
vce_v3_0_set_ring_funcs(struct amdgpu_device * adev)664 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
665 {
666 	adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
667 	adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
668 }
669 
670 static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
671 	.set = vce_v3_0_set_interrupt_state,
672 	.process = vce_v3_0_process_interrupt,
673 };
674 
vce_v3_0_set_irq_funcs(struct amdgpu_device * adev)675 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
676 {
677 	adev->vce.irq.num_types = 1;
678 	adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
679 };
680