Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 51static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
 52static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
 53static 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 */
 62static 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 */
 79static 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 */
 96static 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
106static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override)
107{
108	u32 tmp, data;
109
110	tmp = data = RREG32(mmVCE_RB_ARB_CTRL);
111	if (override)
112		data |= VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK;
113	else
114		data &= ~VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK;
115
116	if (tmp != data)
117		WREG32(mmVCE_RB_ARB_CTRL, data);
118}
119
120static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev,
121					     bool gated)
122{
123	u32 tmp, data;
124	/* Set Override to disable Clock Gating */
125	vce_v3_0_override_vce_clock_gating(adev, true);
126
127	if (!gated) {
128		/* Force CLOCK ON for VCE_CLOCK_GATING_B,
129		 * {*_FORCE_ON, *_FORCE_OFF} = {1, 0}
130		 * VREG can be FORCE ON or set to Dynamic, but can't be OFF
131		 */
132		tmp = data = RREG32(mmVCE_CLOCK_GATING_B);
133		data |= 0x1ff;
134		data &= ~0xef0000;
135		if (tmp != data)
136			WREG32(mmVCE_CLOCK_GATING_B, data);
137
138		/* Force CLOCK ON for VCE_UENC_CLOCK_GATING,
139		 * {*_FORCE_ON, *_FORCE_OFF} = {1, 0}
140		 */
141		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING);
142		data |= 0x3ff000;
143		data &= ~0xffc00000;
144		if (tmp != data)
145			WREG32(mmVCE_UENC_CLOCK_GATING, data);
146
147		/* set VCE_UENC_CLOCK_GATING_2 */
148		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
149		data |= 0x2;
150		data &= ~0x2;
151		if (tmp != data)
152			WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
153
154		/* Force CLOCK ON for VCE_UENC_REG_CLOCK_GATING */
155		tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
156		data |= 0x37f;
157		if (tmp != data)
158			WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
159
160		/* Force VCE_UENC_DMA_DCLK_CTRL Clock ON */
161		tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
162		data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
163				VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
164				VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK  |
165				0x8;
166		if (tmp != data)
167			WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
168	} else {
169		/* Force CLOCK OFF for VCE_CLOCK_GATING_B,
170		 * {*, *_FORCE_OFF} = {*, 1}
171		 * set VREG to Dynamic, as it can't be OFF
172		 */
173		tmp = data = RREG32(mmVCE_CLOCK_GATING_B);
174		data &= ~0x80010;
175		data |= 0xe70008;
176		if (tmp != data)
177			WREG32(mmVCE_CLOCK_GATING_B, data);
178		/* Force CLOCK OFF for VCE_UENC_CLOCK_GATING,
179		 * Force ClOCK OFF takes precedent over Force CLOCK ON setting.
180		 * {*_FORCE_ON, *_FORCE_OFF} = {*, 1}
181		 */
182		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING);
183		data |= 0xffc00000;
184		if (tmp != data)
185			WREG32(mmVCE_UENC_CLOCK_GATING, data);
186		/* Set VCE_UENC_CLOCK_GATING_2 */
187		tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
188		data |= 0x10000;
189		if (tmp != data)
190			WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
191		/* Set VCE_UENC_REG_CLOCK_GATING to dynamic */
192		tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
193		data &= ~0xffc00000;
194		if (tmp != data)
195			WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
196		/* Set VCE_UENC_DMA_DCLK_CTRL CG always in dynamic mode */
197		tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
198		data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
199				VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
200				VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK  |
201				0x8);
202		if (tmp != data)
203			WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
204	}
205	vce_v3_0_override_vce_clock_gating(adev, false);
206}
207
208/**
209 * vce_v3_0_start - start VCE block
210 *
211 * @adev: amdgpu_device pointer
212 *
213 * Setup and start the VCE block
214 */
215static int vce_v3_0_start(struct amdgpu_device *adev)
216{
217	struct amdgpu_ring *ring;
218	int idx, i, j, r;
219
220	mutex_lock(&adev->grbm_idx_mutex);
221	for (idx = 0; idx < 2; ++idx) {
222
223		if (adev->vce.harvest_config & (1 << idx))
224			continue;
225
226		if (idx == 0)
227			WREG32_P(mmGRBM_GFX_INDEX, 0,
228				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
229		else
230			WREG32_P(mmGRBM_GFX_INDEX,
231				GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
232				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
233
234		vce_v3_0_mc_resume(adev, idx);
235
236		/* set BUSY flag */
237		WREG32_P(mmVCE_STATUS, 1, ~1);
238		if (adev->asic_type >= CHIP_STONEY)
239			WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001);
240		else
241			WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
242				~VCE_VCPU_CNTL__CLK_EN_MASK);
243
244		WREG32_P(mmVCE_SOFT_RESET,
245			 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
246			 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
247
248		mdelay(100);
249
250		WREG32_P(mmVCE_SOFT_RESET, 0,
251			~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
252
253		for (i = 0; i < 10; ++i) {
254			uint32_t status;
255			for (j = 0; j < 100; ++j) {
256				status = RREG32(mmVCE_STATUS);
257				if (status & 2)
258					break;
259				mdelay(10);
260			}
261			r = 0;
262			if (status & 2)
263				break;
264
265			DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
266			WREG32_P(mmVCE_SOFT_RESET,
267				VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
268				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
269			mdelay(10);
270			WREG32_P(mmVCE_SOFT_RESET, 0,
271				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
272			mdelay(10);
273			r = -1;
274		}
275
276		/* clear BUSY flag */
277		WREG32_P(mmVCE_STATUS, 0, ~1);
278
279		/* Set Clock-Gating off */
280		if (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)
281			vce_v3_0_set_vce_sw_clock_gating(adev, false);
282
283		if (r) {
284			DRM_ERROR("VCE not responding, giving up!!!\n");
285			mutex_unlock(&adev->grbm_idx_mutex);
286			return r;
287		}
288	}
289
290	WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
291	mutex_unlock(&adev->grbm_idx_mutex);
292
293	ring = &adev->vce.ring[0];
294	WREG32(mmVCE_RB_RPTR, ring->wptr);
295	WREG32(mmVCE_RB_WPTR, ring->wptr);
296	WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
297	WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
298	WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
299
300	ring = &adev->vce.ring[1];
301	WREG32(mmVCE_RB_RPTR2, ring->wptr);
302	WREG32(mmVCE_RB_WPTR2, ring->wptr);
303	WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
304	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
305	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
306
307	return 0;
308}
309
310#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS     0xC0014074
311#define VCE_HARVEST_FUSE_MACRO__SHIFT       27
312#define VCE_HARVEST_FUSE_MACRO__MASK        0x18000000
313
314static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
315{
316	u32 tmp;
317
318	/* Fiji, Stoney are single pipe */
319	if ((adev->asic_type == CHIP_FIJI) ||
320	    (adev->asic_type == CHIP_STONEY))
321		return AMDGPU_VCE_HARVEST_VCE1;
322
323	/* Tonga and CZ are dual or single pipe */
324	if (adev->flags & AMD_IS_APU)
325		tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
326		       VCE_HARVEST_FUSE_MACRO__MASK) >>
327			VCE_HARVEST_FUSE_MACRO__SHIFT;
328	else
329		tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
330		       CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
331			CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;
332
333	switch (tmp) {
334	case 1:
335		return AMDGPU_VCE_HARVEST_VCE0;
336	case 2:
337		return AMDGPU_VCE_HARVEST_VCE1;
338	case 3:
339		return AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
340	default:
341		return 0;
342	}
343}
344
345static int vce_v3_0_early_init(void *handle)
346{
347	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
348
349	adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
350
351	if ((adev->vce.harvest_config &
352	     (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
353	    (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
354		return -ENOENT;
355
356	vce_v3_0_set_ring_funcs(adev);
357	vce_v3_0_set_irq_funcs(adev);
358
359	return 0;
360}
361
362static int vce_v3_0_sw_init(void *handle)
363{
364	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
365	struct amdgpu_ring *ring;
366	int r;
367
368	/* VCE */
369	r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
370	if (r)
371		return r;
372
373	r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
374		(VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
375	if (r)
376		return r;
377
378	r = amdgpu_vce_resume(adev);
379	if (r)
380		return r;
381
382	ring = &adev->vce.ring[0];
383	sprintf(ring->name, "vce0");
384	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
385			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
386	if (r)
387		return r;
388
389	ring = &adev->vce.ring[1];
390	sprintf(ring->name, "vce1");
391	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
392			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
393	if (r)
394		return r;
395
396	return r;
397}
398
399static int vce_v3_0_sw_fini(void *handle)
400{
401	int r;
402	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
403
404	r = amdgpu_vce_suspend(adev);
405	if (r)
406		return r;
407
408	r = amdgpu_vce_sw_fini(adev);
409	if (r)
410		return r;
411
412	return r;
413}
414
415static int vce_v3_0_hw_init(void *handle)
416{
417	int r, i;
418	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
419
420	r = vce_v3_0_start(adev);
421	if (r)
422		return r;
423
424	adev->vce.ring[0].ready = false;
425	adev->vce.ring[1].ready = false;
426
427	for (i = 0; i < 2; i++) {
428		r = amdgpu_ring_test_ring(&adev->vce.ring[i]);
429		if (r)
430			return r;
431		else
432			adev->vce.ring[i].ready = true;
433	}
434
435	DRM_INFO("VCE initialized successfully.\n");
436
437	return 0;
438}
439
440static int vce_v3_0_hw_fini(void *handle)
441{
442	return 0;
443}
444
445static int vce_v3_0_suspend(void *handle)
446{
447	int r;
448	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
449
450	r = vce_v3_0_hw_fini(adev);
451	if (r)
452		return r;
453
454	r = amdgpu_vce_suspend(adev);
455	if (r)
456		return r;
457
458	return r;
459}
460
461static int vce_v3_0_resume(void *handle)
462{
463	int r;
464	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
465
466	r = amdgpu_vce_resume(adev);
467	if (r)
468		return r;
469
470	r = vce_v3_0_hw_init(adev);
471	if (r)
472		return r;
473
474	return r;
475}
476
477static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
478{
479	uint32_t offset, size;
480
481	WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
482	WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
483	WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
484	WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
485
486	WREG32(mmVCE_LMI_CTRL, 0x00398000);
487	WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
488	WREG32(mmVCE_LMI_SWAP_CNTL, 0);
489	WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
490	WREG32(mmVCE_LMI_VM_CTRL, 0);
491	if (adev->asic_type >= CHIP_STONEY) {
492		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8));
493		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8));
494		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8));
495	} else
496		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
497	offset = AMDGPU_VCE_FIRMWARE_OFFSET;
498	size = VCE_V3_0_FW_SIZE;
499	WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
500	WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
501
502	if (idx == 0) {
503		offset += size;
504		size = VCE_V3_0_STACK_SIZE;
505		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
506		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
507		offset += size;
508		size = VCE_V3_0_DATA_SIZE;
509		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
510		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
511	} else {
512		offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
513		size = VCE_V3_0_STACK_SIZE;
514		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
515		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
516		offset += size;
517		size = VCE_V3_0_DATA_SIZE;
518		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
519		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
520	}
521
522	WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
523
524	WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK,
525		 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
526}
527
528static bool vce_v3_0_is_idle(void *handle)
529{
530	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
531	u32 mask = 0;
532
533	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK;
534	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_STATUS2__VCE1_BUSY_MASK;
535
536	return !(RREG32(mmSRBM_STATUS2) & mask);
537}
538
539static int vce_v3_0_wait_for_idle(void *handle)
540{
541	unsigned i;
542	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
543
544	for (i = 0; i < adev->usec_timeout; i++)
545		if (vce_v3_0_is_idle(handle))
546			return 0;
547
548	return -ETIMEDOUT;
549}
550
551static int vce_v3_0_soft_reset(void *handle)
552{
553	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
554	u32 mask = 0;
555
556	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK;
557	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK;
558
559	WREG32_P(mmSRBM_SOFT_RESET, mask,
560		 ~(SRBM_SOFT_RESET__SOFT_RESET_VCE0_MASK |
561		   SRBM_SOFT_RESET__SOFT_RESET_VCE1_MASK));
562	mdelay(5);
563
564	return vce_v3_0_start(adev);
565}
566
567static void vce_v3_0_print_status(void *handle)
568{
569	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
570
571	dev_info(adev->dev, "VCE 3.0 registers\n");
572	dev_info(adev->dev, "  VCE_STATUS=0x%08X\n",
573		 RREG32(mmVCE_STATUS));
574	dev_info(adev->dev, "  VCE_VCPU_CNTL=0x%08X\n",
575		 RREG32(mmVCE_VCPU_CNTL));
576	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
577		 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
578	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE0=0x%08X\n",
579		 RREG32(mmVCE_VCPU_CACHE_SIZE0));
580	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
581		 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
582	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE1=0x%08X\n",
583		 RREG32(mmVCE_VCPU_CACHE_SIZE1));
584	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
585		 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
586	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE2=0x%08X\n",
587		 RREG32(mmVCE_VCPU_CACHE_SIZE2));
588	dev_info(adev->dev, "  VCE_SOFT_RESET=0x%08X\n",
589		 RREG32(mmVCE_SOFT_RESET));
590	dev_info(adev->dev, "  VCE_RB_BASE_LO2=0x%08X\n",
591		 RREG32(mmVCE_RB_BASE_LO2));
592	dev_info(adev->dev, "  VCE_RB_BASE_HI2=0x%08X\n",
593		 RREG32(mmVCE_RB_BASE_HI2));
594	dev_info(adev->dev, "  VCE_RB_SIZE2=0x%08X\n",
595		 RREG32(mmVCE_RB_SIZE2));
596	dev_info(adev->dev, "  VCE_RB_RPTR2=0x%08X\n",
597		 RREG32(mmVCE_RB_RPTR2));
598	dev_info(adev->dev, "  VCE_RB_WPTR2=0x%08X\n",
599		 RREG32(mmVCE_RB_WPTR2));
600	dev_info(adev->dev, "  VCE_RB_BASE_LO=0x%08X\n",
601		 RREG32(mmVCE_RB_BASE_LO));
602	dev_info(adev->dev, "  VCE_RB_BASE_HI=0x%08X\n",
603		 RREG32(mmVCE_RB_BASE_HI));
604	dev_info(adev->dev, "  VCE_RB_SIZE=0x%08X\n",
605		 RREG32(mmVCE_RB_SIZE));
606	dev_info(adev->dev, "  VCE_RB_RPTR=0x%08X\n",
607		 RREG32(mmVCE_RB_RPTR));
608	dev_info(adev->dev, "  VCE_RB_WPTR=0x%08X\n",
609		 RREG32(mmVCE_RB_WPTR));
610	dev_info(adev->dev, "  VCE_CLOCK_GATING_A=0x%08X\n",
611		 RREG32(mmVCE_CLOCK_GATING_A));
612	dev_info(adev->dev, "  VCE_CLOCK_GATING_B=0x%08X\n",
613		 RREG32(mmVCE_CLOCK_GATING_B));
614	dev_info(adev->dev, "  VCE_UENC_CLOCK_GATING=0x%08X\n",
615		 RREG32(mmVCE_UENC_CLOCK_GATING));
616	dev_info(adev->dev, "  VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
617		 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
618	dev_info(adev->dev, "  VCE_SYS_INT_EN=0x%08X\n",
619		 RREG32(mmVCE_SYS_INT_EN));
620	dev_info(adev->dev, "  VCE_LMI_CTRL2=0x%08X\n",
621		 RREG32(mmVCE_LMI_CTRL2));
622	dev_info(adev->dev, "  VCE_LMI_CTRL=0x%08X\n",
623		 RREG32(mmVCE_LMI_CTRL));
624	dev_info(adev->dev, "  VCE_LMI_VM_CTRL=0x%08X\n",
625		 RREG32(mmVCE_LMI_VM_CTRL));
626	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL=0x%08X\n",
627		 RREG32(mmVCE_LMI_SWAP_CNTL));
628	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL1=0x%08X\n",
629		 RREG32(mmVCE_LMI_SWAP_CNTL1));
630	dev_info(adev->dev, "  VCE_LMI_CACHE_CTRL=0x%08X\n",
631		 RREG32(mmVCE_LMI_CACHE_CTRL));
632}
633
634static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
635					struct amdgpu_irq_src *source,
636					unsigned type,
637					enum amdgpu_interrupt_state state)
638{
639	uint32_t val = 0;
640
641	if (state == AMDGPU_IRQ_STATE_ENABLE)
642		val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
643
644	WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
645	return 0;
646}
647
648static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
649				      struct amdgpu_irq_src *source,
650				      struct amdgpu_iv_entry *entry)
651{
652	DRM_DEBUG("IH: VCE\n");
653
654	WREG32_P(mmVCE_SYS_INT_STATUS,
655		VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK,
656		~VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK);
657
658	switch (entry->src_data) {
659	case 0:
660	case 1:
661		amdgpu_fence_process(&adev->vce.ring[entry->src_data]);
662		break;
663	default:
664		DRM_ERROR("Unhandled interrupt: %d %d\n",
665			  entry->src_id, entry->src_data);
666		break;
667	}
668
669	return 0;
670}
671
672static int vce_v3_0_set_clockgating_state(void *handle,
673					  enum amd_clockgating_state state)
674{
675	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
676	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
677	int i;
678
679	if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG))
680		return 0;
681
682	mutex_lock(&adev->grbm_idx_mutex);
683	for (i = 0; i < 2; i++) {
684		/* Program VCE Instance 0 or 1 if not harvested */
685		if (adev->vce.harvest_config & (1 << i))
686			continue;
687
688		if (i == 0)
689			WREG32_P(mmGRBM_GFX_INDEX, 0,
690					~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
691		else
692			WREG32_P(mmGRBM_GFX_INDEX,
693					GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
694					~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
695
696		if (enable) {
697			/* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
698			uint32_t data = RREG32(mmVCE_CLOCK_GATING_A);
699			data &= ~(0xf | 0xff0);
700			data |= ((0x0 << 0) | (0x04 << 4));
701			WREG32(mmVCE_CLOCK_GATING_A, data);
702
703			/* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */
704			data = RREG32(mmVCE_UENC_CLOCK_GATING);
705			data &= ~(0xf | 0xff0);
706			data |= ((0x0 << 0) | (0x04 << 4));
707			WREG32(mmVCE_UENC_CLOCK_GATING, data);
708		}
709
710		vce_v3_0_set_vce_sw_clock_gating(adev, enable);
711	}
712
713	WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
714	mutex_unlock(&adev->grbm_idx_mutex);
715
716	return 0;
717}
718
719static int vce_v3_0_set_powergating_state(void *handle,
720					  enum amd_powergating_state state)
721{
722	/* This doesn't actually powergate the VCE block.
723	 * That's done in the dpm code via the SMC.  This
724	 * just re-inits the block as necessary.  The actual
725	 * gating still happens in the dpm code.  We should
726	 * revisit this when there is a cleaner line between
727	 * the smc and the hw blocks
728	 */
729	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
730
731	if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
732		return 0;
733
734	if (state == AMD_PG_STATE_GATE)
735		/* XXX do we need a vce_v3_0_stop()? */
736		return 0;
737	else
738		return vce_v3_0_start(adev);
739}
740
741const struct amd_ip_funcs vce_v3_0_ip_funcs = {
742	.early_init = vce_v3_0_early_init,
743	.late_init = NULL,
744	.sw_init = vce_v3_0_sw_init,
745	.sw_fini = vce_v3_0_sw_fini,
746	.hw_init = vce_v3_0_hw_init,
747	.hw_fini = vce_v3_0_hw_fini,
748	.suspend = vce_v3_0_suspend,
749	.resume = vce_v3_0_resume,
750	.is_idle = vce_v3_0_is_idle,
751	.wait_for_idle = vce_v3_0_wait_for_idle,
752	.soft_reset = vce_v3_0_soft_reset,
753	.print_status = vce_v3_0_print_status,
754	.set_clockgating_state = vce_v3_0_set_clockgating_state,
755	.set_powergating_state = vce_v3_0_set_powergating_state,
756};
757
758static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
759	.get_rptr = vce_v3_0_ring_get_rptr,
760	.get_wptr = vce_v3_0_ring_get_wptr,
761	.set_wptr = vce_v3_0_ring_set_wptr,
762	.parse_cs = amdgpu_vce_ring_parse_cs,
763	.emit_ib = amdgpu_vce_ring_emit_ib,
764	.emit_fence = amdgpu_vce_ring_emit_fence,
765	.test_ring = amdgpu_vce_ring_test_ring,
766	.test_ib = amdgpu_vce_ring_test_ib,
767	.insert_nop = amdgpu_ring_insert_nop,
768	.pad_ib = amdgpu_ring_generic_pad_ib,
769};
770
771static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
772{
773	adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
774	adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
775}
776
777static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
778	.set = vce_v3_0_set_interrupt_state,
779	.process = vce_v3_0_process_interrupt,
780};
781
782static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
783{
784	adev->vce.irq.num_types = 1;
785	adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
786};