xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c (revision 5fc3aeeb)
1aaa36a97SAlex Deucher /*
2aaa36a97SAlex Deucher  * Copyright 2014 Advanced Micro Devices, Inc.
3aaa36a97SAlex Deucher  * All Rights Reserved.
4aaa36a97SAlex Deucher  *
5aaa36a97SAlex Deucher  * Permission is hereby granted, free of charge, to any person obtaining a
6aaa36a97SAlex Deucher  * copy of this software and associated documentation files (the
7aaa36a97SAlex Deucher  * "Software"), to deal in the Software without restriction, including
8aaa36a97SAlex Deucher  * without limitation the rights to use, copy, modify, merge, publish,
9aaa36a97SAlex Deucher  * distribute, sub license, and/or sell copies of the Software, and to
10aaa36a97SAlex Deucher  * permit persons to whom the Software is furnished to do so, subject to
11aaa36a97SAlex Deucher  * the following conditions:
12aaa36a97SAlex Deucher  *
13aaa36a97SAlex Deucher  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14aaa36a97SAlex Deucher  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15aaa36a97SAlex Deucher  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16aaa36a97SAlex Deucher  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17aaa36a97SAlex Deucher  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18aaa36a97SAlex Deucher  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19aaa36a97SAlex Deucher  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20aaa36a97SAlex Deucher  *
21aaa36a97SAlex Deucher  * The above copyright notice and this permission notice (including the
22aaa36a97SAlex Deucher  * next paragraph) shall be included in all copies or substantial portions
23aaa36a97SAlex Deucher  * of the Software.
24aaa36a97SAlex Deucher  *
25aaa36a97SAlex Deucher  * Authors: Christian König <christian.koenig@amd.com>
26aaa36a97SAlex Deucher  */
27aaa36a97SAlex Deucher 
28aaa36a97SAlex Deucher #include <linux/firmware.h>
29aaa36a97SAlex Deucher #include <drm/drmP.h>
30aaa36a97SAlex Deucher #include "amdgpu.h"
31aaa36a97SAlex Deucher #include "amdgpu_vce.h"
32aaa36a97SAlex Deucher #include "vid.h"
33aaa36a97SAlex Deucher #include "vce/vce_3_0_d.h"
34aaa36a97SAlex Deucher #include "vce/vce_3_0_sh_mask.h"
35aaa36a97SAlex Deucher #include "oss/oss_2_0_d.h"
36aaa36a97SAlex Deucher #include "oss/oss_2_0_sh_mask.h"
375bbc553aSLeo Liu #include "gca/gfx_8_0_d.h"
385bbc553aSLeo Liu 
395bbc553aSLeo Liu #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
405bbc553aSLeo Liu #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
41aaa36a97SAlex Deucher 
42e9822622SLeo Liu #define VCE_V3_0_FW_SIZE	(384 * 1024)
43e9822622SLeo Liu #define VCE_V3_0_STACK_SIZE	(64 * 1024)
44e9822622SLeo Liu #define VCE_V3_0_DATA_SIZE	((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))
45e9822622SLeo Liu 
465bbc553aSLeo Liu static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
47aaa36a97SAlex Deucher static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
48aaa36a97SAlex Deucher static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
49aaa36a97SAlex Deucher 
50aaa36a97SAlex Deucher /**
51aaa36a97SAlex Deucher  * vce_v3_0_ring_get_rptr - get read pointer
52aaa36a97SAlex Deucher  *
53aaa36a97SAlex Deucher  * @ring: amdgpu_ring pointer
54aaa36a97SAlex Deucher  *
55aaa36a97SAlex Deucher  * Returns the current hardware read pointer
56aaa36a97SAlex Deucher  */
57aaa36a97SAlex Deucher static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
58aaa36a97SAlex Deucher {
59aaa36a97SAlex Deucher 	struct amdgpu_device *adev = ring->adev;
60aaa36a97SAlex Deucher 
61aaa36a97SAlex Deucher 	if (ring == &adev->vce.ring[0])
62aaa36a97SAlex Deucher 		return RREG32(mmVCE_RB_RPTR);
63aaa36a97SAlex Deucher 	else
64aaa36a97SAlex Deucher 		return RREG32(mmVCE_RB_RPTR2);
65aaa36a97SAlex Deucher }
66aaa36a97SAlex Deucher 
67aaa36a97SAlex Deucher /**
68aaa36a97SAlex Deucher  * vce_v3_0_ring_get_wptr - get write pointer
69aaa36a97SAlex Deucher  *
70aaa36a97SAlex Deucher  * @ring: amdgpu_ring pointer
71aaa36a97SAlex Deucher  *
72aaa36a97SAlex Deucher  * Returns the current hardware write pointer
73aaa36a97SAlex Deucher  */
74aaa36a97SAlex Deucher static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
75aaa36a97SAlex Deucher {
76aaa36a97SAlex Deucher 	struct amdgpu_device *adev = ring->adev;
77aaa36a97SAlex Deucher 
78aaa36a97SAlex Deucher 	if (ring == &adev->vce.ring[0])
79aaa36a97SAlex Deucher 		return RREG32(mmVCE_RB_WPTR);
80aaa36a97SAlex Deucher 	else
81aaa36a97SAlex Deucher 		return RREG32(mmVCE_RB_WPTR2);
82aaa36a97SAlex Deucher }
83aaa36a97SAlex Deucher 
84aaa36a97SAlex Deucher /**
85aaa36a97SAlex Deucher  * vce_v3_0_ring_set_wptr - set write pointer
86aaa36a97SAlex Deucher  *
87aaa36a97SAlex Deucher  * @ring: amdgpu_ring pointer
88aaa36a97SAlex Deucher  *
89aaa36a97SAlex Deucher  * Commits the write pointer to the hardware
90aaa36a97SAlex Deucher  */
91aaa36a97SAlex Deucher static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
92aaa36a97SAlex Deucher {
93aaa36a97SAlex Deucher 	struct amdgpu_device *adev = ring->adev;
94aaa36a97SAlex Deucher 
95aaa36a97SAlex Deucher 	if (ring == &adev->vce.ring[0])
96aaa36a97SAlex Deucher 		WREG32(mmVCE_RB_WPTR, ring->wptr);
97aaa36a97SAlex Deucher 	else
98aaa36a97SAlex Deucher 		WREG32(mmVCE_RB_WPTR2, ring->wptr);
99aaa36a97SAlex Deucher }
100aaa36a97SAlex Deucher 
101aaa36a97SAlex Deucher /**
102aaa36a97SAlex Deucher  * vce_v3_0_start - start VCE block
103aaa36a97SAlex Deucher  *
104aaa36a97SAlex Deucher  * @adev: amdgpu_device pointer
105aaa36a97SAlex Deucher  *
106aaa36a97SAlex Deucher  * Setup and start the VCE block
107aaa36a97SAlex Deucher  */
108aaa36a97SAlex Deucher static int vce_v3_0_start(struct amdgpu_device *adev)
109aaa36a97SAlex Deucher {
110aaa36a97SAlex Deucher 	struct amdgpu_ring *ring;
1115bbc553aSLeo Liu 	int idx, i, j, r;
112aaa36a97SAlex Deucher 
1135bbc553aSLeo Liu 	mutex_lock(&adev->grbm_idx_mutex);
1145bbc553aSLeo Liu 	for (idx = 0; idx < 2; ++idx) {
1155bbc553aSLeo Liu 		if(idx == 0)
1165bbc553aSLeo Liu 			WREG32_P(mmGRBM_GFX_INDEX, 0,
1175bbc553aSLeo Liu 				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
1185bbc553aSLeo Liu 		else
1195bbc553aSLeo Liu 			WREG32_P(mmGRBM_GFX_INDEX,
1205bbc553aSLeo Liu 				GRBM_GFX_INDEX__VCE_INSTANCE_MASK,
1215bbc553aSLeo Liu 				~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
1225bbc553aSLeo Liu 
1235bbc553aSLeo Liu 		vce_v3_0_mc_resume(adev, idx);
124aaa36a97SAlex Deucher 
125aaa36a97SAlex Deucher 		/* set BUSY flag */
126aaa36a97SAlex Deucher 		WREG32_P(mmVCE_STATUS, 1, ~1);
127aaa36a97SAlex Deucher 
1285bbc553aSLeo Liu 		WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK,
1295bbc553aSLeo Liu 			~VCE_VCPU_CNTL__CLK_EN_MASK);
130aaa36a97SAlex Deucher 
131aaa36a97SAlex Deucher 		WREG32_P(mmVCE_SOFT_RESET,
132aaa36a97SAlex Deucher 			 VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
133aaa36a97SAlex Deucher 			 ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
134aaa36a97SAlex Deucher 
135aaa36a97SAlex Deucher 		mdelay(100);
136aaa36a97SAlex Deucher 
1375bbc553aSLeo Liu 		WREG32_P(mmVCE_SOFT_RESET, 0,
1385bbc553aSLeo Liu 			~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
139aaa36a97SAlex Deucher 
140aaa36a97SAlex Deucher 		for (i = 0; i < 10; ++i) {
141aaa36a97SAlex Deucher 			uint32_t status;
142aaa36a97SAlex Deucher 			for (j = 0; j < 100; ++j) {
143aaa36a97SAlex Deucher 				status = RREG32(mmVCE_STATUS);
144aaa36a97SAlex Deucher 				if (status & 2)
145aaa36a97SAlex Deucher 					break;
146aaa36a97SAlex Deucher 				mdelay(10);
147aaa36a97SAlex Deucher 			}
148aaa36a97SAlex Deucher 			r = 0;
149aaa36a97SAlex Deucher 			if (status & 2)
150aaa36a97SAlex Deucher 				break;
151aaa36a97SAlex Deucher 
152aaa36a97SAlex Deucher 			DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
1535bbc553aSLeo Liu 			WREG32_P(mmVCE_SOFT_RESET,
1545bbc553aSLeo Liu 				VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
155aaa36a97SAlex Deucher 				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
156aaa36a97SAlex Deucher 			mdelay(10);
1575bbc553aSLeo Liu 			WREG32_P(mmVCE_SOFT_RESET, 0,
1585bbc553aSLeo Liu 				~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
159aaa36a97SAlex Deucher 			mdelay(10);
160aaa36a97SAlex Deucher 			r = -1;
161aaa36a97SAlex Deucher 		}
162aaa36a97SAlex Deucher 
163aaa36a97SAlex Deucher 		/* clear BUSY flag */
164aaa36a97SAlex Deucher 		WREG32_P(mmVCE_STATUS, 0, ~1);
165aaa36a97SAlex Deucher 
166aaa36a97SAlex Deucher 		if (r) {
167aaa36a97SAlex Deucher 			DRM_ERROR("VCE not responding, giving up!!!\n");
1685bbc553aSLeo Liu 			mutex_unlock(&adev->grbm_idx_mutex);
169aaa36a97SAlex Deucher 			return r;
170aaa36a97SAlex Deucher 		}
1715bbc553aSLeo Liu 	}
1725bbc553aSLeo Liu 
1735bbc553aSLeo Liu 	WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
1745bbc553aSLeo Liu 	mutex_unlock(&adev->grbm_idx_mutex);
1755bbc553aSLeo Liu 
1765bbc553aSLeo Liu 	ring = &adev->vce.ring[0];
1775bbc553aSLeo Liu 	WREG32(mmVCE_RB_RPTR, ring->wptr);
1785bbc553aSLeo Liu 	WREG32(mmVCE_RB_WPTR, ring->wptr);
1795bbc553aSLeo Liu 	WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
1805bbc553aSLeo Liu 	WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
1815bbc553aSLeo Liu 	WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
1825bbc553aSLeo Liu 
1835bbc553aSLeo Liu 	ring = &adev->vce.ring[1];
1845bbc553aSLeo Liu 	WREG32(mmVCE_RB_RPTR2, ring->wptr);
1855bbc553aSLeo Liu 	WREG32(mmVCE_RB_WPTR2, ring->wptr);
1865bbc553aSLeo Liu 	WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
1875bbc553aSLeo Liu 	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
1885bbc553aSLeo Liu 	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
189aaa36a97SAlex Deucher 
190aaa36a97SAlex Deucher 	return 0;
191aaa36a97SAlex Deucher }
192aaa36a97SAlex Deucher 
1935fc3aeebSyanyang1 static int vce_v3_0_early_init(void *handle)
194aaa36a97SAlex Deucher {
1955fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1965fc3aeebSyanyang1 
197aaa36a97SAlex Deucher 	vce_v3_0_set_ring_funcs(adev);
198aaa36a97SAlex Deucher 	vce_v3_0_set_irq_funcs(adev);
199aaa36a97SAlex Deucher 
200aaa36a97SAlex Deucher 	return 0;
201aaa36a97SAlex Deucher }
202aaa36a97SAlex Deucher 
2035fc3aeebSyanyang1 static int vce_v3_0_sw_init(void *handle)
204aaa36a97SAlex Deucher {
2055fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
206aaa36a97SAlex Deucher 	struct amdgpu_ring *ring;
207aaa36a97SAlex Deucher 	int r;
208aaa36a97SAlex Deucher 
209aaa36a97SAlex Deucher 	/* VCE */
210aaa36a97SAlex Deucher 	r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
211aaa36a97SAlex Deucher 	if (r)
212aaa36a97SAlex Deucher 		return r;
213aaa36a97SAlex Deucher 
214e9822622SLeo Liu 	r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
215e9822622SLeo Liu 		(VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
216aaa36a97SAlex Deucher 	if (r)
217aaa36a97SAlex Deucher 		return r;
218aaa36a97SAlex Deucher 
219aaa36a97SAlex Deucher 	r = amdgpu_vce_resume(adev);
220aaa36a97SAlex Deucher 	if (r)
221aaa36a97SAlex Deucher 		return r;
222aaa36a97SAlex Deucher 
223aaa36a97SAlex Deucher 	ring = &adev->vce.ring[0];
224aaa36a97SAlex Deucher 	sprintf(ring->name, "vce0");
225aaa36a97SAlex Deucher 	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
226aaa36a97SAlex Deucher 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
227aaa36a97SAlex Deucher 	if (r)
228aaa36a97SAlex Deucher 		return r;
229aaa36a97SAlex Deucher 
230aaa36a97SAlex Deucher 	ring = &adev->vce.ring[1];
231aaa36a97SAlex Deucher 	sprintf(ring->name, "vce1");
232aaa36a97SAlex Deucher 	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
233aaa36a97SAlex Deucher 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
234aaa36a97SAlex Deucher 	if (r)
235aaa36a97SAlex Deucher 		return r;
236aaa36a97SAlex Deucher 
237aaa36a97SAlex Deucher 	return r;
238aaa36a97SAlex Deucher }
239aaa36a97SAlex Deucher 
2405fc3aeebSyanyang1 static int vce_v3_0_sw_fini(void *handle)
241aaa36a97SAlex Deucher {
242aaa36a97SAlex Deucher 	int r;
2435fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
244aaa36a97SAlex Deucher 
245aaa36a97SAlex Deucher 	r = amdgpu_vce_suspend(adev);
246aaa36a97SAlex Deucher 	if (r)
247aaa36a97SAlex Deucher 		return r;
248aaa36a97SAlex Deucher 
249aaa36a97SAlex Deucher 	r = amdgpu_vce_sw_fini(adev);
250aaa36a97SAlex Deucher 	if (r)
251aaa36a97SAlex Deucher 		return r;
252aaa36a97SAlex Deucher 
253aaa36a97SAlex Deucher 	return r;
254aaa36a97SAlex Deucher }
255aaa36a97SAlex Deucher 
2565fc3aeebSyanyang1 static int vce_v3_0_hw_init(void *handle)
257aaa36a97SAlex Deucher {
258aaa36a97SAlex Deucher 	struct amdgpu_ring *ring;
259aaa36a97SAlex Deucher 	int r;
2605fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
261aaa36a97SAlex Deucher 
262aaa36a97SAlex Deucher 	r = vce_v3_0_start(adev);
263aaa36a97SAlex Deucher 	if (r)
264aaa36a97SAlex Deucher 		return r;
265aaa36a97SAlex Deucher 
266aaa36a97SAlex Deucher 	ring = &adev->vce.ring[0];
267aaa36a97SAlex Deucher 	ring->ready = true;
268aaa36a97SAlex Deucher 	r = amdgpu_ring_test_ring(ring);
269aaa36a97SAlex Deucher 	if (r) {
270aaa36a97SAlex Deucher 		ring->ready = false;
271aaa36a97SAlex Deucher 		return r;
272aaa36a97SAlex Deucher 	}
273aaa36a97SAlex Deucher 
274aaa36a97SAlex Deucher 	ring = &adev->vce.ring[1];
275aaa36a97SAlex Deucher 	ring->ready = true;
276aaa36a97SAlex Deucher 	r = amdgpu_ring_test_ring(ring);
277aaa36a97SAlex Deucher 	if (r) {
278aaa36a97SAlex Deucher 		ring->ready = false;
279aaa36a97SAlex Deucher 		return r;
280aaa36a97SAlex Deucher 	}
281aaa36a97SAlex Deucher 
282aaa36a97SAlex Deucher 	DRM_INFO("VCE initialized successfully.\n");
283aaa36a97SAlex Deucher 
284aaa36a97SAlex Deucher 	return 0;
285aaa36a97SAlex Deucher }
286aaa36a97SAlex Deucher 
2875fc3aeebSyanyang1 static int vce_v3_0_hw_fini(void *handle)
288aaa36a97SAlex Deucher {
289aaa36a97SAlex Deucher 	return 0;
290aaa36a97SAlex Deucher }
291aaa36a97SAlex Deucher 
2925fc3aeebSyanyang1 static int vce_v3_0_suspend(void *handle)
293aaa36a97SAlex Deucher {
294aaa36a97SAlex Deucher 	int r;
2955fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
296aaa36a97SAlex Deucher 
297aaa36a97SAlex Deucher 	r = vce_v3_0_hw_fini(adev);
298aaa36a97SAlex Deucher 	if (r)
299aaa36a97SAlex Deucher 		return r;
300aaa36a97SAlex Deucher 
301aaa36a97SAlex Deucher 	r = amdgpu_vce_suspend(adev);
302aaa36a97SAlex Deucher 	if (r)
303aaa36a97SAlex Deucher 		return r;
304aaa36a97SAlex Deucher 
305aaa36a97SAlex Deucher 	return r;
306aaa36a97SAlex Deucher }
307aaa36a97SAlex Deucher 
3085fc3aeebSyanyang1 static int vce_v3_0_resume(void *handle)
309aaa36a97SAlex Deucher {
310aaa36a97SAlex Deucher 	int r;
3115fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
312aaa36a97SAlex Deucher 
313aaa36a97SAlex Deucher 	r = amdgpu_vce_resume(adev);
314aaa36a97SAlex Deucher 	if (r)
315aaa36a97SAlex Deucher 		return r;
316aaa36a97SAlex Deucher 
317aaa36a97SAlex Deucher 	r = vce_v3_0_hw_init(adev);
318aaa36a97SAlex Deucher 	if (r)
319aaa36a97SAlex Deucher 		return r;
320aaa36a97SAlex Deucher 
321aaa36a97SAlex Deucher 	return r;
322aaa36a97SAlex Deucher }
323aaa36a97SAlex Deucher 
3245bbc553aSLeo Liu static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
325aaa36a97SAlex Deucher {
326aaa36a97SAlex Deucher 	uint32_t offset, size;
327aaa36a97SAlex Deucher 
328aaa36a97SAlex Deucher 	WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
329aaa36a97SAlex Deucher 	WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
330aaa36a97SAlex Deucher 	WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
331aaa36a97SAlex Deucher 	WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
332aaa36a97SAlex Deucher 
333aaa36a97SAlex Deucher 	WREG32(mmVCE_LMI_CTRL, 0x00398000);
334aaa36a97SAlex Deucher 	WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
335aaa36a97SAlex Deucher 	WREG32(mmVCE_LMI_SWAP_CNTL, 0);
336aaa36a97SAlex Deucher 	WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
337aaa36a97SAlex Deucher 	WREG32(mmVCE_LMI_VM_CTRL, 0);
338aaa36a97SAlex Deucher 
339aaa36a97SAlex Deucher 	WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
340aaa36a97SAlex Deucher 	offset = AMDGPU_VCE_FIRMWARE_OFFSET;
341e9822622SLeo Liu 	size = VCE_V3_0_FW_SIZE;
342aaa36a97SAlex Deucher 	WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
343aaa36a97SAlex Deucher 	WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
344aaa36a97SAlex Deucher 
3455bbc553aSLeo Liu 	if (idx == 0) {
346aaa36a97SAlex Deucher 		offset += size;
347e9822622SLeo Liu 		size = VCE_V3_0_STACK_SIZE;
348aaa36a97SAlex Deucher 		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
349aaa36a97SAlex Deucher 		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
350aaa36a97SAlex Deucher 		offset += size;
351e9822622SLeo Liu 		size = VCE_V3_0_DATA_SIZE;
352aaa36a97SAlex Deucher 		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
353aaa36a97SAlex Deucher 		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
3545bbc553aSLeo Liu 	} else {
3555bbc553aSLeo Liu 		offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
3565bbc553aSLeo Liu 		size = VCE_V3_0_STACK_SIZE;
3575bbc553aSLeo Liu 		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
3585bbc553aSLeo Liu 		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
3595bbc553aSLeo Liu 		offset += size;
3605bbc553aSLeo Liu 		size = VCE_V3_0_DATA_SIZE;
3615bbc553aSLeo Liu 		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
3625bbc553aSLeo Liu 		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
3635bbc553aSLeo Liu 	}
364aaa36a97SAlex Deucher 
365aaa36a97SAlex Deucher 	WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
366aaa36a97SAlex Deucher 
367aaa36a97SAlex Deucher 	WREG32_P(mmVCE_SYS_INT_EN, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK,
368aaa36a97SAlex Deucher 		 ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
369aaa36a97SAlex Deucher }
370aaa36a97SAlex Deucher 
3715fc3aeebSyanyang1 static bool vce_v3_0_is_idle(void *handle)
372aaa36a97SAlex Deucher {
3735fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
3745fc3aeebSyanyang1 
375aaa36a97SAlex Deucher 	return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK);
376aaa36a97SAlex Deucher }
377aaa36a97SAlex Deucher 
3785fc3aeebSyanyang1 static int vce_v3_0_wait_for_idle(void *handle)
379aaa36a97SAlex Deucher {
380aaa36a97SAlex Deucher 	unsigned i;
3815fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
382aaa36a97SAlex Deucher 
383aaa36a97SAlex Deucher 	for (i = 0; i < adev->usec_timeout; i++) {
384aaa36a97SAlex Deucher 		if (!(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK))
385aaa36a97SAlex Deucher 			return 0;
386aaa36a97SAlex Deucher 	}
387aaa36a97SAlex Deucher 	return -ETIMEDOUT;
388aaa36a97SAlex Deucher }
389aaa36a97SAlex Deucher 
3905fc3aeebSyanyang1 static int vce_v3_0_soft_reset(void *handle)
391aaa36a97SAlex Deucher {
3925fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
3935fc3aeebSyanyang1 
394aaa36a97SAlex Deucher 	WREG32_P(mmSRBM_SOFT_RESET, SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK,
395aaa36a97SAlex Deucher 			~SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK);
396aaa36a97SAlex Deucher 	mdelay(5);
397aaa36a97SAlex Deucher 
398aaa36a97SAlex Deucher 	return vce_v3_0_start(adev);
399aaa36a97SAlex Deucher }
400aaa36a97SAlex Deucher 
4015fc3aeebSyanyang1 static void vce_v3_0_print_status(void *handle)
402aaa36a97SAlex Deucher {
4035fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
4045fc3aeebSyanyang1 
405aaa36a97SAlex Deucher 	dev_info(adev->dev, "VCE 3.0 registers\n");
406aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_STATUS=0x%08X\n",
407aaa36a97SAlex Deucher 		 RREG32(mmVCE_STATUS));
408aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CNTL=0x%08X\n",
409aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CNTL));
410aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
411aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
412aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE0=0x%08X\n",
413aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CACHE_SIZE0));
414aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
415aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
416aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE1=0x%08X\n",
417aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CACHE_SIZE1));
418aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
419aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
420aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE2=0x%08X\n",
421aaa36a97SAlex Deucher 		 RREG32(mmVCE_VCPU_CACHE_SIZE2));
422aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_SOFT_RESET=0x%08X\n",
423aaa36a97SAlex Deucher 		 RREG32(mmVCE_SOFT_RESET));
424aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_BASE_LO2=0x%08X\n",
425aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_BASE_LO2));
426aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_BASE_HI2=0x%08X\n",
427aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_BASE_HI2));
428aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_SIZE2=0x%08X\n",
429aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_SIZE2));
430aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_RPTR2=0x%08X\n",
431aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_RPTR2));
432aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_WPTR2=0x%08X\n",
433aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_WPTR2));
434aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_BASE_LO=0x%08X\n",
435aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_BASE_LO));
436aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_BASE_HI=0x%08X\n",
437aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_BASE_HI));
438aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_SIZE=0x%08X\n",
439aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_SIZE));
440aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_RPTR=0x%08X\n",
441aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_RPTR));
442aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_RB_WPTR=0x%08X\n",
443aaa36a97SAlex Deucher 		 RREG32(mmVCE_RB_WPTR));
444aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_CLOCK_GATING_A=0x%08X\n",
445aaa36a97SAlex Deucher 		 RREG32(mmVCE_CLOCK_GATING_A));
446aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_CLOCK_GATING_B=0x%08X\n",
447aaa36a97SAlex Deucher 		 RREG32(mmVCE_CLOCK_GATING_B));
448aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_UENC_CLOCK_GATING=0x%08X\n",
449aaa36a97SAlex Deucher 		 RREG32(mmVCE_UENC_CLOCK_GATING));
450aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
451aaa36a97SAlex Deucher 		 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
452aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_SYS_INT_EN=0x%08X\n",
453aaa36a97SAlex Deucher 		 RREG32(mmVCE_SYS_INT_EN));
454aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_LMI_CTRL2=0x%08X\n",
455aaa36a97SAlex Deucher 		 RREG32(mmVCE_LMI_CTRL2));
456aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_LMI_CTRL=0x%08X\n",
457aaa36a97SAlex Deucher 		 RREG32(mmVCE_LMI_CTRL));
458aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_LMI_VM_CTRL=0x%08X\n",
459aaa36a97SAlex Deucher 		 RREG32(mmVCE_LMI_VM_CTRL));
460aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL=0x%08X\n",
461aaa36a97SAlex Deucher 		 RREG32(mmVCE_LMI_SWAP_CNTL));
462aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL1=0x%08X\n",
463aaa36a97SAlex Deucher 		 RREG32(mmVCE_LMI_SWAP_CNTL1));
464aaa36a97SAlex Deucher 	dev_info(adev->dev, "  VCE_LMI_CACHE_CTRL=0x%08X\n",
465aaa36a97SAlex Deucher 		 RREG32(mmVCE_LMI_CACHE_CTRL));
466aaa36a97SAlex Deucher }
467aaa36a97SAlex Deucher 
468aaa36a97SAlex Deucher static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
469aaa36a97SAlex Deucher 					struct amdgpu_irq_src *source,
470aaa36a97SAlex Deucher 					unsigned type,
471aaa36a97SAlex Deucher 					enum amdgpu_interrupt_state state)
472aaa36a97SAlex Deucher {
473aaa36a97SAlex Deucher 	uint32_t val = 0;
474aaa36a97SAlex Deucher 
475aaa36a97SAlex Deucher 	if (state == AMDGPU_IRQ_STATE_ENABLE)
476aaa36a97SAlex Deucher 		val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
477aaa36a97SAlex Deucher 
478aaa36a97SAlex Deucher 	WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
479aaa36a97SAlex Deucher 	return 0;
480aaa36a97SAlex Deucher }
481aaa36a97SAlex Deucher 
482aaa36a97SAlex Deucher static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
483aaa36a97SAlex Deucher 				      struct amdgpu_irq_src *source,
484aaa36a97SAlex Deucher 				      struct amdgpu_iv_entry *entry)
485aaa36a97SAlex Deucher {
486aaa36a97SAlex Deucher 	DRM_DEBUG("IH: VCE\n");
487aaa36a97SAlex Deucher 	switch (entry->src_data) {
488aaa36a97SAlex Deucher 	case 0:
489aaa36a97SAlex Deucher 		amdgpu_fence_process(&adev->vce.ring[0]);
490aaa36a97SAlex Deucher 		break;
491aaa36a97SAlex Deucher 	case 1:
492aaa36a97SAlex Deucher 		amdgpu_fence_process(&adev->vce.ring[1]);
493aaa36a97SAlex Deucher 		break;
494aaa36a97SAlex Deucher 	default:
495aaa36a97SAlex Deucher 		DRM_ERROR("Unhandled interrupt: %d %d\n",
496aaa36a97SAlex Deucher 			  entry->src_id, entry->src_data);
497aaa36a97SAlex Deucher 		break;
498aaa36a97SAlex Deucher 	}
499aaa36a97SAlex Deucher 
500aaa36a97SAlex Deucher 	return 0;
501aaa36a97SAlex Deucher }
502aaa36a97SAlex Deucher 
5035fc3aeebSyanyang1 static int vce_v3_0_set_clockgating_state(void *handle,
5045fc3aeebSyanyang1 					  enum amd_clockgating_state state)
505aaa36a97SAlex Deucher {
506aaa36a97SAlex Deucher 	return 0;
507aaa36a97SAlex Deucher }
508aaa36a97SAlex Deucher 
5095fc3aeebSyanyang1 static int vce_v3_0_set_powergating_state(void *handle,
5105fc3aeebSyanyang1 					  enum amd_powergating_state state)
511aaa36a97SAlex Deucher {
512aaa36a97SAlex Deucher 	/* This doesn't actually powergate the VCE block.
513aaa36a97SAlex Deucher 	 * That's done in the dpm code via the SMC.  This
514aaa36a97SAlex Deucher 	 * just re-inits the block as necessary.  The actual
515aaa36a97SAlex Deucher 	 * gating still happens in the dpm code.  We should
516aaa36a97SAlex Deucher 	 * revisit this when there is a cleaner line between
517aaa36a97SAlex Deucher 	 * the smc and the hw blocks
518aaa36a97SAlex Deucher 	 */
5195fc3aeebSyanyang1 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
5205fc3aeebSyanyang1 
5215fc3aeebSyanyang1 	if (state == AMD_PG_STATE_GATE)
522aaa36a97SAlex Deucher 		/* XXX do we need a vce_v3_0_stop()? */
523aaa36a97SAlex Deucher 		return 0;
524aaa36a97SAlex Deucher 	else
525aaa36a97SAlex Deucher 		return vce_v3_0_start(adev);
526aaa36a97SAlex Deucher }
527aaa36a97SAlex Deucher 
5285fc3aeebSyanyang1 const struct amd_ip_funcs vce_v3_0_ip_funcs = {
529aaa36a97SAlex Deucher 	.early_init = vce_v3_0_early_init,
530aaa36a97SAlex Deucher 	.late_init = NULL,
531aaa36a97SAlex Deucher 	.sw_init = vce_v3_0_sw_init,
532aaa36a97SAlex Deucher 	.sw_fini = vce_v3_0_sw_fini,
533aaa36a97SAlex Deucher 	.hw_init = vce_v3_0_hw_init,
534aaa36a97SAlex Deucher 	.hw_fini = vce_v3_0_hw_fini,
535aaa36a97SAlex Deucher 	.suspend = vce_v3_0_suspend,
536aaa36a97SAlex Deucher 	.resume = vce_v3_0_resume,
537aaa36a97SAlex Deucher 	.is_idle = vce_v3_0_is_idle,
538aaa36a97SAlex Deucher 	.wait_for_idle = vce_v3_0_wait_for_idle,
539aaa36a97SAlex Deucher 	.soft_reset = vce_v3_0_soft_reset,
540aaa36a97SAlex Deucher 	.print_status = vce_v3_0_print_status,
541aaa36a97SAlex Deucher 	.set_clockgating_state = vce_v3_0_set_clockgating_state,
542aaa36a97SAlex Deucher 	.set_powergating_state = vce_v3_0_set_powergating_state,
543aaa36a97SAlex Deucher };
544aaa36a97SAlex Deucher 
545aaa36a97SAlex Deucher static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
546aaa36a97SAlex Deucher 	.get_rptr = vce_v3_0_ring_get_rptr,
547aaa36a97SAlex Deucher 	.get_wptr = vce_v3_0_ring_get_wptr,
548aaa36a97SAlex Deucher 	.set_wptr = vce_v3_0_ring_set_wptr,
549aaa36a97SAlex Deucher 	.parse_cs = amdgpu_vce_ring_parse_cs,
550aaa36a97SAlex Deucher 	.emit_ib = amdgpu_vce_ring_emit_ib,
551aaa36a97SAlex Deucher 	.emit_fence = amdgpu_vce_ring_emit_fence,
552aaa36a97SAlex Deucher 	.emit_semaphore = amdgpu_vce_ring_emit_semaphore,
553aaa36a97SAlex Deucher 	.test_ring = amdgpu_vce_ring_test_ring,
554aaa36a97SAlex Deucher 	.test_ib = amdgpu_vce_ring_test_ib,
555aaa36a97SAlex Deucher 	.is_lockup = amdgpu_ring_test_lockup,
556aaa36a97SAlex Deucher };
557aaa36a97SAlex Deucher 
558aaa36a97SAlex Deucher static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
559aaa36a97SAlex Deucher {
560aaa36a97SAlex Deucher 	adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
561aaa36a97SAlex Deucher 	adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
562aaa36a97SAlex Deucher }
563aaa36a97SAlex Deucher 
564aaa36a97SAlex Deucher static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
565aaa36a97SAlex Deucher 	.set = vce_v3_0_set_interrupt_state,
566aaa36a97SAlex Deucher 	.process = vce_v3_0_process_interrupt,
567aaa36a97SAlex Deucher };
568aaa36a97SAlex Deucher 
569aaa36a97SAlex Deucher static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
570aaa36a97SAlex Deucher {
571aaa36a97SAlex Deucher 	adev->vce.irq.num_types = 1;
572aaa36a97SAlex Deucher 	adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
573aaa36a97SAlex Deucher };
574