xref: /openbsd-src/sys/dev/pci/drm/amd/amdgpu/vcn_v1_0.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
1fb4d8502Sjsg /*
2fb4d8502Sjsg  * Copyright 2016 Advanced Micro Devices, Inc.
3fb4d8502Sjsg  *
4fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
5fb4d8502Sjsg  * copy of this software and associated documentation files (the "Software"),
6fb4d8502Sjsg  * to deal in the Software without restriction, including without limitation
7fb4d8502Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fb4d8502Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
9fb4d8502Sjsg  * Software is furnished to do so, subject to the following conditions:
10fb4d8502Sjsg  *
11fb4d8502Sjsg  * The above copyright notice and this permission notice shall be included in
12fb4d8502Sjsg  * all copies or substantial portions of the Software.
13fb4d8502Sjsg  *
14fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17fb4d8502Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18fb4d8502Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19fb4d8502Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20fb4d8502Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg  *
22fb4d8502Sjsg  */
23fb4d8502Sjsg 
24fb4d8502Sjsg #include <linux/firmware.h>
25c349dbc7Sjsg 
26fb4d8502Sjsg #include "amdgpu.h"
271bb76ff1Sjsg #include "amdgpu_cs.h"
28fb4d8502Sjsg #include "amdgpu_vcn.h"
29c349dbc7Sjsg #include "amdgpu_pm.h"
30fb4d8502Sjsg #include "soc15.h"
31fb4d8502Sjsg #include "soc15d.h"
32fb4d8502Sjsg #include "soc15_common.h"
33fb4d8502Sjsg 
34fb4d8502Sjsg #include "vcn/vcn_1_0_offset.h"
35fb4d8502Sjsg #include "vcn/vcn_1_0_sh_mask.h"
36fb4d8502Sjsg #include "mmhub/mmhub_9_1_offset.h"
37fb4d8502Sjsg #include "mmhub/mmhub_9_1_sh_mask.h"
38fb4d8502Sjsg 
39fb4d8502Sjsg #include "ivsrcid/vcn/irqsrcs_vcn_1_0.h"
40c349dbc7Sjsg #include "jpeg_v1_0.h"
41ad8b1aafSjsg #include "vcn_v1_0.h"
42c349dbc7Sjsg 
43c349dbc7Sjsg #define mmUVD_RBC_XX_IB_REG_CHECK_1_0		0x05ab
44c349dbc7Sjsg #define mmUVD_RBC_XX_IB_REG_CHECK_1_0_BASE_IDX	1
45c349dbc7Sjsg #define mmUVD_REG_XX_MASK_1_0			0x05ac
46c349dbc7Sjsg #define mmUVD_REG_XX_MASK_1_0_BASE_IDX		1
47fb4d8502Sjsg 
48fb4d8502Sjsg static int vcn_v1_0_stop(struct amdgpu_device *adev);
49fb4d8502Sjsg static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
50fb4d8502Sjsg static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
51fb4d8502Sjsg static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
52fb4d8502Sjsg static int vcn_v1_0_set_powergating_state(void *handle, enum amd_powergating_state state);
53c349dbc7Sjsg static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
54c349dbc7Sjsg 				int inst_idx, struct dpg_pause_state *new_state);
55c349dbc7Sjsg 
56c349dbc7Sjsg static void vcn_v1_0_idle_work_handler(struct work_struct *work);
57ad8b1aafSjsg static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);
58fb4d8502Sjsg 
59fb4d8502Sjsg /**
60*f005ef32Sjsg  * vcn_v1_0_early_init - set function pointers and load microcode
61fb4d8502Sjsg  *
62fb4d8502Sjsg  * @handle: amdgpu_device pointer
63fb4d8502Sjsg  *
64fb4d8502Sjsg  * Set ring and irq function pointers
65*f005ef32Sjsg  * Load microcode from filesystem
66fb4d8502Sjsg  */
vcn_v1_0_early_init(void * handle)67fb4d8502Sjsg static int vcn_v1_0_early_init(void *handle)
68fb4d8502Sjsg {
69fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
70fb4d8502Sjsg 
71fb4d8502Sjsg 	adev->vcn.num_enc_rings = 2;
72fb4d8502Sjsg 
73fb4d8502Sjsg 	vcn_v1_0_set_dec_ring_funcs(adev);
74fb4d8502Sjsg 	vcn_v1_0_set_enc_ring_funcs(adev);
75fb4d8502Sjsg 	vcn_v1_0_set_irq_funcs(adev);
76fb4d8502Sjsg 
77c349dbc7Sjsg 	jpeg_v1_0_early_init(handle);
78c349dbc7Sjsg 
79*f005ef32Sjsg 	return amdgpu_vcn_early_init(adev);
80fb4d8502Sjsg }
81fb4d8502Sjsg 
82fb4d8502Sjsg /**
83fb4d8502Sjsg  * vcn_v1_0_sw_init - sw init for VCN block
84fb4d8502Sjsg  *
85fb4d8502Sjsg  * @handle: amdgpu_device pointer
86fb4d8502Sjsg  *
87fb4d8502Sjsg  * Load firmware and sw initialization
88fb4d8502Sjsg  */
vcn_v1_0_sw_init(void * handle)89fb4d8502Sjsg static int vcn_v1_0_sw_init(void *handle)
90fb4d8502Sjsg {
91fb4d8502Sjsg 	struct amdgpu_ring *ring;
92fb4d8502Sjsg 	int i, r;
93fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
94fb4d8502Sjsg 
95fb4d8502Sjsg 	/* VCN DEC TRAP */
96c349dbc7Sjsg 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
97c349dbc7Sjsg 			VCN_1_0__SRCID__UVD_SYSTEM_MESSAGE_INTERRUPT, &adev->vcn.inst->irq);
98fb4d8502Sjsg 	if (r)
99fb4d8502Sjsg 		return r;
100fb4d8502Sjsg 
101fb4d8502Sjsg 	/* VCN ENC TRAP */
102fb4d8502Sjsg 	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
103fb4d8502Sjsg 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, i + VCN_1_0__SRCID__UVD_ENC_GENERAL_PURPOSE,
104c349dbc7Sjsg 					&adev->vcn.inst->irq);
105fb4d8502Sjsg 		if (r)
106fb4d8502Sjsg 			return r;
107fb4d8502Sjsg 	}
108fb4d8502Sjsg 
109fb4d8502Sjsg 	r = amdgpu_vcn_sw_init(adev);
110fb4d8502Sjsg 	if (r)
111fb4d8502Sjsg 		return r;
112fb4d8502Sjsg 
113c349dbc7Sjsg 	/* Override the work func */
114c349dbc7Sjsg #ifdef __linux__
115c349dbc7Sjsg 	adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler;
116c349dbc7Sjsg #else
117c349dbc7Sjsg 	task_set(&adev->vcn.idle_work.work.task,
118c349dbc7Sjsg 	    (void (*)(void *))vcn_v1_0_idle_work_handler,
119c349dbc7Sjsg 	    &adev->vcn.idle_work.work);
120c349dbc7Sjsg #endif
121c349dbc7Sjsg 
1221bb76ff1Sjsg 	amdgpu_vcn_setup_ucode(adev);
123fb4d8502Sjsg 
124fb4d8502Sjsg 	r = amdgpu_vcn_resume(adev);
125fb4d8502Sjsg 	if (r)
126fb4d8502Sjsg 		return r;
127fb4d8502Sjsg 
128c349dbc7Sjsg 	ring = &adev->vcn.inst->ring_dec;
129*f005ef32Sjsg 	ring->vm_hub = AMDGPU_MMHUB0(0);
130fb4d8502Sjsg 	snprintf(ring->name, sizeof(ring->name), "vcn_dec");
131ad8b1aafSjsg 	r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0,
1325ca02815Sjsg 			     AMDGPU_RING_PRIO_DEFAULT, NULL);
133fb4d8502Sjsg 	if (r)
134fb4d8502Sjsg 		return r;
135fb4d8502Sjsg 
136c349dbc7Sjsg 	adev->vcn.internal.scratch9 = adev->vcn.inst->external.scratch9 =
137c349dbc7Sjsg 		SOC15_REG_OFFSET(UVD, 0, mmUVD_SCRATCH9);
138c349dbc7Sjsg 	adev->vcn.internal.data0 = adev->vcn.inst->external.data0 =
139c349dbc7Sjsg 		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0);
140c349dbc7Sjsg 	adev->vcn.internal.data1 = adev->vcn.inst->external.data1 =
141c349dbc7Sjsg 		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1);
142c349dbc7Sjsg 	adev->vcn.internal.cmd = adev->vcn.inst->external.cmd =
143c349dbc7Sjsg 		SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD);
144c349dbc7Sjsg 	adev->vcn.internal.nop = adev->vcn.inst->external.nop =
145c349dbc7Sjsg 		SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP);
146c349dbc7Sjsg 
147fb4d8502Sjsg 	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
1481bb76ff1Sjsg 		enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i);
1491bb76ff1Sjsg 
150c349dbc7Sjsg 		ring = &adev->vcn.inst->ring_enc[i];
151*f005ef32Sjsg 		ring->vm_hub = AMDGPU_MMHUB0(0);
152fb4d8502Sjsg 		snprintf(ring->name, sizeof(ring->name), "vcn_enc%d", i);
153ad8b1aafSjsg 		r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0,
1541bb76ff1Sjsg 				     hw_prio, NULL);
155fb4d8502Sjsg 		if (r)
156fb4d8502Sjsg 			return r;
157fb4d8502Sjsg 	}
158fb4d8502Sjsg 
159c349dbc7Sjsg 	adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
160c349dbc7Sjsg 
1611bb76ff1Sjsg 	if (amdgpu_vcnfw_log) {
1621bb76ff1Sjsg 		volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared.cpu_addr;
1631bb76ff1Sjsg 
1641bb76ff1Sjsg 		fw_shared->present_flag_0 = 0;
1651bb76ff1Sjsg 		amdgpu_vcn_fwlog_init(adev->vcn.inst);
1661bb76ff1Sjsg 	}
1671bb76ff1Sjsg 
168c349dbc7Sjsg 	r = jpeg_v1_0_sw_init(handle);
169fb4d8502Sjsg 
170fb4d8502Sjsg 	return r;
171fb4d8502Sjsg }
172fb4d8502Sjsg 
173fb4d8502Sjsg /**
174fb4d8502Sjsg  * vcn_v1_0_sw_fini - sw fini for VCN block
175fb4d8502Sjsg  *
176fb4d8502Sjsg  * @handle: amdgpu_device pointer
177fb4d8502Sjsg  *
178fb4d8502Sjsg  * VCN suspend and free up sw allocation
179fb4d8502Sjsg  */
vcn_v1_0_sw_fini(void * handle)180fb4d8502Sjsg static int vcn_v1_0_sw_fini(void *handle)
181fb4d8502Sjsg {
182fb4d8502Sjsg 	int r;
183fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
184fb4d8502Sjsg 
185fb4d8502Sjsg 	r = amdgpu_vcn_suspend(adev);
186fb4d8502Sjsg 	if (r)
187fb4d8502Sjsg 		return r;
188fb4d8502Sjsg 
189c349dbc7Sjsg 	jpeg_v1_0_sw_fini(handle);
190c349dbc7Sjsg 
191fb4d8502Sjsg 	r = amdgpu_vcn_sw_fini(adev);
192fb4d8502Sjsg 
193fb4d8502Sjsg 	return r;
194fb4d8502Sjsg }
195fb4d8502Sjsg 
196fb4d8502Sjsg /**
197fb4d8502Sjsg  * vcn_v1_0_hw_init - start and test VCN block
198fb4d8502Sjsg  *
199fb4d8502Sjsg  * @handle: amdgpu_device pointer
200fb4d8502Sjsg  *
201fb4d8502Sjsg  * Initialize the hardware, boot up the VCPU and do some testing
202fb4d8502Sjsg  */
vcn_v1_0_hw_init(void * handle)203fb4d8502Sjsg static int vcn_v1_0_hw_init(void *handle)
204fb4d8502Sjsg {
205fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
206c349dbc7Sjsg 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
207fb4d8502Sjsg 	int i, r;
208fb4d8502Sjsg 
209c349dbc7Sjsg 	r = amdgpu_ring_test_helper(ring);
210c349dbc7Sjsg 	if (r)
211fb4d8502Sjsg 		goto done;
212fb4d8502Sjsg 
213fb4d8502Sjsg 	for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
214c349dbc7Sjsg 		ring = &adev->vcn.inst->ring_enc[i];
215c349dbc7Sjsg 		r = amdgpu_ring_test_helper(ring);
216c349dbc7Sjsg 		if (r)
217fb4d8502Sjsg 			goto done;
218fb4d8502Sjsg 	}
219fb4d8502Sjsg 
220*f005ef32Sjsg 	ring = adev->jpeg.inst->ring_dec;
221c349dbc7Sjsg 	r = amdgpu_ring_test_helper(ring);
222c349dbc7Sjsg 	if (r)
223fb4d8502Sjsg 		goto done;
224fb4d8502Sjsg 
225fb4d8502Sjsg done:
226fb4d8502Sjsg 	if (!r)
227c349dbc7Sjsg 		DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
228c349dbc7Sjsg 			(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
229fb4d8502Sjsg 
230fb4d8502Sjsg 	return r;
231fb4d8502Sjsg }
232fb4d8502Sjsg 
233fb4d8502Sjsg /**
234fb4d8502Sjsg  * vcn_v1_0_hw_fini - stop the hardware block
235fb4d8502Sjsg  *
236fb4d8502Sjsg  * @handle: amdgpu_device pointer
237fb4d8502Sjsg  *
238fb4d8502Sjsg  * Stop the VCN block, mark ring as not ready any more
239fb4d8502Sjsg  */
vcn_v1_0_hw_fini(void * handle)240fb4d8502Sjsg static int vcn_v1_0_hw_fini(void *handle)
241fb4d8502Sjsg {
242fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
243ad8b1aafSjsg 
244ad8b1aafSjsg 	cancel_delayed_work_sync(&adev->vcn.idle_work);
245fb4d8502Sjsg 
246c349dbc7Sjsg 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
247ad8b1aafSjsg 		(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
248ad8b1aafSjsg 		 RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
249fb4d8502Sjsg 		vcn_v1_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
250ad8b1aafSjsg 	}
251fb4d8502Sjsg 
252fb4d8502Sjsg 	return 0;
253fb4d8502Sjsg }
254fb4d8502Sjsg 
255fb4d8502Sjsg /**
256fb4d8502Sjsg  * vcn_v1_0_suspend - suspend VCN block
257fb4d8502Sjsg  *
258fb4d8502Sjsg  * @handle: amdgpu_device pointer
259fb4d8502Sjsg  *
260fb4d8502Sjsg  * HW fini and suspend VCN block
261fb4d8502Sjsg  */
vcn_v1_0_suspend(void * handle)262fb4d8502Sjsg static int vcn_v1_0_suspend(void *handle)
263fb4d8502Sjsg {
264fb4d8502Sjsg 	int r;
265fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
266ec2bd244Sjsg 	bool idle_work_unexecuted;
267ec2bd244Sjsg 
268ec2bd244Sjsg 	idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.idle_work);
269ec2bd244Sjsg 	if (idle_work_unexecuted) {
270ec2bd244Sjsg 		if (adev->pm.dpm_enabled)
271ec2bd244Sjsg 			amdgpu_dpm_enable_uvd(adev, false);
272ec2bd244Sjsg 	}
273fb4d8502Sjsg 
274fb4d8502Sjsg 	r = vcn_v1_0_hw_fini(adev);
275fb4d8502Sjsg 	if (r)
276fb4d8502Sjsg 		return r;
277fb4d8502Sjsg 
278fb4d8502Sjsg 	r = amdgpu_vcn_suspend(adev);
279fb4d8502Sjsg 
280fb4d8502Sjsg 	return r;
281fb4d8502Sjsg }
282fb4d8502Sjsg 
283fb4d8502Sjsg /**
284fb4d8502Sjsg  * vcn_v1_0_resume - resume VCN block
285fb4d8502Sjsg  *
286fb4d8502Sjsg  * @handle: amdgpu_device pointer
287fb4d8502Sjsg  *
288fb4d8502Sjsg  * Resume firmware and hw init VCN block
289fb4d8502Sjsg  */
vcn_v1_0_resume(void * handle)290fb4d8502Sjsg static int vcn_v1_0_resume(void *handle)
291fb4d8502Sjsg {
292fb4d8502Sjsg 	int r;
293fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
294fb4d8502Sjsg 
295fb4d8502Sjsg 	r = amdgpu_vcn_resume(adev);
296fb4d8502Sjsg 	if (r)
297fb4d8502Sjsg 		return r;
298fb4d8502Sjsg 
299fb4d8502Sjsg 	r = vcn_v1_0_hw_init(adev);
300fb4d8502Sjsg 
301fb4d8502Sjsg 	return r;
302fb4d8502Sjsg }
303fb4d8502Sjsg 
304fb4d8502Sjsg /**
305c349dbc7Sjsg  * vcn_v1_0_mc_resume_spg_mode - memory controller programming
306fb4d8502Sjsg  *
307fb4d8502Sjsg  * @adev: amdgpu_device pointer
308fb4d8502Sjsg  *
309fb4d8502Sjsg  * Let the VCN memory controller know it's offsets
310fb4d8502Sjsg  */
vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device * adev)311c349dbc7Sjsg static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
312fb4d8502Sjsg {
313fb4d8502Sjsg 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4);
314fb4d8502Sjsg 	uint32_t offset;
315fb4d8502Sjsg 
316c349dbc7Sjsg 	/* cache window 0: fw */
317fb4d8502Sjsg 	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
318fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
319fb4d8502Sjsg 			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo));
320fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
321fb4d8502Sjsg 			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi));
322fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, 0);
323fb4d8502Sjsg 		offset = 0;
324fb4d8502Sjsg 	} else {
325fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
326c349dbc7Sjsg 			lower_32_bits(adev->vcn.inst->gpu_addr));
327fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
328c349dbc7Sjsg 			upper_32_bits(adev->vcn.inst->gpu_addr));
329fb4d8502Sjsg 		offset = size;
330fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0,
331fb4d8502Sjsg 			     AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
332fb4d8502Sjsg 	}
333fb4d8502Sjsg 
334fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size);
335fb4d8502Sjsg 
336c349dbc7Sjsg 	/* cache window 1: stack */
337fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
338c349dbc7Sjsg 		     lower_32_bits(adev->vcn.inst->gpu_addr + offset));
339fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
340c349dbc7Sjsg 		     upper_32_bits(adev->vcn.inst->gpu_addr + offset));
341fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1, 0);
342c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
343fb4d8502Sjsg 
344c349dbc7Sjsg 	/* cache window 2: context */
345fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
346c349dbc7Sjsg 		     lower_32_bits(adev->vcn.inst->gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
347fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
348c349dbc7Sjsg 		     upper_32_bits(adev->vcn.inst->gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
349fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2, 0);
350c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
351fb4d8502Sjsg 
352fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_UDEC_ADDR_CONFIG,
353fb4d8502Sjsg 			adev->gfx.config.gb_addr_config);
354fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_UDEC_DB_ADDR_CONFIG,
355fb4d8502Sjsg 			adev->gfx.config.gb_addr_config);
356fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_UDEC_DBW_ADDR_CONFIG,
357fb4d8502Sjsg 			adev->gfx.config.gb_addr_config);
358c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_UDEC_DBW_UV_ADDR_CONFIG,
359c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
360c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MIF_CURR_ADDR_CONFIG,
361c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
362c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MIF_CURR_UV_ADDR_CONFIG,
363c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
364c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MIF_RECON1_ADDR_CONFIG,
365c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
366c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MIF_RECON1_UV_ADDR_CONFIG,
367c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
368c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MIF_REF_ADDR_CONFIG,
369c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
370c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MIF_REF_UV_ADDR_CONFIG,
371c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
372c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_JPEG_ADDR_CONFIG,
373c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
374c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_JPEG_UV_ADDR_CONFIG,
375c349dbc7Sjsg 			adev->gfx.config.gb_addr_config);
376c349dbc7Sjsg }
377c349dbc7Sjsg 
vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device * adev)378c349dbc7Sjsg static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
379c349dbc7Sjsg {
380c349dbc7Sjsg 	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4);
381c349dbc7Sjsg 	uint32_t offset;
382c349dbc7Sjsg 
383c349dbc7Sjsg 	/* cache window 0: fw */
384c349dbc7Sjsg 	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
385ad8b1aafSjsg 		WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
386c349dbc7Sjsg 			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo),
387c349dbc7Sjsg 			     0xFFFFFFFF, 0);
388ad8b1aafSjsg 		WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
389c349dbc7Sjsg 			     (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_hi),
390c349dbc7Sjsg 			     0xFFFFFFFF, 0);
391ad8b1aafSjsg 		WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0, 0,
392c349dbc7Sjsg 			     0xFFFFFFFF, 0);
393c349dbc7Sjsg 		offset = 0;
394c349dbc7Sjsg 	} else {
395ad8b1aafSjsg 		WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
396c349dbc7Sjsg 			lower_32_bits(adev->vcn.inst->gpu_addr), 0xFFFFFFFF, 0);
397ad8b1aafSjsg 		WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
398c349dbc7Sjsg 			upper_32_bits(adev->vcn.inst->gpu_addr), 0xFFFFFFFF, 0);
399c349dbc7Sjsg 		offset = size;
400ad8b1aafSjsg 		WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0,
401c349dbc7Sjsg 			     AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0xFFFFFFFF, 0);
402c349dbc7Sjsg 	}
403c349dbc7Sjsg 
404ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size, 0xFFFFFFFF, 0);
405c349dbc7Sjsg 
406c349dbc7Sjsg 	/* cache window 1: stack */
407ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
408c349dbc7Sjsg 		     lower_32_bits(adev->vcn.inst->gpu_addr + offset), 0xFFFFFFFF, 0);
409ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
410c349dbc7Sjsg 		     upper_32_bits(adev->vcn.inst->gpu_addr + offset), 0xFFFFFFFF, 0);
411ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1, 0,
412c349dbc7Sjsg 			     0xFFFFFFFF, 0);
413ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE,
414c349dbc7Sjsg 			     0xFFFFFFFF, 0);
415c349dbc7Sjsg 
416c349dbc7Sjsg 	/* cache window 2: context */
417ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
418c349dbc7Sjsg 		     lower_32_bits(adev->vcn.inst->gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),
419c349dbc7Sjsg 			     0xFFFFFFFF, 0);
420ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
421c349dbc7Sjsg 		     upper_32_bits(adev->vcn.inst->gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),
422c349dbc7Sjsg 			     0xFFFFFFFF, 0);
423ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2, 0, 0xFFFFFFFF, 0);
424ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE,
425c349dbc7Sjsg 			     0xFFFFFFFF, 0);
426c349dbc7Sjsg 
427c349dbc7Sjsg 	/* VCN global tiling registers */
428ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_UDEC_ADDR_CONFIG,
429c349dbc7Sjsg 			adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
430ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_UDEC_DB_ADDR_CONFIG,
431c349dbc7Sjsg 			adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
432ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_UDEC_DBW_ADDR_CONFIG,
433c349dbc7Sjsg 			adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
434ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_UDEC_DBW_UV_ADDR_CONFIG,
435c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
436ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MIF_CURR_ADDR_CONFIG,
437c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
438ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MIF_CURR_UV_ADDR_CONFIG,
439c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
440ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MIF_RECON1_ADDR_CONFIG,
441c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
442ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MIF_RECON1_UV_ADDR_CONFIG,
443c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
444ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MIF_REF_ADDR_CONFIG,
445c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
446ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MIF_REF_UV_ADDR_CONFIG,
447c349dbc7Sjsg 		adev->gfx.config.gb_addr_config, 0xFFFFFFFF, 0);
448fb4d8502Sjsg }
449fb4d8502Sjsg 
450fb4d8502Sjsg /**
451fb4d8502Sjsg  * vcn_v1_0_disable_clock_gating - disable VCN clock gating
452fb4d8502Sjsg  *
453fb4d8502Sjsg  * @adev: amdgpu_device pointer
454fb4d8502Sjsg  *
455fb4d8502Sjsg  * Disable clock gating for VCN block
456fb4d8502Sjsg  */
vcn_v1_0_disable_clock_gating(struct amdgpu_device * adev)457fb4d8502Sjsg static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev)
458fb4d8502Sjsg {
459fb4d8502Sjsg 	uint32_t data;
460fb4d8502Sjsg 
461fb4d8502Sjsg 	/* JPEG disable CGC */
462fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL);
463fb4d8502Sjsg 
464fb4d8502Sjsg 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
465fb4d8502Sjsg 		data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
466fb4d8502Sjsg 	else
467fb4d8502Sjsg 		data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE_MASK;
468fb4d8502Sjsg 
469fb4d8502Sjsg 	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
470fb4d8502Sjsg 	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
471fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL, data);
472fb4d8502Sjsg 
473fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE);
474fb4d8502Sjsg 	data &= ~(JPEG_CGC_GATE__JPEG_MASK | JPEG_CGC_GATE__JPEG2_MASK);
475fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE, data);
476fb4d8502Sjsg 
477fb4d8502Sjsg 	/* UVD disable CGC */
478fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL);
479fb4d8502Sjsg 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
480fb4d8502Sjsg 		data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
481fb4d8502Sjsg 	else
482fb4d8502Sjsg 		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
483fb4d8502Sjsg 
484fb4d8502Sjsg 	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
485fb4d8502Sjsg 	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
486fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL, data);
487fb4d8502Sjsg 
488fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_CGC_GATE);
489fb4d8502Sjsg 	data &= ~(UVD_CGC_GATE__SYS_MASK
490fb4d8502Sjsg 		| UVD_CGC_GATE__UDEC_MASK
491fb4d8502Sjsg 		| UVD_CGC_GATE__MPEG2_MASK
492fb4d8502Sjsg 		| UVD_CGC_GATE__REGS_MASK
493fb4d8502Sjsg 		| UVD_CGC_GATE__RBC_MASK
494fb4d8502Sjsg 		| UVD_CGC_GATE__LMI_MC_MASK
495fb4d8502Sjsg 		| UVD_CGC_GATE__LMI_UMC_MASK
496fb4d8502Sjsg 		| UVD_CGC_GATE__IDCT_MASK
497fb4d8502Sjsg 		| UVD_CGC_GATE__MPRD_MASK
498fb4d8502Sjsg 		| UVD_CGC_GATE__MPC_MASK
499fb4d8502Sjsg 		| UVD_CGC_GATE__LBSI_MASK
500fb4d8502Sjsg 		| UVD_CGC_GATE__LRBBM_MASK
501fb4d8502Sjsg 		| UVD_CGC_GATE__UDEC_RE_MASK
502fb4d8502Sjsg 		| UVD_CGC_GATE__UDEC_CM_MASK
503fb4d8502Sjsg 		| UVD_CGC_GATE__UDEC_IT_MASK
504fb4d8502Sjsg 		| UVD_CGC_GATE__UDEC_DB_MASK
505fb4d8502Sjsg 		| UVD_CGC_GATE__UDEC_MP_MASK
506fb4d8502Sjsg 		| UVD_CGC_GATE__WCB_MASK
507fb4d8502Sjsg 		| UVD_CGC_GATE__VCPU_MASK
508fb4d8502Sjsg 		| UVD_CGC_GATE__SCPU_MASK);
509fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_CGC_GATE, data);
510fb4d8502Sjsg 
511fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL);
512fb4d8502Sjsg 	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
513fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_CM_MODE_MASK
514fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_IT_MODE_MASK
515fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_DB_MODE_MASK
516fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_MP_MODE_MASK
517fb4d8502Sjsg 		| UVD_CGC_CTRL__SYS_MODE_MASK
518fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_MODE_MASK
519fb4d8502Sjsg 		| UVD_CGC_CTRL__MPEG2_MODE_MASK
520fb4d8502Sjsg 		| UVD_CGC_CTRL__REGS_MODE_MASK
521fb4d8502Sjsg 		| UVD_CGC_CTRL__RBC_MODE_MASK
522fb4d8502Sjsg 		| UVD_CGC_CTRL__LMI_MC_MODE_MASK
523fb4d8502Sjsg 		| UVD_CGC_CTRL__LMI_UMC_MODE_MASK
524fb4d8502Sjsg 		| UVD_CGC_CTRL__IDCT_MODE_MASK
525fb4d8502Sjsg 		| UVD_CGC_CTRL__MPRD_MODE_MASK
526fb4d8502Sjsg 		| UVD_CGC_CTRL__MPC_MODE_MASK
527fb4d8502Sjsg 		| UVD_CGC_CTRL__LBSI_MODE_MASK
528fb4d8502Sjsg 		| UVD_CGC_CTRL__LRBBM_MODE_MASK
529fb4d8502Sjsg 		| UVD_CGC_CTRL__WCB_MODE_MASK
530fb4d8502Sjsg 		| UVD_CGC_CTRL__VCPU_MODE_MASK
531fb4d8502Sjsg 		| UVD_CGC_CTRL__SCPU_MODE_MASK);
532fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL, data);
533fb4d8502Sjsg 
534fb4d8502Sjsg 	/* turn on */
535fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_GATE);
536fb4d8502Sjsg 	data |= (UVD_SUVD_CGC_GATE__SRE_MASK
537fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SIT_MASK
538fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SMP_MASK
539fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SCM_MASK
540fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SDB_MASK
541fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SRE_H264_MASK
542fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
543fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SIT_H264_MASK
544fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
545fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SCM_H264_MASK
546fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
547fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SDB_H264_MASK
548fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
549fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SCLR_MASK
550fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__UVD_SC_MASK
551fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__ENT_MASK
552fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
553fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
554fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SITE_MASK
555fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SRE_VP9_MASK
556fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SCM_VP9_MASK
557fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
558fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__SDB_VP9_MASK
559fb4d8502Sjsg 		| UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
560fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_GATE, data);
561fb4d8502Sjsg 
562fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL);
563fb4d8502Sjsg 	data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
564fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
565fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
566fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
567fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
568fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
569fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
570fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
571fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
572fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
573fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
574fb4d8502Sjsg }
575fb4d8502Sjsg 
576fb4d8502Sjsg /**
577fb4d8502Sjsg  * vcn_v1_0_enable_clock_gating - enable VCN clock gating
578fb4d8502Sjsg  *
579fb4d8502Sjsg  * @adev: amdgpu_device pointer
580fb4d8502Sjsg  *
581fb4d8502Sjsg  * Enable clock gating for VCN block
582fb4d8502Sjsg  */
vcn_v1_0_enable_clock_gating(struct amdgpu_device * adev)583fb4d8502Sjsg static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev)
584fb4d8502Sjsg {
585fb4d8502Sjsg 	uint32_t data = 0;
586fb4d8502Sjsg 
587fb4d8502Sjsg 	/* enable JPEG CGC */
588fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL);
589fb4d8502Sjsg 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
590fb4d8502Sjsg 		data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
591fb4d8502Sjsg 	else
592fb4d8502Sjsg 		data |= 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
593fb4d8502Sjsg 	data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
594fb4d8502Sjsg 	data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
595fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL, data);
596fb4d8502Sjsg 
597fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE);
598fb4d8502Sjsg 	data |= (JPEG_CGC_GATE__JPEG_MASK | JPEG_CGC_GATE__JPEG2_MASK);
599fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE, data);
600fb4d8502Sjsg 
601fb4d8502Sjsg 	/* enable UVD CGC */
602fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL);
603fb4d8502Sjsg 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
604fb4d8502Sjsg 		data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
605fb4d8502Sjsg 	else
606fb4d8502Sjsg 		data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
607fb4d8502Sjsg 	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
608fb4d8502Sjsg 	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
609fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL, data);
610fb4d8502Sjsg 
611fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL);
612fb4d8502Sjsg 	data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
613fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_CM_MODE_MASK
614fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_IT_MODE_MASK
615fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_DB_MODE_MASK
616fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_MP_MODE_MASK
617fb4d8502Sjsg 		| UVD_CGC_CTRL__SYS_MODE_MASK
618fb4d8502Sjsg 		| UVD_CGC_CTRL__UDEC_MODE_MASK
619fb4d8502Sjsg 		| UVD_CGC_CTRL__MPEG2_MODE_MASK
620fb4d8502Sjsg 		| UVD_CGC_CTRL__REGS_MODE_MASK
621fb4d8502Sjsg 		| UVD_CGC_CTRL__RBC_MODE_MASK
622fb4d8502Sjsg 		| UVD_CGC_CTRL__LMI_MC_MODE_MASK
623fb4d8502Sjsg 		| UVD_CGC_CTRL__LMI_UMC_MODE_MASK
624fb4d8502Sjsg 		| UVD_CGC_CTRL__IDCT_MODE_MASK
625fb4d8502Sjsg 		| UVD_CGC_CTRL__MPRD_MODE_MASK
626fb4d8502Sjsg 		| UVD_CGC_CTRL__MPC_MODE_MASK
627fb4d8502Sjsg 		| UVD_CGC_CTRL__LBSI_MODE_MASK
628fb4d8502Sjsg 		| UVD_CGC_CTRL__LRBBM_MODE_MASK
629fb4d8502Sjsg 		| UVD_CGC_CTRL__WCB_MODE_MASK
630fb4d8502Sjsg 		| UVD_CGC_CTRL__VCPU_MODE_MASK
631fb4d8502Sjsg 		| UVD_CGC_CTRL__SCPU_MODE_MASK);
632fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_CGC_CTRL, data);
633fb4d8502Sjsg 
634fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL);
635fb4d8502Sjsg 	data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
636fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
637fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
638fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
639fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
640fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
641fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
642fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
643fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__IME_MODE_MASK
644fb4d8502Sjsg 		| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
645fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_SUVD_CGC_CTRL, data);
646fb4d8502Sjsg }
647fb4d8502Sjsg 
vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device * adev,uint8_t sram_sel)648c349dbc7Sjsg static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel)
649c349dbc7Sjsg {
650c349dbc7Sjsg 	uint32_t reg_data = 0;
651c349dbc7Sjsg 
652c349dbc7Sjsg 	/* disable JPEG CGC */
653c349dbc7Sjsg 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
654c349dbc7Sjsg 		reg_data = 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
655c349dbc7Sjsg 	else
656c349dbc7Sjsg 		reg_data = 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
657c349dbc7Sjsg 	reg_data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
658c349dbc7Sjsg 	reg_data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
659ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmJPEG_CGC_CTRL, reg_data, 0xFFFFFFFF, sram_sel);
660c349dbc7Sjsg 
661ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmJPEG_CGC_GATE, 0, 0xFFFFFFFF, sram_sel);
662c349dbc7Sjsg 
663c349dbc7Sjsg 	/* enable sw clock gating control */
664c349dbc7Sjsg 	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
665c349dbc7Sjsg 		reg_data = 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
666c349dbc7Sjsg 	else
667c349dbc7Sjsg 		reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
668c349dbc7Sjsg 	reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
669c349dbc7Sjsg 	reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
670c349dbc7Sjsg 	reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
671c349dbc7Sjsg 		 UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
672c349dbc7Sjsg 		 UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
673c349dbc7Sjsg 		 UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
674c349dbc7Sjsg 		 UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
675c349dbc7Sjsg 		 UVD_CGC_CTRL__SYS_MODE_MASK |
676c349dbc7Sjsg 		 UVD_CGC_CTRL__UDEC_MODE_MASK |
677c349dbc7Sjsg 		 UVD_CGC_CTRL__MPEG2_MODE_MASK |
678c349dbc7Sjsg 		 UVD_CGC_CTRL__REGS_MODE_MASK |
679c349dbc7Sjsg 		 UVD_CGC_CTRL__RBC_MODE_MASK |
680c349dbc7Sjsg 		 UVD_CGC_CTRL__LMI_MC_MODE_MASK |
681c349dbc7Sjsg 		 UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
682c349dbc7Sjsg 		 UVD_CGC_CTRL__IDCT_MODE_MASK |
683c349dbc7Sjsg 		 UVD_CGC_CTRL__MPRD_MODE_MASK |
684c349dbc7Sjsg 		 UVD_CGC_CTRL__MPC_MODE_MASK |
685c349dbc7Sjsg 		 UVD_CGC_CTRL__LBSI_MODE_MASK |
686c349dbc7Sjsg 		 UVD_CGC_CTRL__LRBBM_MODE_MASK |
687c349dbc7Sjsg 		 UVD_CGC_CTRL__WCB_MODE_MASK |
688c349dbc7Sjsg 		 UVD_CGC_CTRL__VCPU_MODE_MASK |
689c349dbc7Sjsg 		 UVD_CGC_CTRL__SCPU_MODE_MASK);
690ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_CGC_CTRL, reg_data, 0xFFFFFFFF, sram_sel);
691c349dbc7Sjsg 
692c349dbc7Sjsg 	/* turn off clock gating */
693ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_CGC_GATE, 0, 0xFFFFFFFF, sram_sel);
694c349dbc7Sjsg 
695c349dbc7Sjsg 	/* turn on SUVD clock gating */
696ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SUVD_CGC_GATE, 1, 0xFFFFFFFF, sram_sel);
697c349dbc7Sjsg 
698c349dbc7Sjsg 	/* turn on sw mode in UVD_SUVD_CGC_CTRL */
699ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SUVD_CGC_CTRL, 0, 0xFFFFFFFF, sram_sel);
700c349dbc7Sjsg }
701c349dbc7Sjsg 
vcn_1_0_disable_static_power_gating(struct amdgpu_device * adev)702fb4d8502Sjsg static void vcn_1_0_disable_static_power_gating(struct amdgpu_device *adev)
703fb4d8502Sjsg {
704fb4d8502Sjsg 	uint32_t data = 0;
705fb4d8502Sjsg 
706fb4d8502Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
707fb4d8502Sjsg 		data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
708fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
709fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
710fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
711fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
712fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDIL_PWR_CONFIG__SHIFT
713fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDIR_PWR_CONFIG__SHIFT
714fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
715fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
716fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
717fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDW_PWR_CONFIG__SHIFT);
718fb4d8502Sjsg 
719fb4d8502Sjsg 		WREG32_SOC15(VCN, 0, mmUVD_PGFSM_CONFIG, data);
720ad8b1aafSjsg 		SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON, 0xFFFFFF);
721fb4d8502Sjsg 	} else {
722fb4d8502Sjsg 		data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
723fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
724fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
725fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
726fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
727fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDIL_PWR_CONFIG__SHIFT
728fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDIR_PWR_CONFIG__SHIFT
729fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
730fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
731fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
732fb4d8502Sjsg 			| 1 << UVD_PGFSM_CONFIG__UVDW_PWR_CONFIG__SHIFT);
733fb4d8502Sjsg 		WREG32_SOC15(VCN, 0, mmUVD_PGFSM_CONFIG, data);
734ad8b1aafSjsg 		SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS, 0,  0xFFFFFFFF);
735fb4d8502Sjsg 	}
736fb4d8502Sjsg 
737fb4d8502Sjsg 	/* polling UVD_PGFSM_STATUS to confirm UVDM_PWR_STATUS , UVDU_PWR_STATUS are 0 (power on) */
738fb4d8502Sjsg 
739fb4d8502Sjsg 	data = RREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS);
740fb4d8502Sjsg 	data &= ~0x103;
741fb4d8502Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN)
742fb4d8502Sjsg 		data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON | UVD_POWER_STATUS__UVD_PG_EN_MASK;
743fb4d8502Sjsg 
744fb4d8502Sjsg 	WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
745fb4d8502Sjsg }
746fb4d8502Sjsg 
vcn_1_0_enable_static_power_gating(struct amdgpu_device * adev)747fb4d8502Sjsg static void vcn_1_0_enable_static_power_gating(struct amdgpu_device *adev)
748fb4d8502Sjsg {
749fb4d8502Sjsg 	uint32_t data = 0;
750fb4d8502Sjsg 
751fb4d8502Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
752fb4d8502Sjsg 		/* Before power off, this indicator has to be turned on */
753fb4d8502Sjsg 		data = RREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS);
754fb4d8502Sjsg 		data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;
755fb4d8502Sjsg 		data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;
756fb4d8502Sjsg 		WREG32_SOC15(VCN, 0, mmUVD_POWER_STATUS, data);
757fb4d8502Sjsg 
758fb4d8502Sjsg 
759fb4d8502Sjsg 		data = (2 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
760fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
761fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
762fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
763fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
764fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDIL_PWR_CONFIG__SHIFT
765fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDIR_PWR_CONFIG__SHIFT
766fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
767fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
768fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
769fb4d8502Sjsg 			| 2 << UVD_PGFSM_CONFIG__UVDW_PWR_CONFIG__SHIFT);
770fb4d8502Sjsg 
771fb4d8502Sjsg 		WREG32_SOC15(VCN, 0, mmUVD_PGFSM_CONFIG, data);
772fb4d8502Sjsg 
773fb4d8502Sjsg 		data = (2 << UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT
774fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDU_PWR_STATUS__SHIFT
775fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT
776fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDC_PWR_STATUS__SHIFT
777fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT
778fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDIL_PWR_STATUS__SHIFT
779fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDIR_PWR_STATUS__SHIFT
780fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT
781fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT
782fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT
783fb4d8502Sjsg 			| 2 << UVD_PGFSM_STATUS__UVDW_PWR_STATUS__SHIFT);
784ad8b1aafSjsg 		SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS, data, 0xFFFFFFFF);
785fb4d8502Sjsg 	}
786fb4d8502Sjsg }
787fb4d8502Sjsg 
788fb4d8502Sjsg /**
7895ca02815Sjsg  * vcn_v1_0_start_spg_mode - start VCN block
790fb4d8502Sjsg  *
791fb4d8502Sjsg  * @adev: amdgpu_device pointer
792fb4d8502Sjsg  *
793fb4d8502Sjsg  * Setup and start the VCN block
794fb4d8502Sjsg  */
vcn_v1_0_start_spg_mode(struct amdgpu_device * adev)795c349dbc7Sjsg static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
796fb4d8502Sjsg {
797c349dbc7Sjsg 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
798fb4d8502Sjsg 	uint32_t rb_bufsz, tmp;
799fb4d8502Sjsg 	uint32_t lmi_swap_cntl;
800fb4d8502Sjsg 	int i, j, r;
801fb4d8502Sjsg 
802fb4d8502Sjsg 	/* disable byte swapping */
803fb4d8502Sjsg 	lmi_swap_cntl = 0;
804fb4d8502Sjsg 
805fb4d8502Sjsg 	vcn_1_0_disable_static_power_gating(adev);
806c349dbc7Sjsg 
807c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
808c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp);
809c349dbc7Sjsg 
810fb4d8502Sjsg 	/* disable clock gating */
811fb4d8502Sjsg 	vcn_v1_0_disable_clock_gating(adev);
812fb4d8502Sjsg 
813fb4d8502Sjsg 	/* disable interupt */
814fb4d8502Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), 0,
815fb4d8502Sjsg 			~UVD_MASTINT_EN__VCPU_EN_MASK);
816fb4d8502Sjsg 
817fb4d8502Sjsg 	/* initialize VCN memory controller */
818c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_LMI_CTRL);
819c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_CTRL, tmp		|
820fb4d8502Sjsg 		UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK	|
821c349dbc7Sjsg 		UVD_LMI_CTRL__MASK_MC_URGENT_MASK			|
822fb4d8502Sjsg 		UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK		|
823c349dbc7Sjsg 		UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
824fb4d8502Sjsg 
825fb4d8502Sjsg #ifdef __BIG_ENDIAN
826fb4d8502Sjsg 	/* swap (8 in 32) RB and IB */
827fb4d8502Sjsg 	lmi_swap_cntl = 0xa;
828fb4d8502Sjsg #endif
829fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_SWAP_CNTL, lmi_swap_cntl);
830fb4d8502Sjsg 
831c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_MPC_CNTL);
832c349dbc7Sjsg 	tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
833c349dbc7Sjsg 	tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
834c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MPC_CNTL, tmp);
835fb4d8502Sjsg 
836c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MPC_SET_MUXA0,
837c349dbc7Sjsg 		((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
838c349dbc7Sjsg 		(0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
839c349dbc7Sjsg 		(0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
840c349dbc7Sjsg 		(0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
841c349dbc7Sjsg 
842c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MPC_SET_MUXB0,
843c349dbc7Sjsg 		((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
844c349dbc7Sjsg 		(0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
845c349dbc7Sjsg 		(0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
846c349dbc7Sjsg 		(0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
847c349dbc7Sjsg 
848c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_MPC_SET_MUX,
849c349dbc7Sjsg 		((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
850c349dbc7Sjsg 		(0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
851c349dbc7Sjsg 		(0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
852c349dbc7Sjsg 
853c349dbc7Sjsg 	vcn_v1_0_mc_resume_spg_mode(adev);
854c349dbc7Sjsg 
855c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_REG_XX_MASK_1_0, 0x10);
856c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK_1_0,
857c349dbc7Sjsg 		RREG32_SOC15(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK_1_0) | 0x3);
858fb4d8502Sjsg 
859fb4d8502Sjsg 	/* enable VCPU clock */
860c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_VCPU_CNTL, UVD_VCPU_CNTL__CLK_EN_MASK);
861c349dbc7Sjsg 
862c349dbc7Sjsg 	/* boot up the VCPU */
863c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0,
864c349dbc7Sjsg 			~UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
865fb4d8502Sjsg 
866fb4d8502Sjsg 	/* enable UMC */
867fb4d8502Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2), 0,
868fb4d8502Sjsg 			~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
869fb4d8502Sjsg 
870c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_SOFT_RESET);
871c349dbc7Sjsg 	tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
872c349dbc7Sjsg 	tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
873c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_SOFT_RESET, tmp);
874fb4d8502Sjsg 
875fb4d8502Sjsg 	for (i = 0; i < 10; ++i) {
876fb4d8502Sjsg 		uint32_t status;
877fb4d8502Sjsg 
878fb4d8502Sjsg 		for (j = 0; j < 100; ++j) {
879fb4d8502Sjsg 			status = RREG32_SOC15(UVD, 0, mmUVD_STATUS);
880c349dbc7Sjsg 			if (status & UVD_STATUS__IDLE)
881fb4d8502Sjsg 				break;
882fb4d8502Sjsg 			mdelay(10);
883fb4d8502Sjsg 		}
884fb4d8502Sjsg 		r = 0;
885c349dbc7Sjsg 		if (status & UVD_STATUS__IDLE)
886fb4d8502Sjsg 			break;
887fb4d8502Sjsg 
888fb4d8502Sjsg 		DRM_ERROR("VCN decode not responding, trying to reset the VCPU!!!\n");
889fb4d8502Sjsg 		WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET),
890fb4d8502Sjsg 				UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK,
891fb4d8502Sjsg 				~UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
892fb4d8502Sjsg 		mdelay(10);
893fb4d8502Sjsg 		WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0,
894fb4d8502Sjsg 				~UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
895fb4d8502Sjsg 		mdelay(10);
896fb4d8502Sjsg 		r = -1;
897fb4d8502Sjsg 	}
898fb4d8502Sjsg 
899fb4d8502Sjsg 	if (r) {
900fb4d8502Sjsg 		DRM_ERROR("VCN decode not responding, giving up!!!\n");
901fb4d8502Sjsg 		return r;
902fb4d8502Sjsg 	}
903fb4d8502Sjsg 	/* enable master interrupt */
904fb4d8502Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN),
905c349dbc7Sjsg 		UVD_MASTINT_EN__VCPU_EN_MASK, ~UVD_MASTINT_EN__VCPU_EN_MASK);
906fb4d8502Sjsg 
907c349dbc7Sjsg 	/* enable system interrupt for JRBC, TODO: move to set interrupt*/
908c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SYS_INT_EN),
909c349dbc7Sjsg 		UVD_SYS_INT_EN__UVD_JRBC_EN_MASK,
910c349dbc7Sjsg 		~UVD_SYS_INT_EN__UVD_JRBC_EN_MASK);
911c349dbc7Sjsg 
912c349dbc7Sjsg 	/* clear the busy bit of UVD_STATUS */
913c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_STATUS) & ~UVD_STATUS__UVD_BUSY;
914c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_STATUS, tmp);
915fb4d8502Sjsg 
916fb4d8502Sjsg 	/* force RBC into idle state */
917fb4d8502Sjsg 	rb_bufsz = order_base_2(ring->ring_size);
918fb4d8502Sjsg 	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
919fb4d8502Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
920fb4d8502Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
921fb4d8502Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
922fb4d8502Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
923fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_CNTL, tmp);
924fb4d8502Sjsg 
925fb4d8502Sjsg 	/* set the write pointer delay */
926fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR_CNTL, 0);
927fb4d8502Sjsg 
928fb4d8502Sjsg 	/* set the wb address */
929fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR,
930fb4d8502Sjsg 			(upper_32_bits(ring->gpu_addr) >> 2));
931fb4d8502Sjsg 
932ad8b1aafSjsg 	/* program the RB_BASE for ring buffer */
933fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
934fb4d8502Sjsg 			lower_32_bits(ring->gpu_addr));
935fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
936fb4d8502Sjsg 			upper_32_bits(ring->gpu_addr));
937fb4d8502Sjsg 
938fb4d8502Sjsg 	/* Initialize the ring buffer's read and write pointers */
939fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR, 0);
940fb4d8502Sjsg 
941c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_SCRATCH2, 0);
942c349dbc7Sjsg 
943fb4d8502Sjsg 	ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR);
944fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
945fb4d8502Sjsg 			lower_32_bits(ring->wptr));
946fb4d8502Sjsg 
947fb4d8502Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), 0,
948fb4d8502Sjsg 			~UVD_RBC_RB_CNTL__RB_NO_FETCH_MASK);
949fb4d8502Sjsg 
950c349dbc7Sjsg 	ring = &adev->vcn.inst->ring_enc[0];
951fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
952fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
953fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO, ring->gpu_addr);
954fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
955fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE, ring->ring_size / 4);
956fb4d8502Sjsg 
957c349dbc7Sjsg 	ring = &adev->vcn.inst->ring_enc[1];
958fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
959fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
960fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO2, ring->gpu_addr);
961fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
962fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE2, ring->ring_size / 4);
963fb4d8502Sjsg 
964c349dbc7Sjsg 	jpeg_v1_0_start(adev, 0);
965fb4d8502Sjsg 
966fb4d8502Sjsg 	return 0;
967fb4d8502Sjsg }
968fb4d8502Sjsg 
vcn_v1_0_start_dpg_mode(struct amdgpu_device * adev)969c349dbc7Sjsg static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
970c349dbc7Sjsg {
971c349dbc7Sjsg 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
972c349dbc7Sjsg 	uint32_t rb_bufsz, tmp;
973c349dbc7Sjsg 	uint32_t lmi_swap_cntl;
974c349dbc7Sjsg 
975c349dbc7Sjsg 	/* disable byte swapping */
976c349dbc7Sjsg 	lmi_swap_cntl = 0;
977c349dbc7Sjsg 
978c349dbc7Sjsg 	vcn_1_0_enable_static_power_gating(adev);
979c349dbc7Sjsg 
980c349dbc7Sjsg 	/* enable dynamic power gating mode */
981c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
982c349dbc7Sjsg 	tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;
983c349dbc7Sjsg 	tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK;
984c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS, tmp);
985c349dbc7Sjsg 
986c349dbc7Sjsg 	/* enable clock gating */
987c349dbc7Sjsg 	vcn_v1_0_clock_gating_dpg_mode(adev, 0);
988c349dbc7Sjsg 
989c349dbc7Sjsg 	/* enable VCPU clock */
990c349dbc7Sjsg 	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
991c349dbc7Sjsg 	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
992c349dbc7Sjsg 	tmp |= UVD_VCPU_CNTL__MIF_WR_LOW_THRESHOLD_BP_MASK;
993ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_VCPU_CNTL, tmp, 0xFFFFFFFF, 0);
994c349dbc7Sjsg 
995c349dbc7Sjsg 	/* disable interupt */
996ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MASTINT_EN,
997c349dbc7Sjsg 			0, UVD_MASTINT_EN__VCPU_EN_MASK, 0);
998c349dbc7Sjsg 
999c349dbc7Sjsg 	/* initialize VCN memory controller */
1000ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_CTRL,
1001c349dbc7Sjsg 		(8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
1002c349dbc7Sjsg 		UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
1003c349dbc7Sjsg 		UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
1004c349dbc7Sjsg 		UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
1005c349dbc7Sjsg 		UVD_LMI_CTRL__REQ_MODE_MASK |
1006c349dbc7Sjsg 		UVD_LMI_CTRL__CRC_RESET_MASK |
1007c349dbc7Sjsg 		UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
1008c349dbc7Sjsg 		0x00100000L, 0xFFFFFFFF, 0);
1009c349dbc7Sjsg 
1010c349dbc7Sjsg #ifdef __BIG_ENDIAN
1011c349dbc7Sjsg 	/* swap (8 in 32) RB and IB */
1012c349dbc7Sjsg 	lmi_swap_cntl = 0xa;
1013c349dbc7Sjsg #endif
1014ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_SWAP_CNTL, lmi_swap_cntl, 0xFFFFFFFF, 0);
1015c349dbc7Sjsg 
1016ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MPC_CNTL,
1017c349dbc7Sjsg 		0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0xFFFFFFFF, 0);
1018c349dbc7Sjsg 
1019ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MPC_SET_MUXA0,
1020c349dbc7Sjsg 		((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
1021c349dbc7Sjsg 		 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
1022c349dbc7Sjsg 		 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
1023c349dbc7Sjsg 		 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0xFFFFFFFF, 0);
1024c349dbc7Sjsg 
1025ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MPC_SET_MUXB0,
1026c349dbc7Sjsg 		((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
1027c349dbc7Sjsg 		 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
1028c349dbc7Sjsg 		 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
1029c349dbc7Sjsg 		 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0xFFFFFFFF, 0);
1030c349dbc7Sjsg 
1031ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MPC_SET_MUX,
1032c349dbc7Sjsg 		((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
1033c349dbc7Sjsg 		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
1034c349dbc7Sjsg 		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0xFFFFFFFF, 0);
1035c349dbc7Sjsg 
1036c349dbc7Sjsg 	vcn_v1_0_mc_resume_dpg_mode(adev);
1037c349dbc7Sjsg 
1038ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_REG_XX_MASK, 0x10, 0xFFFFFFFF, 0);
1039ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_RBC_XX_IB_REG_CHECK, 0x3, 0xFFFFFFFF, 0);
1040c349dbc7Sjsg 
1041c349dbc7Sjsg 	/* boot up the VCPU */
1042ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SOFT_RESET, 0, 0xFFFFFFFF, 0);
1043c349dbc7Sjsg 
1044c349dbc7Sjsg 	/* enable UMC */
1045ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_CTRL2,
1046c349dbc7Sjsg 		0x1F << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT,
1047c349dbc7Sjsg 		0xFFFFFFFF, 0);
1048c349dbc7Sjsg 
1049c349dbc7Sjsg 	/* enable master interrupt */
1050ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_MASTINT_EN,
1051c349dbc7Sjsg 			UVD_MASTINT_EN__VCPU_EN_MASK, UVD_MASTINT_EN__VCPU_EN_MASK, 0);
1052c349dbc7Sjsg 
1053c349dbc7Sjsg 	vcn_v1_0_clock_gating_dpg_mode(adev, 1);
1054c349dbc7Sjsg 	/* setup mmUVD_LMI_CTRL */
1055ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_LMI_CTRL,
1056c349dbc7Sjsg 		(8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
1057c349dbc7Sjsg 		UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
1058c349dbc7Sjsg 		UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
1059c349dbc7Sjsg 		UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
1060c349dbc7Sjsg 		UVD_LMI_CTRL__REQ_MODE_MASK |
1061c349dbc7Sjsg 		UVD_LMI_CTRL__CRC_RESET_MASK |
1062c349dbc7Sjsg 		UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
1063c349dbc7Sjsg 		0x00100000L, 0xFFFFFFFF, 1);
1064c349dbc7Sjsg 
1065c349dbc7Sjsg 	tmp = adev->gfx.config.gb_addr_config;
1066c349dbc7Sjsg 	/* setup VCN global tiling registers */
1067ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_JPEG_ADDR_CONFIG, tmp, 0xFFFFFFFF, 1);
1068ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_JPEG_UV_ADDR_CONFIG, tmp, 0xFFFFFFFF, 1);
1069c349dbc7Sjsg 
1070c349dbc7Sjsg 	/* enable System Interrupt for JRBC */
1071ad8b1aafSjsg 	WREG32_SOC15_DPG_MODE_1_0(UVD, 0, mmUVD_SYS_INT_EN,
1072c349dbc7Sjsg 									UVD_SYS_INT_EN__UVD_JRBC_EN_MASK, 0xFFFFFFFF, 1);
1073c349dbc7Sjsg 
1074c349dbc7Sjsg 	/* force RBC into idle state */
1075c349dbc7Sjsg 	rb_bufsz = order_base_2(ring->ring_size);
1076c349dbc7Sjsg 	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);
1077c349dbc7Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
1078c349dbc7Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
1079c349dbc7Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
1080c349dbc7Sjsg 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
1081c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_CNTL, tmp);
1082c349dbc7Sjsg 
1083c349dbc7Sjsg 	/* set the write pointer delay */
1084c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR_CNTL, 0);
1085c349dbc7Sjsg 
1086c349dbc7Sjsg 	/* set the wb address */
1087c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR,
1088c349dbc7Sjsg 								(upper_32_bits(ring->gpu_addr) >> 2));
1089c349dbc7Sjsg 
1090ad8b1aafSjsg 	/* program the RB_BASE for ring buffer */
1091c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,
1092c349dbc7Sjsg 								lower_32_bits(ring->gpu_addr));
1093c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,
1094c349dbc7Sjsg 								upper_32_bits(ring->gpu_addr));
1095c349dbc7Sjsg 
1096c349dbc7Sjsg 	/* Initialize the ring buffer's read and write pointers */
1097c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR, 0);
1098c349dbc7Sjsg 
1099c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_SCRATCH2, 0);
1100c349dbc7Sjsg 
1101c349dbc7Sjsg 	ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR);
1102c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
1103c349dbc7Sjsg 								lower_32_bits(ring->wptr));
1104c349dbc7Sjsg 
1105c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), 0,
1106c349dbc7Sjsg 			~UVD_RBC_RB_CNTL__RB_NO_FETCH_MASK);
1107c349dbc7Sjsg 
1108c349dbc7Sjsg 	jpeg_v1_0_start(adev, 1);
1109c349dbc7Sjsg 
1110c349dbc7Sjsg 	return 0;
1111c349dbc7Sjsg }
1112c349dbc7Sjsg 
vcn_v1_0_start(struct amdgpu_device * adev)1113c349dbc7Sjsg static int vcn_v1_0_start(struct amdgpu_device *adev)
1114c349dbc7Sjsg {
11151bb76ff1Sjsg 	return (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ?
11161bb76ff1Sjsg 		vcn_v1_0_start_dpg_mode(adev) : vcn_v1_0_start_spg_mode(adev);
1117c349dbc7Sjsg }
1118c349dbc7Sjsg 
1119fb4d8502Sjsg /**
11205ca02815Sjsg  * vcn_v1_0_stop_spg_mode - stop VCN block
1121fb4d8502Sjsg  *
1122fb4d8502Sjsg  * @adev: amdgpu_device pointer
1123fb4d8502Sjsg  *
1124fb4d8502Sjsg  * stop the VCN block
1125fb4d8502Sjsg  */
vcn_v1_0_stop_spg_mode(struct amdgpu_device * adev)1126c349dbc7Sjsg static int vcn_v1_0_stop_spg_mode(struct amdgpu_device *adev)
1127fb4d8502Sjsg {
1128ad8b1aafSjsg 	int tmp;
1129fb4d8502Sjsg 
1130ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_STATUS, UVD_STATUS__IDLE, 0x7);
1131c349dbc7Sjsg 
1132c349dbc7Sjsg 	tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
1133c349dbc7Sjsg 		UVD_LMI_STATUS__READ_CLEAN_MASK |
1134c349dbc7Sjsg 		UVD_LMI_STATUS__WRITE_CLEAN_MASK |
1135c349dbc7Sjsg 		UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
1136ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_LMI_STATUS, tmp, tmp);
1137fb4d8502Sjsg 
11385ca02815Sjsg 	/* stall UMC channel */
11395ca02815Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2),
11405ca02815Sjsg 		UVD_LMI_CTRL2__STALL_ARB_UMC_MASK,
11415ca02815Sjsg 		~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
1142c349dbc7Sjsg 
1143c349dbc7Sjsg 	tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
1144c349dbc7Sjsg 		UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
1145ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_LMI_STATUS, tmp, tmp);
1146fb4d8502Sjsg 
1147fb4d8502Sjsg 	/* disable VCPU clock */
1148c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CNTL), 0,
1149c349dbc7Sjsg 		~UVD_VCPU_CNTL__CLK_EN_MASK);
1150fb4d8502Sjsg 
1151c349dbc7Sjsg 	/* reset LMI UMC/LMI */
1152c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET),
1153c349dbc7Sjsg 		UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK,
1154c349dbc7Sjsg 		~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK);
1155fb4d8502Sjsg 
1156c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET),
1157c349dbc7Sjsg 		UVD_SOFT_RESET__LMI_SOFT_RESET_MASK,
1158c349dbc7Sjsg 		~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK);
1159c349dbc7Sjsg 
11605ca02815Sjsg 	/* put VCPU into reset */
11615ca02815Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET),
11625ca02815Sjsg 		UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK,
11635ca02815Sjsg 		~UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
11645ca02815Sjsg 
1165c349dbc7Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_STATUS, 0);
1166fb4d8502Sjsg 
1167fb4d8502Sjsg 	vcn_v1_0_enable_clock_gating(adev);
1168fb4d8502Sjsg 	vcn_1_0_enable_static_power_gating(adev);
1169fb4d8502Sjsg 	return 0;
1170fb4d8502Sjsg }
1171fb4d8502Sjsg 
vcn_v1_0_stop_dpg_mode(struct amdgpu_device * adev)1172c349dbc7Sjsg static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev)
1173c349dbc7Sjsg {
1174c349dbc7Sjsg 	uint32_t tmp;
1175c349dbc7Sjsg 
1176c349dbc7Sjsg 	/* Wait for power status to be UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF */
1177c349dbc7Sjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
1178c349dbc7Sjsg 			UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
1179ad8b1aafSjsg 			UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1180c349dbc7Sjsg 
1181c349dbc7Sjsg 	/* wait for read ptr to be equal to write ptr */
1182c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_RB_WPTR);
1183ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_RB_RPTR, tmp, 0xFFFFFFFF);
1184c349dbc7Sjsg 
1185c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2);
1186ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_RB_RPTR2, tmp, 0xFFFFFFFF);
1187c349dbc7Sjsg 
1188c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
1189ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_JRBC_RB_RPTR, tmp, 0xFFFFFFFF);
1190c349dbc7Sjsg 
1191c349dbc7Sjsg 	tmp = RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR) & 0x7FFFFFFF;
1192ad8b1aafSjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_RBC_RB_RPTR, tmp, 0xFFFFFFFF);
1193c349dbc7Sjsg 
1194c349dbc7Sjsg 	SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
1195c349dbc7Sjsg 		UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
1196ad8b1aafSjsg 		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1197c349dbc7Sjsg 
1198c349dbc7Sjsg 	/* disable dynamic power gating mode */
1199c349dbc7Sjsg 	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS), 0,
1200c349dbc7Sjsg 			~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
1201c349dbc7Sjsg 
1202c349dbc7Sjsg 	return 0;
1203c349dbc7Sjsg }
1204c349dbc7Sjsg 
vcn_v1_0_stop(struct amdgpu_device * adev)1205c349dbc7Sjsg static int vcn_v1_0_stop(struct amdgpu_device *adev)
1206c349dbc7Sjsg {
1207c349dbc7Sjsg 	int r;
1208c349dbc7Sjsg 
1209c349dbc7Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
1210c349dbc7Sjsg 		r = vcn_v1_0_stop_dpg_mode(adev);
1211c349dbc7Sjsg 	else
1212c349dbc7Sjsg 		r = vcn_v1_0_stop_spg_mode(adev);
1213c349dbc7Sjsg 
1214c349dbc7Sjsg 	return r;
1215c349dbc7Sjsg }
1216c349dbc7Sjsg 
vcn_v1_0_pause_dpg_mode(struct amdgpu_device * adev,int inst_idx,struct dpg_pause_state * new_state)1217c349dbc7Sjsg static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
1218c349dbc7Sjsg 				int inst_idx, struct dpg_pause_state *new_state)
1219c349dbc7Sjsg {
1220c349dbc7Sjsg 	int ret_code;
1221c349dbc7Sjsg 	uint32_t reg_data = 0;
1222c349dbc7Sjsg 	uint32_t reg_data2 = 0;
1223c349dbc7Sjsg 	struct amdgpu_ring *ring;
1224c349dbc7Sjsg 
1225c349dbc7Sjsg 	/* pause/unpause if state is changed */
1226c349dbc7Sjsg 	if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
1227c349dbc7Sjsg 		DRM_DEBUG("dpg pause state changed %d:%d -> %d:%d",
1228c349dbc7Sjsg 			adev->vcn.inst[inst_idx].pause_state.fw_based,
1229c349dbc7Sjsg 			adev->vcn.inst[inst_idx].pause_state.jpeg,
1230c349dbc7Sjsg 			new_state->fw_based, new_state->jpeg);
1231c349dbc7Sjsg 
1232c349dbc7Sjsg 		reg_data = RREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE) &
1233c349dbc7Sjsg 			(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
1234c349dbc7Sjsg 
1235c349dbc7Sjsg 		if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
1236c349dbc7Sjsg 			ret_code = 0;
1237c349dbc7Sjsg 
1238c349dbc7Sjsg 			if (!(reg_data & UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK))
1239ad8b1aafSjsg 				ret_code = SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
1240c349dbc7Sjsg 						   UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
1241ad8b1aafSjsg 						   UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1242c349dbc7Sjsg 
1243c349dbc7Sjsg 			if (!ret_code) {
1244c349dbc7Sjsg 				/* pause DPG non-jpeg */
1245c349dbc7Sjsg 				reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
1246c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
1247c349dbc7Sjsg 				SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_DPG_PAUSE,
1248c349dbc7Sjsg 						   UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
1249ad8b1aafSjsg 						   UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
1250c349dbc7Sjsg 
1251c349dbc7Sjsg 				/* Restore */
1252c349dbc7Sjsg 				ring = &adev->vcn.inst->ring_enc[0];
1253c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO, ring->gpu_addr);
1254c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
1255c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE, ring->ring_size / 4);
1256c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_RPTR, lower_32_bits(ring->wptr));
1257c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
1258c349dbc7Sjsg 
1259c349dbc7Sjsg 				ring = &adev->vcn.inst->ring_enc[1];
1260c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO2, ring->gpu_addr);
1261c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
1262c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE2, ring->ring_size / 4);
1263c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
1264c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
1265c349dbc7Sjsg 
1266c349dbc7Sjsg 				ring = &adev->vcn.inst->ring_dec;
1267c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
1268c349dbc7Sjsg 						   RREG32_SOC15(UVD, 0, mmUVD_SCRATCH2) & 0x7FFFFFFF);
1269c349dbc7Sjsg 				SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
1270c349dbc7Sjsg 						   UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
1271ad8b1aafSjsg 						   UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1272c349dbc7Sjsg 			}
1273c349dbc7Sjsg 		} else {
1274c349dbc7Sjsg 			/* unpause dpg non-jpeg, no need to wait */
1275c349dbc7Sjsg 			reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
1276c349dbc7Sjsg 			WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
1277c349dbc7Sjsg 		}
1278c349dbc7Sjsg 		adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
1279c349dbc7Sjsg 	}
1280c349dbc7Sjsg 
1281c349dbc7Sjsg 	/* pause/unpause if state is changed */
1282c349dbc7Sjsg 	if (adev->vcn.inst[inst_idx].pause_state.jpeg != new_state->jpeg) {
1283c349dbc7Sjsg 		DRM_DEBUG("dpg pause state changed %d:%d -> %d:%d",
1284c349dbc7Sjsg 			adev->vcn.inst[inst_idx].pause_state.fw_based,
1285c349dbc7Sjsg 			adev->vcn.inst[inst_idx].pause_state.jpeg,
1286c349dbc7Sjsg 			new_state->fw_based, new_state->jpeg);
1287c349dbc7Sjsg 
1288c349dbc7Sjsg 		reg_data = RREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE) &
1289c349dbc7Sjsg 			(~UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK);
1290c349dbc7Sjsg 
1291c349dbc7Sjsg 		if (new_state->jpeg == VCN_DPG_STATE__PAUSE) {
1292c349dbc7Sjsg 			ret_code = 0;
1293c349dbc7Sjsg 
1294c349dbc7Sjsg 			if (!(reg_data & UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK))
1295ad8b1aafSjsg 				ret_code = SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
1296c349dbc7Sjsg 						   UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
1297ad8b1aafSjsg 						   UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1298c349dbc7Sjsg 
1299c349dbc7Sjsg 			if (!ret_code) {
1300c349dbc7Sjsg 				/* Make sure JPRG Snoop is disabled before sending the pause */
1301c349dbc7Sjsg 				reg_data2 = RREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS);
1302c349dbc7Sjsg 				reg_data2 |= UVD_POWER_STATUS__JRBC_SNOOP_DIS_MASK;
1303c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_POWER_STATUS, reg_data2);
1304c349dbc7Sjsg 
1305c349dbc7Sjsg 				/* pause DPG jpeg */
1306c349dbc7Sjsg 				reg_data |= UVD_DPG_PAUSE__JPEG_PAUSE_DPG_REQ_MASK;
1307c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
1308c349dbc7Sjsg 				SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_DPG_PAUSE,
1309c349dbc7Sjsg 							UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK,
1310ad8b1aafSjsg 							UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK);
1311c349dbc7Sjsg 
1312c349dbc7Sjsg 				/* Restore */
1313*f005ef32Sjsg 				ring = adev->jpeg.inst->ring_dec;
1314c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
1315c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL,
1316c349dbc7Sjsg 							UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
1317c349dbc7Sjsg 							UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
1318c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
1319c349dbc7Sjsg 							lower_32_bits(ring->gpu_addr));
1320c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
1321c349dbc7Sjsg 							upper_32_bits(ring->gpu_addr));
1322c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR, ring->wptr);
1323c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, ring->wptr);
1324c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL,
1325c349dbc7Sjsg 							UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
1326c349dbc7Sjsg 
1327c349dbc7Sjsg 				ring = &adev->vcn.inst->ring_dec;
1328c349dbc7Sjsg 				WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
1329c349dbc7Sjsg 						   RREG32_SOC15(UVD, 0, mmUVD_SCRATCH2) & 0x7FFFFFFF);
1330c349dbc7Sjsg 				SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
1331c349dbc7Sjsg 						   UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
1332ad8b1aafSjsg 						   UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1333c349dbc7Sjsg 			}
1334c349dbc7Sjsg 		} else {
1335c349dbc7Sjsg 			/* unpause dpg jpeg, no need to wait */
1336c349dbc7Sjsg 			reg_data &= ~UVD_DPG_PAUSE__JPEG_PAUSE_DPG_REQ_MASK;
1337c349dbc7Sjsg 			WREG32_SOC15(UVD, 0, mmUVD_DPG_PAUSE, reg_data);
1338c349dbc7Sjsg 		}
1339c349dbc7Sjsg 		adev->vcn.inst[inst_idx].pause_state.jpeg = new_state->jpeg;
1340c349dbc7Sjsg 	}
1341c349dbc7Sjsg 
1342c349dbc7Sjsg 	return 0;
1343c349dbc7Sjsg }
1344c349dbc7Sjsg 
vcn_v1_0_is_idle(void * handle)1345fb4d8502Sjsg static bool vcn_v1_0_is_idle(void *handle)
1346fb4d8502Sjsg {
1347fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1348fb4d8502Sjsg 
1349c349dbc7Sjsg 	return (RREG32_SOC15(VCN, 0, mmUVD_STATUS) == UVD_STATUS__IDLE);
1350fb4d8502Sjsg }
1351fb4d8502Sjsg 
vcn_v1_0_wait_for_idle(void * handle)1352fb4d8502Sjsg static int vcn_v1_0_wait_for_idle(void *handle)
1353fb4d8502Sjsg {
1354fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1355ad8b1aafSjsg 	int ret;
1356fb4d8502Sjsg 
1357ad8b1aafSjsg 	ret = SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_STATUS, UVD_STATUS__IDLE,
1358ad8b1aafSjsg 		UVD_STATUS__IDLE);
1359fb4d8502Sjsg 
1360fb4d8502Sjsg 	return ret;
1361fb4d8502Sjsg }
1362fb4d8502Sjsg 
vcn_v1_0_set_clockgating_state(void * handle,enum amd_clockgating_state state)1363fb4d8502Sjsg static int vcn_v1_0_set_clockgating_state(void *handle,
1364fb4d8502Sjsg 					  enum amd_clockgating_state state)
1365fb4d8502Sjsg {
1366fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1367c349dbc7Sjsg 	bool enable = (state == AMD_CG_STATE_GATE);
1368fb4d8502Sjsg 
1369fb4d8502Sjsg 	if (enable) {
1370fb4d8502Sjsg 		/* wait for STATUS to clear */
1371a928e695Sjsg 		if (!vcn_v1_0_is_idle(handle))
1372fb4d8502Sjsg 			return -EBUSY;
1373fb4d8502Sjsg 		vcn_v1_0_enable_clock_gating(adev);
1374fb4d8502Sjsg 	} else {
1375fb4d8502Sjsg 		/* disable HW gating and enable Sw gating */
1376fb4d8502Sjsg 		vcn_v1_0_disable_clock_gating(adev);
1377fb4d8502Sjsg 	}
1378fb4d8502Sjsg 	return 0;
1379fb4d8502Sjsg }
1380fb4d8502Sjsg 
1381fb4d8502Sjsg /**
1382fb4d8502Sjsg  * vcn_v1_0_dec_ring_get_rptr - get read pointer
1383fb4d8502Sjsg  *
1384fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1385fb4d8502Sjsg  *
1386fb4d8502Sjsg  * Returns the current hardware read pointer
1387fb4d8502Sjsg  */
vcn_v1_0_dec_ring_get_rptr(struct amdgpu_ring * ring)1388fb4d8502Sjsg static uint64_t vcn_v1_0_dec_ring_get_rptr(struct amdgpu_ring *ring)
1389fb4d8502Sjsg {
1390fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1391fb4d8502Sjsg 
1392fb4d8502Sjsg 	return RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR);
1393fb4d8502Sjsg }
1394fb4d8502Sjsg 
1395fb4d8502Sjsg /**
1396fb4d8502Sjsg  * vcn_v1_0_dec_ring_get_wptr - get write pointer
1397fb4d8502Sjsg  *
1398fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1399fb4d8502Sjsg  *
1400fb4d8502Sjsg  * Returns the current hardware write pointer
1401fb4d8502Sjsg  */
vcn_v1_0_dec_ring_get_wptr(struct amdgpu_ring * ring)1402fb4d8502Sjsg static uint64_t vcn_v1_0_dec_ring_get_wptr(struct amdgpu_ring *ring)
1403fb4d8502Sjsg {
1404fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1405fb4d8502Sjsg 
1406fb4d8502Sjsg 	return RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR);
1407fb4d8502Sjsg }
1408fb4d8502Sjsg 
1409fb4d8502Sjsg /**
1410fb4d8502Sjsg  * vcn_v1_0_dec_ring_set_wptr - set write pointer
1411fb4d8502Sjsg  *
1412fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1413fb4d8502Sjsg  *
1414fb4d8502Sjsg  * Commits the write pointer to the hardware
1415fb4d8502Sjsg  */
vcn_v1_0_dec_ring_set_wptr(struct amdgpu_ring * ring)1416fb4d8502Sjsg static void vcn_v1_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
1417fb4d8502Sjsg {
1418fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1419fb4d8502Sjsg 
1420c349dbc7Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
1421c349dbc7Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_SCRATCH2,
1422c349dbc7Sjsg 			lower_32_bits(ring->wptr) | 0x80000000);
1423c349dbc7Sjsg 
1424fb4d8502Sjsg 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR, lower_32_bits(ring->wptr));
1425fb4d8502Sjsg }
1426fb4d8502Sjsg 
1427fb4d8502Sjsg /**
1428fb4d8502Sjsg  * vcn_v1_0_dec_ring_insert_start - insert a start command
1429fb4d8502Sjsg  *
1430fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1431fb4d8502Sjsg  *
1432fb4d8502Sjsg  * Write a start command to the ring.
1433fb4d8502Sjsg  */
vcn_v1_0_dec_ring_insert_start(struct amdgpu_ring * ring)1434fb4d8502Sjsg static void vcn_v1_0_dec_ring_insert_start(struct amdgpu_ring *ring)
1435fb4d8502Sjsg {
1436fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1437fb4d8502Sjsg 
1438fb4d8502Sjsg 	amdgpu_ring_write(ring,
1439fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0));
1440fb4d8502Sjsg 	amdgpu_ring_write(ring, 0);
1441fb4d8502Sjsg 	amdgpu_ring_write(ring,
1442fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0));
1443fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_START << 1);
1444fb4d8502Sjsg }
1445fb4d8502Sjsg 
1446fb4d8502Sjsg /**
1447fb4d8502Sjsg  * vcn_v1_0_dec_ring_insert_end - insert a end command
1448fb4d8502Sjsg  *
1449fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1450fb4d8502Sjsg  *
1451fb4d8502Sjsg  * Write a end command to the ring.
1452fb4d8502Sjsg  */
vcn_v1_0_dec_ring_insert_end(struct amdgpu_ring * ring)1453fb4d8502Sjsg static void vcn_v1_0_dec_ring_insert_end(struct amdgpu_ring *ring)
1454fb4d8502Sjsg {
1455fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1456fb4d8502Sjsg 
1457fb4d8502Sjsg 	amdgpu_ring_write(ring,
1458fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0));
1459fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_DEC_CMD_PACKET_END << 1);
1460fb4d8502Sjsg }
1461fb4d8502Sjsg 
1462fb4d8502Sjsg /**
1463fb4d8502Sjsg  * vcn_v1_0_dec_ring_emit_fence - emit an fence & trap command
1464fb4d8502Sjsg  *
1465fb4d8502Sjsg  * @ring: amdgpu_ring pointer
14665ca02815Sjsg  * @addr: address
14675ca02815Sjsg  * @seq: sequence number
14685ca02815Sjsg  * @flags: fence related flags
1469fb4d8502Sjsg  *
1470fb4d8502Sjsg  * Write a fence and a trap command to the ring.
1471fb4d8502Sjsg  */
vcn_v1_0_dec_ring_emit_fence(struct amdgpu_ring * ring,u64 addr,u64 seq,unsigned flags)1472fb4d8502Sjsg static void vcn_v1_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
1473fb4d8502Sjsg 				     unsigned flags)
1474fb4d8502Sjsg {
1475fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1476fb4d8502Sjsg 
1477fb4d8502Sjsg 	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
1478fb4d8502Sjsg 
1479fb4d8502Sjsg 	amdgpu_ring_write(ring,
1480fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_CONTEXT_ID), 0));
1481fb4d8502Sjsg 	amdgpu_ring_write(ring, seq);
1482fb4d8502Sjsg 	amdgpu_ring_write(ring,
1483fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0));
1484fb4d8502Sjsg 	amdgpu_ring_write(ring, addr & 0xffffffff);
1485fb4d8502Sjsg 	amdgpu_ring_write(ring,
1486fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1), 0));
1487fb4d8502Sjsg 	amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);
1488fb4d8502Sjsg 	amdgpu_ring_write(ring,
1489fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0));
1490fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_DEC_CMD_FENCE << 1);
1491fb4d8502Sjsg 
1492fb4d8502Sjsg 	amdgpu_ring_write(ring,
1493fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0));
1494fb4d8502Sjsg 	amdgpu_ring_write(ring, 0);
1495fb4d8502Sjsg 	amdgpu_ring_write(ring,
1496fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1), 0));
1497fb4d8502Sjsg 	amdgpu_ring_write(ring, 0);
1498fb4d8502Sjsg 	amdgpu_ring_write(ring,
1499fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0));
1500fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_DEC_CMD_TRAP << 1);
1501fb4d8502Sjsg }
1502fb4d8502Sjsg 
1503fb4d8502Sjsg /**
1504fb4d8502Sjsg  * vcn_v1_0_dec_ring_emit_ib - execute indirect buffer
1505fb4d8502Sjsg  *
1506fb4d8502Sjsg  * @ring: amdgpu_ring pointer
15075ca02815Sjsg  * @job: job to retrieve vmid from
1508fb4d8502Sjsg  * @ib: indirect buffer to execute
15095ca02815Sjsg  * @flags: unused
1510fb4d8502Sjsg  *
1511fb4d8502Sjsg  * Write ring commands to execute the indirect buffer
1512fb4d8502Sjsg  */
vcn_v1_0_dec_ring_emit_ib(struct amdgpu_ring * ring,struct amdgpu_job * job,struct amdgpu_ib * ib,uint32_t flags)1513fb4d8502Sjsg static void vcn_v1_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
1514c349dbc7Sjsg 					struct amdgpu_job *job,
1515fb4d8502Sjsg 					struct amdgpu_ib *ib,
1516c349dbc7Sjsg 					uint32_t flags)
1517fb4d8502Sjsg {
1518fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1519c349dbc7Sjsg 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
1520fb4d8502Sjsg 
1521fb4d8502Sjsg 	amdgpu_ring_write(ring,
1522fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_IB_VMID), 0));
1523fb4d8502Sjsg 	amdgpu_ring_write(ring, vmid);
1524fb4d8502Sjsg 
1525fb4d8502Sjsg 	amdgpu_ring_write(ring,
1526fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_IB_64BIT_BAR_LOW), 0));
1527fb4d8502Sjsg 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
1528fb4d8502Sjsg 	amdgpu_ring_write(ring,
1529fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH), 0));
1530fb4d8502Sjsg 	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
1531fb4d8502Sjsg 	amdgpu_ring_write(ring,
1532fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_IB_SIZE), 0));
1533fb4d8502Sjsg 	amdgpu_ring_write(ring, ib->length_dw);
1534fb4d8502Sjsg }
1535fb4d8502Sjsg 
vcn_v1_0_dec_ring_emit_reg_wait(struct amdgpu_ring * ring,uint32_t reg,uint32_t val,uint32_t mask)1536fb4d8502Sjsg static void vcn_v1_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring,
1537fb4d8502Sjsg 					    uint32_t reg, uint32_t val,
1538fb4d8502Sjsg 					    uint32_t mask)
1539fb4d8502Sjsg {
1540fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1541fb4d8502Sjsg 
1542fb4d8502Sjsg 	amdgpu_ring_write(ring,
1543fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0));
1544fb4d8502Sjsg 	amdgpu_ring_write(ring, reg << 2);
1545fb4d8502Sjsg 	amdgpu_ring_write(ring,
1546fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1), 0));
1547fb4d8502Sjsg 	amdgpu_ring_write(ring, val);
1548fb4d8502Sjsg 	amdgpu_ring_write(ring,
1549fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GP_SCRATCH8), 0));
1550fb4d8502Sjsg 	amdgpu_ring_write(ring, mask);
1551fb4d8502Sjsg 	amdgpu_ring_write(ring,
1552fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0));
1553fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_DEC_CMD_REG_READ_COND_WAIT << 1);
1554fb4d8502Sjsg }
1555fb4d8502Sjsg 
vcn_v1_0_dec_ring_emit_vm_flush(struct amdgpu_ring * ring,unsigned vmid,uint64_t pd_addr)1556fb4d8502Sjsg static void vcn_v1_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
1557fb4d8502Sjsg 					    unsigned vmid, uint64_t pd_addr)
1558fb4d8502Sjsg {
1559*f005ef32Sjsg 	struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
1560fb4d8502Sjsg 	uint32_t data0, data1, mask;
1561fb4d8502Sjsg 
1562fb4d8502Sjsg 	pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
1563fb4d8502Sjsg 
1564fb4d8502Sjsg 	/* wait for register write */
1565ad8b1aafSjsg 	data0 = hub->ctx0_ptb_addr_lo32 + vmid * hub->ctx_addr_distance;
1566fb4d8502Sjsg 	data1 = lower_32_bits(pd_addr);
1567fb4d8502Sjsg 	mask = 0xffffffff;
1568fb4d8502Sjsg 	vcn_v1_0_dec_ring_emit_reg_wait(ring, data0, data1, mask);
1569fb4d8502Sjsg }
1570fb4d8502Sjsg 
vcn_v1_0_dec_ring_emit_wreg(struct amdgpu_ring * ring,uint32_t reg,uint32_t val)1571fb4d8502Sjsg static void vcn_v1_0_dec_ring_emit_wreg(struct amdgpu_ring *ring,
1572fb4d8502Sjsg 					uint32_t reg, uint32_t val)
1573fb4d8502Sjsg {
1574fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1575fb4d8502Sjsg 
1576fb4d8502Sjsg 	amdgpu_ring_write(ring,
1577fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA0), 0));
1578fb4d8502Sjsg 	amdgpu_ring_write(ring, reg << 2);
1579fb4d8502Sjsg 	amdgpu_ring_write(ring,
1580fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_DATA1), 0));
1581fb4d8502Sjsg 	amdgpu_ring_write(ring, val);
1582fb4d8502Sjsg 	amdgpu_ring_write(ring,
1583fb4d8502Sjsg 		PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_GPCOM_VCPU_CMD), 0));
1584fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_DEC_CMD_WRITE_REG << 1);
1585fb4d8502Sjsg }
1586fb4d8502Sjsg 
1587fb4d8502Sjsg /**
1588fb4d8502Sjsg  * vcn_v1_0_enc_ring_get_rptr - get enc read pointer
1589fb4d8502Sjsg  *
1590fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1591fb4d8502Sjsg  *
1592fb4d8502Sjsg  * Returns the current hardware enc read pointer
1593fb4d8502Sjsg  */
vcn_v1_0_enc_ring_get_rptr(struct amdgpu_ring * ring)1594fb4d8502Sjsg static uint64_t vcn_v1_0_enc_ring_get_rptr(struct amdgpu_ring *ring)
1595fb4d8502Sjsg {
1596fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1597fb4d8502Sjsg 
1598c349dbc7Sjsg 	if (ring == &adev->vcn.inst->ring_enc[0])
1599fb4d8502Sjsg 		return RREG32_SOC15(UVD, 0, mmUVD_RB_RPTR);
1600fb4d8502Sjsg 	else
1601fb4d8502Sjsg 		return RREG32_SOC15(UVD, 0, mmUVD_RB_RPTR2);
1602fb4d8502Sjsg }
1603fb4d8502Sjsg 
1604fb4d8502Sjsg  /**
1605fb4d8502Sjsg  * vcn_v1_0_enc_ring_get_wptr - get enc write pointer
1606fb4d8502Sjsg  *
1607fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1608fb4d8502Sjsg  *
1609fb4d8502Sjsg  * Returns the current hardware enc write pointer
1610fb4d8502Sjsg  */
vcn_v1_0_enc_ring_get_wptr(struct amdgpu_ring * ring)1611fb4d8502Sjsg static uint64_t vcn_v1_0_enc_ring_get_wptr(struct amdgpu_ring *ring)
1612fb4d8502Sjsg {
1613fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1614fb4d8502Sjsg 
1615c349dbc7Sjsg 	if (ring == &adev->vcn.inst->ring_enc[0])
1616fb4d8502Sjsg 		return RREG32_SOC15(UVD, 0, mmUVD_RB_WPTR);
1617fb4d8502Sjsg 	else
1618fb4d8502Sjsg 		return RREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2);
1619fb4d8502Sjsg }
1620fb4d8502Sjsg 
1621fb4d8502Sjsg  /**
1622fb4d8502Sjsg  * vcn_v1_0_enc_ring_set_wptr - set enc write pointer
1623fb4d8502Sjsg  *
1624fb4d8502Sjsg  * @ring: amdgpu_ring pointer
1625fb4d8502Sjsg  *
1626fb4d8502Sjsg  * Commits the enc write pointer to the hardware
1627fb4d8502Sjsg  */
vcn_v1_0_enc_ring_set_wptr(struct amdgpu_ring * ring)1628fb4d8502Sjsg static void vcn_v1_0_enc_ring_set_wptr(struct amdgpu_ring *ring)
1629fb4d8502Sjsg {
1630fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1631fb4d8502Sjsg 
1632c349dbc7Sjsg 	if (ring == &adev->vcn.inst->ring_enc[0])
1633fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR,
1634fb4d8502Sjsg 			lower_32_bits(ring->wptr));
1635fb4d8502Sjsg 	else
1636fb4d8502Sjsg 		WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2,
1637fb4d8502Sjsg 			lower_32_bits(ring->wptr));
1638fb4d8502Sjsg }
1639fb4d8502Sjsg 
1640fb4d8502Sjsg /**
1641fb4d8502Sjsg  * vcn_v1_0_enc_ring_emit_fence - emit an enc fence & trap command
1642fb4d8502Sjsg  *
1643fb4d8502Sjsg  * @ring: amdgpu_ring pointer
16445ca02815Sjsg  * @addr: address
16455ca02815Sjsg  * @seq: sequence number
16465ca02815Sjsg  * @flags: fence related flags
1647fb4d8502Sjsg  *
1648fb4d8502Sjsg  * Write enc a fence and a trap command to the ring.
1649fb4d8502Sjsg  */
vcn_v1_0_enc_ring_emit_fence(struct amdgpu_ring * ring,u64 addr,u64 seq,unsigned flags)1650fb4d8502Sjsg static void vcn_v1_0_enc_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
1651fb4d8502Sjsg 			u64 seq, unsigned flags)
1652fb4d8502Sjsg {
1653fb4d8502Sjsg 	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
1654fb4d8502Sjsg 
1655fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_ENC_CMD_FENCE);
1656fb4d8502Sjsg 	amdgpu_ring_write(ring, addr);
1657fb4d8502Sjsg 	amdgpu_ring_write(ring, upper_32_bits(addr));
1658fb4d8502Sjsg 	amdgpu_ring_write(ring, seq);
1659fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_ENC_CMD_TRAP);
1660fb4d8502Sjsg }
1661fb4d8502Sjsg 
vcn_v1_0_enc_ring_insert_end(struct amdgpu_ring * ring)1662fb4d8502Sjsg static void vcn_v1_0_enc_ring_insert_end(struct amdgpu_ring *ring)
1663fb4d8502Sjsg {
1664fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_ENC_CMD_END);
1665fb4d8502Sjsg }
1666fb4d8502Sjsg 
1667fb4d8502Sjsg /**
1668fb4d8502Sjsg  * vcn_v1_0_enc_ring_emit_ib - enc execute indirect buffer
1669fb4d8502Sjsg  *
1670fb4d8502Sjsg  * @ring: amdgpu_ring pointer
16715ca02815Sjsg  * @job: job to retrive vmid from
1672fb4d8502Sjsg  * @ib: indirect buffer to execute
16735ca02815Sjsg  * @flags: unused
1674fb4d8502Sjsg  *
1675fb4d8502Sjsg  * Write enc ring commands to execute the indirect buffer
1676fb4d8502Sjsg  */
vcn_v1_0_enc_ring_emit_ib(struct amdgpu_ring * ring,struct amdgpu_job * job,struct amdgpu_ib * ib,uint32_t flags)1677fb4d8502Sjsg static void vcn_v1_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
1678c349dbc7Sjsg 					struct amdgpu_job *job,
1679c349dbc7Sjsg 					struct amdgpu_ib *ib,
1680c349dbc7Sjsg 					uint32_t flags)
1681fb4d8502Sjsg {
1682c349dbc7Sjsg 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
1683c349dbc7Sjsg 
1684fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_ENC_CMD_IB);
1685fb4d8502Sjsg 	amdgpu_ring_write(ring, vmid);
1686fb4d8502Sjsg 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
1687fb4d8502Sjsg 	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
1688fb4d8502Sjsg 	amdgpu_ring_write(ring, ib->length_dw);
1689fb4d8502Sjsg }
1690fb4d8502Sjsg 
vcn_v1_0_enc_ring_emit_reg_wait(struct amdgpu_ring * ring,uint32_t reg,uint32_t val,uint32_t mask)1691fb4d8502Sjsg static void vcn_v1_0_enc_ring_emit_reg_wait(struct amdgpu_ring *ring,
1692fb4d8502Sjsg 					    uint32_t reg, uint32_t val,
1693fb4d8502Sjsg 					    uint32_t mask)
1694fb4d8502Sjsg {
1695fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_ENC_CMD_REG_WAIT);
1696fb4d8502Sjsg 	amdgpu_ring_write(ring, reg << 2);
1697fb4d8502Sjsg 	amdgpu_ring_write(ring, mask);
1698fb4d8502Sjsg 	amdgpu_ring_write(ring, val);
1699fb4d8502Sjsg }
1700fb4d8502Sjsg 
vcn_v1_0_enc_ring_emit_vm_flush(struct amdgpu_ring * ring,unsigned int vmid,uint64_t pd_addr)1701fb4d8502Sjsg static void vcn_v1_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring,
1702fb4d8502Sjsg 					    unsigned int vmid, uint64_t pd_addr)
1703fb4d8502Sjsg {
1704*f005ef32Sjsg 	struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
1705fb4d8502Sjsg 
1706fb4d8502Sjsg 	pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
1707fb4d8502Sjsg 
1708fb4d8502Sjsg 	/* wait for reg writes */
1709ad8b1aafSjsg 	vcn_v1_0_enc_ring_emit_reg_wait(ring, hub->ctx0_ptb_addr_lo32 +
1710ad8b1aafSjsg 					vmid * hub->ctx_addr_distance,
1711fb4d8502Sjsg 					lower_32_bits(pd_addr), 0xffffffff);
1712fb4d8502Sjsg }
1713fb4d8502Sjsg 
vcn_v1_0_enc_ring_emit_wreg(struct amdgpu_ring * ring,uint32_t reg,uint32_t val)1714fb4d8502Sjsg static void vcn_v1_0_enc_ring_emit_wreg(struct amdgpu_ring *ring,
1715fb4d8502Sjsg 					uint32_t reg, uint32_t val)
1716fb4d8502Sjsg {
1717fb4d8502Sjsg 	amdgpu_ring_write(ring, VCN_ENC_CMD_REG_WRITE);
1718fb4d8502Sjsg 	amdgpu_ring_write(ring,	reg << 2);
1719fb4d8502Sjsg 	amdgpu_ring_write(ring, val);
1720fb4d8502Sjsg }
1721fb4d8502Sjsg 
vcn_v1_0_set_interrupt_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned type,enum amdgpu_interrupt_state state)1722fb4d8502Sjsg static int vcn_v1_0_set_interrupt_state(struct amdgpu_device *adev,
1723fb4d8502Sjsg 					struct amdgpu_irq_src *source,
1724fb4d8502Sjsg 					unsigned type,
1725fb4d8502Sjsg 					enum amdgpu_interrupt_state state)
1726fb4d8502Sjsg {
1727fb4d8502Sjsg 	return 0;
1728fb4d8502Sjsg }
1729fb4d8502Sjsg 
vcn_v1_0_process_interrupt(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)1730fb4d8502Sjsg static int vcn_v1_0_process_interrupt(struct amdgpu_device *adev,
1731fb4d8502Sjsg 				      struct amdgpu_irq_src *source,
1732fb4d8502Sjsg 				      struct amdgpu_iv_entry *entry)
1733fb4d8502Sjsg {
1734fb4d8502Sjsg 	DRM_DEBUG("IH: VCN TRAP\n");
1735fb4d8502Sjsg 
1736fb4d8502Sjsg 	switch (entry->src_id) {
1737fb4d8502Sjsg 	case 124:
1738c349dbc7Sjsg 		amdgpu_fence_process(&adev->vcn.inst->ring_dec);
1739fb4d8502Sjsg 		break;
1740fb4d8502Sjsg 	case 119:
1741c349dbc7Sjsg 		amdgpu_fence_process(&adev->vcn.inst->ring_enc[0]);
1742fb4d8502Sjsg 		break;
1743fb4d8502Sjsg 	case 120:
1744c349dbc7Sjsg 		amdgpu_fence_process(&adev->vcn.inst->ring_enc[1]);
1745fb4d8502Sjsg 		break;
1746fb4d8502Sjsg 	default:
1747fb4d8502Sjsg 		DRM_ERROR("Unhandled interrupt: %d %d\n",
1748fb4d8502Sjsg 			  entry->src_id, entry->src_data[0]);
1749fb4d8502Sjsg 		break;
1750fb4d8502Sjsg 	}
1751fb4d8502Sjsg 
1752fb4d8502Sjsg 	return 0;
1753fb4d8502Sjsg }
1754fb4d8502Sjsg 
vcn_v1_0_dec_ring_insert_nop(struct amdgpu_ring * ring,uint32_t count)1755fb4d8502Sjsg static void vcn_v1_0_dec_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
1756fb4d8502Sjsg {
1757fb4d8502Sjsg 	struct amdgpu_device *adev = ring->adev;
1758fb4d8502Sjsg 	int i;
1759fb4d8502Sjsg 
1760fb4d8502Sjsg 	WARN_ON(ring->wptr % 2 || count % 2);
1761fb4d8502Sjsg 
1762fb4d8502Sjsg 	for (i = 0; i < count / 2; i++) {
1763fb4d8502Sjsg 		amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP), 0));
1764fb4d8502Sjsg 		amdgpu_ring_write(ring, 0);
1765fb4d8502Sjsg 	}
1766fb4d8502Sjsg }
1767fb4d8502Sjsg 
vcn_v1_0_set_powergating_state(void * handle,enum amd_powergating_state state)1768fb4d8502Sjsg static int vcn_v1_0_set_powergating_state(void *handle,
1769fb4d8502Sjsg 					  enum amd_powergating_state state)
1770fb4d8502Sjsg {
1771fb4d8502Sjsg 	/* This doesn't actually powergate the VCN block.
1772fb4d8502Sjsg 	 * That's done in the dpm code via the SMC.  This
1773fb4d8502Sjsg 	 * just re-inits the block as necessary.  The actual
1774fb4d8502Sjsg 	 * gating still happens in the dpm code.  We should
1775fb4d8502Sjsg 	 * revisit this when there is a cleaner line between
1776fb4d8502Sjsg 	 * the smc and the hw blocks
1777fb4d8502Sjsg 	 */
1778c349dbc7Sjsg 	int ret;
1779fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1780fb4d8502Sjsg 
1781c349dbc7Sjsg 	if (state == adev->vcn.cur_state)
1782c349dbc7Sjsg 		return 0;
1783c349dbc7Sjsg 
1784fb4d8502Sjsg 	if (state == AMD_PG_STATE_GATE)
1785c349dbc7Sjsg 		ret = vcn_v1_0_stop(adev);
1786fb4d8502Sjsg 	else
1787c349dbc7Sjsg 		ret = vcn_v1_0_start(adev);
1788c349dbc7Sjsg 
1789c349dbc7Sjsg 	if (!ret)
1790c349dbc7Sjsg 		adev->vcn.cur_state = state;
1791c349dbc7Sjsg 	return ret;
1792c349dbc7Sjsg }
1793c349dbc7Sjsg 
vcn_v1_0_idle_work_handler(struct work_struct * work)1794c349dbc7Sjsg static void vcn_v1_0_idle_work_handler(struct work_struct *work)
1795c349dbc7Sjsg {
1796c349dbc7Sjsg 	struct amdgpu_device *adev =
1797c349dbc7Sjsg 		container_of(work, struct amdgpu_device, vcn.idle_work.work);
1798c349dbc7Sjsg 	unsigned int fences = 0, i;
1799c349dbc7Sjsg 
1800c349dbc7Sjsg 	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
1801c349dbc7Sjsg 		fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
1802c349dbc7Sjsg 
1803c349dbc7Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
1804c349dbc7Sjsg 		struct dpg_pause_state new_state;
1805c349dbc7Sjsg 
1806c349dbc7Sjsg 		if (fences)
1807c349dbc7Sjsg 			new_state.fw_based = VCN_DPG_STATE__PAUSE;
1808c349dbc7Sjsg 		else
1809c349dbc7Sjsg 			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
1810c349dbc7Sjsg 
1811*f005ef32Sjsg 		if (amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec))
1812c349dbc7Sjsg 			new_state.jpeg = VCN_DPG_STATE__PAUSE;
1813c349dbc7Sjsg 		else
1814c349dbc7Sjsg 			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
1815c349dbc7Sjsg 
1816c349dbc7Sjsg 		adev->vcn.pause_dpg_mode(adev, 0, &new_state);
1817c349dbc7Sjsg 	}
1818c349dbc7Sjsg 
1819*f005ef32Sjsg 	fences += amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec);
1820c349dbc7Sjsg 	fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_dec);
1821c349dbc7Sjsg 
1822c349dbc7Sjsg 	if (fences == 0) {
1823c349dbc7Sjsg 		amdgpu_gfx_off_ctrl(adev, true);
1824c349dbc7Sjsg 		if (adev->pm.dpm_enabled)
1825c349dbc7Sjsg 			amdgpu_dpm_enable_uvd(adev, false);
1826c349dbc7Sjsg 		else
1827c349dbc7Sjsg 			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
1828c349dbc7Sjsg 			       AMD_PG_STATE_GATE);
1829c349dbc7Sjsg 	} else {
1830c349dbc7Sjsg 		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
1831c349dbc7Sjsg 	}
1832c349dbc7Sjsg }
1833c349dbc7Sjsg 
vcn_v1_0_ring_begin_use(struct amdgpu_ring * ring)1834ad8b1aafSjsg static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
1835c349dbc7Sjsg {
1836c349dbc7Sjsg 	struct	amdgpu_device *adev = ring->adev;
1837c349dbc7Sjsg 	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
1838c349dbc7Sjsg 
1839ad8b1aafSjsg 	mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
1840ad8b1aafSjsg 
1841*f005ef32Sjsg 	if (amdgpu_fence_wait_empty(ring->adev->jpeg.inst->ring_dec))
1842ad8b1aafSjsg 		DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
1843ad8b1aafSjsg 
1844ad8b1aafSjsg 	vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);
1845ad8b1aafSjsg 
1846ad8b1aafSjsg }
1847ad8b1aafSjsg 
vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring * ring,bool set_clocks)1848ad8b1aafSjsg void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
1849ad8b1aafSjsg {
1850ad8b1aafSjsg 	struct amdgpu_device *adev = ring->adev;
1851ad8b1aafSjsg 
1852c349dbc7Sjsg 	if (set_clocks) {
1853c349dbc7Sjsg 		amdgpu_gfx_off_ctrl(adev, false);
1854c349dbc7Sjsg 		if (adev->pm.dpm_enabled)
1855c349dbc7Sjsg 			amdgpu_dpm_enable_uvd(adev, true);
1856c349dbc7Sjsg 		else
1857c349dbc7Sjsg 			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
1858c349dbc7Sjsg 			       AMD_PG_STATE_UNGATE);
1859c349dbc7Sjsg 	}
1860c349dbc7Sjsg 
1861c349dbc7Sjsg 	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
1862c349dbc7Sjsg 		struct dpg_pause_state new_state;
1863c349dbc7Sjsg 		unsigned int fences = 0, i;
1864c349dbc7Sjsg 
1865c349dbc7Sjsg 		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
1866c349dbc7Sjsg 			fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);
1867c349dbc7Sjsg 
1868c349dbc7Sjsg 		if (fences)
1869c349dbc7Sjsg 			new_state.fw_based = VCN_DPG_STATE__PAUSE;
1870c349dbc7Sjsg 		else
1871c349dbc7Sjsg 			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
1872c349dbc7Sjsg 
1873*f005ef32Sjsg 		if (amdgpu_fence_count_emitted(adev->jpeg.inst->ring_dec))
1874c349dbc7Sjsg 			new_state.jpeg = VCN_DPG_STATE__PAUSE;
1875c349dbc7Sjsg 		else
1876c349dbc7Sjsg 			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
1877c349dbc7Sjsg 
1878c349dbc7Sjsg 		if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
1879c349dbc7Sjsg 			new_state.fw_based = VCN_DPG_STATE__PAUSE;
1880c349dbc7Sjsg 		else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
1881c349dbc7Sjsg 			new_state.jpeg = VCN_DPG_STATE__PAUSE;
1882c349dbc7Sjsg 
1883c349dbc7Sjsg 		adev->vcn.pause_dpg_mode(adev, 0, &new_state);
1884c349dbc7Sjsg 	}
1885fb4d8502Sjsg }
1886fb4d8502Sjsg 
vcn_v1_0_ring_end_use(struct amdgpu_ring * ring)1887ad8b1aafSjsg void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
1888ad8b1aafSjsg {
1889ad8b1aafSjsg 	schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
1890ad8b1aafSjsg 	mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
1891ad8b1aafSjsg }
1892ad8b1aafSjsg 
1893fb4d8502Sjsg static const struct amd_ip_funcs vcn_v1_0_ip_funcs = {
1894fb4d8502Sjsg 	.name = "vcn_v1_0",
1895fb4d8502Sjsg 	.early_init = vcn_v1_0_early_init,
1896fb4d8502Sjsg 	.late_init = NULL,
1897fb4d8502Sjsg 	.sw_init = vcn_v1_0_sw_init,
1898fb4d8502Sjsg 	.sw_fini = vcn_v1_0_sw_fini,
1899fb4d8502Sjsg 	.hw_init = vcn_v1_0_hw_init,
1900fb4d8502Sjsg 	.hw_fini = vcn_v1_0_hw_fini,
1901fb4d8502Sjsg 	.suspend = vcn_v1_0_suspend,
1902fb4d8502Sjsg 	.resume = vcn_v1_0_resume,
1903fb4d8502Sjsg 	.is_idle = vcn_v1_0_is_idle,
1904fb4d8502Sjsg 	.wait_for_idle = vcn_v1_0_wait_for_idle,
1905fb4d8502Sjsg 	.check_soft_reset = NULL /* vcn_v1_0_check_soft_reset */,
1906fb4d8502Sjsg 	.pre_soft_reset = NULL /* vcn_v1_0_pre_soft_reset */,
1907fb4d8502Sjsg 	.soft_reset = NULL /* vcn_v1_0_soft_reset */,
1908fb4d8502Sjsg 	.post_soft_reset = NULL /* vcn_v1_0_post_soft_reset */,
1909fb4d8502Sjsg 	.set_clockgating_state = vcn_v1_0_set_clockgating_state,
1910fb4d8502Sjsg 	.set_powergating_state = vcn_v1_0_set_powergating_state,
1911fb4d8502Sjsg };
1912fb4d8502Sjsg 
19131bb76ff1Sjsg /*
19141bb76ff1Sjsg  * It is a hardware issue that VCN can't handle a GTT TMZ buffer on
19151bb76ff1Sjsg  * CHIP_RAVEN series ASIC. Move such a GTT TMZ buffer to VRAM domain
19161bb76ff1Sjsg  * before command submission as a workaround.
19171bb76ff1Sjsg  */
vcn_v1_0_validate_bo(struct amdgpu_cs_parser * parser,struct amdgpu_job * job,uint64_t addr)19181bb76ff1Sjsg static int vcn_v1_0_validate_bo(struct amdgpu_cs_parser *parser,
19191bb76ff1Sjsg 				struct amdgpu_job *job,
19201bb76ff1Sjsg 				uint64_t addr)
19211bb76ff1Sjsg {
19221bb76ff1Sjsg 	struct ttm_operation_ctx ctx = { false, false };
19231bb76ff1Sjsg 	struct amdgpu_fpriv *fpriv = parser->filp->driver_priv;
19241bb76ff1Sjsg 	struct amdgpu_vm *vm = &fpriv->vm;
19251bb76ff1Sjsg 	struct amdgpu_bo_va_mapping *mapping;
19261bb76ff1Sjsg 	struct amdgpu_bo *bo;
19271bb76ff1Sjsg 	int r;
19281bb76ff1Sjsg 
19291bb76ff1Sjsg 	addr &= AMDGPU_GMC_HOLE_MASK;
19301bb76ff1Sjsg 	if (addr & 0x7) {
19311bb76ff1Sjsg 		DRM_ERROR("VCN messages must be 8 byte aligned!\n");
19321bb76ff1Sjsg 		return -EINVAL;
19331bb76ff1Sjsg 	}
19341bb76ff1Sjsg 
19351bb76ff1Sjsg 	mapping = amdgpu_vm_bo_lookup_mapping(vm, addr/AMDGPU_GPU_PAGE_SIZE);
19361bb76ff1Sjsg 	if (!mapping || !mapping->bo_va || !mapping->bo_va->base.bo)
19371bb76ff1Sjsg 		return -EINVAL;
19381bb76ff1Sjsg 
19391bb76ff1Sjsg 	bo = mapping->bo_va->base.bo;
19401bb76ff1Sjsg 	if (!(bo->flags & AMDGPU_GEM_CREATE_ENCRYPTED))
19411bb76ff1Sjsg 		return 0;
19421bb76ff1Sjsg 
19431bb76ff1Sjsg 	amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
19441bb76ff1Sjsg 	r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
19451bb76ff1Sjsg 	if (r) {
19461bb76ff1Sjsg 		DRM_ERROR("Failed to validate the VCN message BO (%d)!\n", r);
19471bb76ff1Sjsg 		return r;
19481bb76ff1Sjsg 	}
19491bb76ff1Sjsg 
19501bb76ff1Sjsg 	return r;
19511bb76ff1Sjsg }
19521bb76ff1Sjsg 
vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser * p,struct amdgpu_job * job,struct amdgpu_ib * ib)19531bb76ff1Sjsg static int vcn_v1_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
19541bb76ff1Sjsg 					   struct amdgpu_job *job,
19551bb76ff1Sjsg 					   struct amdgpu_ib *ib)
19561bb76ff1Sjsg {
19571bb76ff1Sjsg 	uint32_t msg_lo = 0, msg_hi = 0;
19581bb76ff1Sjsg 	int i, r;
19591bb76ff1Sjsg 
19601bb76ff1Sjsg 	if (!(ib->flags & AMDGPU_IB_FLAGS_SECURE))
19611bb76ff1Sjsg 		return 0;
19621bb76ff1Sjsg 
19631bb76ff1Sjsg 	for (i = 0; i < ib->length_dw; i += 2) {
19641bb76ff1Sjsg 		uint32_t reg = amdgpu_ib_get_value(ib, i);
19651bb76ff1Sjsg 		uint32_t val = amdgpu_ib_get_value(ib, i + 1);
19661bb76ff1Sjsg 
19671bb76ff1Sjsg 		if (reg == PACKET0(p->adev->vcn.internal.data0, 0)) {
19681bb76ff1Sjsg 			msg_lo = val;
19691bb76ff1Sjsg 		} else if (reg == PACKET0(p->adev->vcn.internal.data1, 0)) {
19701bb76ff1Sjsg 			msg_hi = val;
19711bb76ff1Sjsg 		} else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0)) {
19721bb76ff1Sjsg 			r = vcn_v1_0_validate_bo(p, job,
19731bb76ff1Sjsg 						 ((u64)msg_hi) << 32 | msg_lo);
19741bb76ff1Sjsg 			if (r)
19751bb76ff1Sjsg 				return r;
19761bb76ff1Sjsg 		}
19771bb76ff1Sjsg 	}
19781bb76ff1Sjsg 
19791bb76ff1Sjsg 	return 0;
19801bb76ff1Sjsg }
19811bb76ff1Sjsg 
1982fb4d8502Sjsg static const struct amdgpu_ring_funcs vcn_v1_0_dec_ring_vm_funcs = {
1983fb4d8502Sjsg 	.type = AMDGPU_RING_TYPE_VCN_DEC,
1984fb4d8502Sjsg 	.align_mask = 0xf,
1985fb4d8502Sjsg 	.support_64bit_ptrs = false,
1986c349dbc7Sjsg 	.no_user_fence = true,
19871bb76ff1Sjsg 	.secure_submission_supported = true,
1988fb4d8502Sjsg 	.get_rptr = vcn_v1_0_dec_ring_get_rptr,
1989fb4d8502Sjsg 	.get_wptr = vcn_v1_0_dec_ring_get_wptr,
1990fb4d8502Sjsg 	.set_wptr = vcn_v1_0_dec_ring_set_wptr,
19911bb76ff1Sjsg 	.patch_cs_in_place = vcn_v1_0_ring_patch_cs_in_place,
1992fb4d8502Sjsg 	.emit_frame_size =
1993fb4d8502Sjsg 		6 + 6 + /* hdp invalidate / flush */
1994fb4d8502Sjsg 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
1995fb4d8502Sjsg 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
1996fb4d8502Sjsg 		8 + /* vcn_v1_0_dec_ring_emit_vm_flush */
1997fb4d8502Sjsg 		14 + 14 + /* vcn_v1_0_dec_ring_emit_fence x2 vm fence */
1998fb4d8502Sjsg 		6,
1999fb4d8502Sjsg 	.emit_ib_size = 8, /* vcn_v1_0_dec_ring_emit_ib */
2000fb4d8502Sjsg 	.emit_ib = vcn_v1_0_dec_ring_emit_ib,
2001fb4d8502Sjsg 	.emit_fence = vcn_v1_0_dec_ring_emit_fence,
2002fb4d8502Sjsg 	.emit_vm_flush = vcn_v1_0_dec_ring_emit_vm_flush,
2003fb4d8502Sjsg 	.test_ring = amdgpu_vcn_dec_ring_test_ring,
2004fb4d8502Sjsg 	.test_ib = amdgpu_vcn_dec_ring_test_ib,
2005fb4d8502Sjsg 	.insert_nop = vcn_v1_0_dec_ring_insert_nop,
2006fb4d8502Sjsg 	.insert_start = vcn_v1_0_dec_ring_insert_start,
2007fb4d8502Sjsg 	.insert_end = vcn_v1_0_dec_ring_insert_end,
2008fb4d8502Sjsg 	.pad_ib = amdgpu_ring_generic_pad_ib,
2009c349dbc7Sjsg 	.begin_use = vcn_v1_0_ring_begin_use,
2010ad8b1aafSjsg 	.end_use = vcn_v1_0_ring_end_use,
2011fb4d8502Sjsg 	.emit_wreg = vcn_v1_0_dec_ring_emit_wreg,
2012fb4d8502Sjsg 	.emit_reg_wait = vcn_v1_0_dec_ring_emit_reg_wait,
2013fb4d8502Sjsg 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
2014fb4d8502Sjsg };
2015fb4d8502Sjsg 
2016fb4d8502Sjsg static const struct amdgpu_ring_funcs vcn_v1_0_enc_ring_vm_funcs = {
2017fb4d8502Sjsg 	.type = AMDGPU_RING_TYPE_VCN_ENC,
2018fb4d8502Sjsg 	.align_mask = 0x3f,
2019fb4d8502Sjsg 	.nop = VCN_ENC_CMD_NO_OP,
2020fb4d8502Sjsg 	.support_64bit_ptrs = false,
2021c349dbc7Sjsg 	.no_user_fence = true,
2022fb4d8502Sjsg 	.get_rptr = vcn_v1_0_enc_ring_get_rptr,
2023fb4d8502Sjsg 	.get_wptr = vcn_v1_0_enc_ring_get_wptr,
2024fb4d8502Sjsg 	.set_wptr = vcn_v1_0_enc_ring_set_wptr,
2025fb4d8502Sjsg 	.emit_frame_size =
2026fb4d8502Sjsg 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
2027fb4d8502Sjsg 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
2028fb4d8502Sjsg 		4 + /* vcn_v1_0_enc_ring_emit_vm_flush */
2029fb4d8502Sjsg 		5 + 5 + /* vcn_v1_0_enc_ring_emit_fence x2 vm fence */
2030fb4d8502Sjsg 		1, /* vcn_v1_0_enc_ring_insert_end */
2031fb4d8502Sjsg 	.emit_ib_size = 5, /* vcn_v1_0_enc_ring_emit_ib */
2032fb4d8502Sjsg 	.emit_ib = vcn_v1_0_enc_ring_emit_ib,
2033fb4d8502Sjsg 	.emit_fence = vcn_v1_0_enc_ring_emit_fence,
2034fb4d8502Sjsg 	.emit_vm_flush = vcn_v1_0_enc_ring_emit_vm_flush,
2035fb4d8502Sjsg 	.test_ring = amdgpu_vcn_enc_ring_test_ring,
2036fb4d8502Sjsg 	.test_ib = amdgpu_vcn_enc_ring_test_ib,
2037fb4d8502Sjsg 	.insert_nop = amdgpu_ring_insert_nop,
2038fb4d8502Sjsg 	.insert_end = vcn_v1_0_enc_ring_insert_end,
2039fb4d8502Sjsg 	.pad_ib = amdgpu_ring_generic_pad_ib,
2040c349dbc7Sjsg 	.begin_use = vcn_v1_0_ring_begin_use,
2041ad8b1aafSjsg 	.end_use = vcn_v1_0_ring_end_use,
2042fb4d8502Sjsg 	.emit_wreg = vcn_v1_0_enc_ring_emit_wreg,
2043fb4d8502Sjsg 	.emit_reg_wait = vcn_v1_0_enc_ring_emit_reg_wait,
2044fb4d8502Sjsg 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
2045fb4d8502Sjsg };
2046fb4d8502Sjsg 
vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device * adev)2047fb4d8502Sjsg static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
2048fb4d8502Sjsg {
2049c349dbc7Sjsg 	adev->vcn.inst->ring_dec.funcs = &vcn_v1_0_dec_ring_vm_funcs;
2050fb4d8502Sjsg 	DRM_INFO("VCN decode is enabled in VM mode\n");
2051fb4d8502Sjsg }
2052fb4d8502Sjsg 
vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device * adev)2053fb4d8502Sjsg static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
2054fb4d8502Sjsg {
2055fb4d8502Sjsg 	int i;
2056fb4d8502Sjsg 
2057fb4d8502Sjsg 	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
2058c349dbc7Sjsg 		adev->vcn.inst->ring_enc[i].funcs = &vcn_v1_0_enc_ring_vm_funcs;
2059fb4d8502Sjsg 
2060fb4d8502Sjsg 	DRM_INFO("VCN encode is enabled in VM mode\n");
2061fb4d8502Sjsg }
2062fb4d8502Sjsg 
2063fb4d8502Sjsg static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
2064fb4d8502Sjsg 	.set = vcn_v1_0_set_interrupt_state,
2065fb4d8502Sjsg 	.process = vcn_v1_0_process_interrupt,
2066fb4d8502Sjsg };
2067fb4d8502Sjsg 
vcn_v1_0_set_irq_funcs(struct amdgpu_device * adev)2068fb4d8502Sjsg static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev)
2069fb4d8502Sjsg {
2070c349dbc7Sjsg 	adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2;
2071c349dbc7Sjsg 	adev->vcn.inst->irq.funcs = &vcn_v1_0_irq_funcs;
2072fb4d8502Sjsg }
2073fb4d8502Sjsg 
2074*f005ef32Sjsg const struct amdgpu_ip_block_version vcn_v1_0_ip_block = {
2075fb4d8502Sjsg 		.type = AMD_IP_BLOCK_TYPE_VCN,
2076fb4d8502Sjsg 		.major = 1,
2077fb4d8502Sjsg 		.minor = 0,
2078fb4d8502Sjsg 		.rev = 0,
2079fb4d8502Sjsg 		.funcs = &vcn_v1_0_ip_funcs,
2080fb4d8502Sjsg };
2081