xref: /linux/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c (revision 79d2e1919a2728ef49d938eb20ebd5903c14dfb0)
1 /*
2  * Copyright 2013 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19  * USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * The above copyright notice and this permission notice (including the
22  * next paragraph) shall be included in all copies or substantial portions
23  * of the Software.
24  *
25  * Authors: Christian König <christian.koenig@amd.com>
26  */
27 
28 #include <linux/firmware.h>
29 
30 #include "amdgpu.h"
31 #include "amdgpu_vce.h"
32 #include "cikd.h"
33 #include "vce/vce_2_0_d.h"
34 #include "vce/vce_2_0_sh_mask.h"
35 #include "smu/smu_7_0_1_d.h"
36 #include "smu/smu_7_0_1_sh_mask.h"
37 #include "oss/oss_2_0_d.h"
38 #include "oss/oss_2_0_sh_mask.h"
39 
40 #define VCE_V2_0_FW_SIZE	(256 * 1024)
41 #define VCE_V2_0_STACK_SIZE	(64 * 1024)
42 #define VCE_V2_0_DATA_SIZE	(23552 * AMDGPU_MAX_VCE_HANDLES)
43 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK	0x02
44 
45 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev);
46 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev);
47 
48 /**
49  * vce_v2_0_ring_get_rptr - get read pointer
50  *
51  * @ring: amdgpu_ring pointer
52  *
53  * Returns the current hardware read pointer
54  */
55 static uint64_t vce_v2_0_ring_get_rptr(struct amdgpu_ring *ring)
56 {
57 	struct amdgpu_device *adev = ring->adev;
58 
59 	if (ring->me == 0)
60 		return RREG32(mmVCE_RB_RPTR);
61 	else
62 		return RREG32(mmVCE_RB_RPTR2);
63 }
64 
65 /**
66  * vce_v2_0_ring_get_wptr - get write pointer
67  *
68  * @ring: amdgpu_ring pointer
69  *
70  * Returns the current hardware write pointer
71  */
72 static uint64_t vce_v2_0_ring_get_wptr(struct amdgpu_ring *ring)
73 {
74 	struct amdgpu_device *adev = ring->adev;
75 
76 	if (ring->me == 0)
77 		return RREG32(mmVCE_RB_WPTR);
78 	else
79 		return RREG32(mmVCE_RB_WPTR2);
80 }
81 
82 /**
83  * vce_v2_0_ring_set_wptr - set write pointer
84  *
85  * @ring: amdgpu_ring pointer
86  *
87  * Commits the write pointer to the hardware
88  */
89 static void vce_v2_0_ring_set_wptr(struct amdgpu_ring *ring)
90 {
91 	struct amdgpu_device *adev = ring->adev;
92 
93 	if (ring->me == 0)
94 		WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
95 	else
96 		WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
97 }
98 
99 static int vce_v2_0_lmi_clean(struct amdgpu_device *adev)
100 {
101 	int i, j;
102 
103 	for (i = 0; i < 10; ++i) {
104 		for (j = 0; j < 100; ++j) {
105 			uint32_t status = RREG32(mmVCE_LMI_STATUS);
106 
107 			if (status & 0x337f)
108 				return 0;
109 			mdelay(10);
110 		}
111 	}
112 
113 	return -ETIMEDOUT;
114 }
115 
116 static int vce_v2_0_firmware_loaded(struct amdgpu_device *adev)
117 {
118 	int i, j;
119 
120 	for (i = 0; i < 10; ++i) {
121 		for (j = 0; j < 100; ++j) {
122 			uint32_t status = RREG32(mmVCE_STATUS);
123 
124 			if (status & VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK)
125 				return 0;
126 			mdelay(10);
127 		}
128 
129 		DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
130 		WREG32_P(mmVCE_SOFT_RESET,
131 			VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
132 			~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
133 		mdelay(10);
134 		WREG32_P(mmVCE_SOFT_RESET, 0,
135 			~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
136 		mdelay(10);
137 	}
138 
139 	return -ETIMEDOUT;
140 }
141 
142 static void vce_v2_0_disable_cg(struct amdgpu_device *adev)
143 {
144 	WREG32(mmVCE_CGTT_CLK_OVERRIDE, 7);
145 }
146 
147 static void vce_v2_0_init_cg(struct amdgpu_device *adev)
148 {
149 	u32 tmp;
150 
151 	tmp = RREG32(mmVCE_CLOCK_GATING_A);
152 	tmp &= ~0xfff;
153 	tmp |= ((0 << 0) | (4 << 4));
154 	tmp |= 0x40000;
155 	WREG32(mmVCE_CLOCK_GATING_A, tmp);
156 
157 	tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
158 	tmp &= ~0xfff;
159 	tmp |= ((0 << 0) | (4 << 4));
160 	WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
161 
162 	tmp = RREG32(mmVCE_CLOCK_GATING_B);
163 	tmp |= 0x10;
164 	tmp &= ~0x100000;
165 	WREG32(mmVCE_CLOCK_GATING_B, tmp);
166 }
167 
168 static void vce_v2_0_mc_resume(struct amdgpu_device *adev)
169 {
170 	uint32_t size, offset;
171 
172 	WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
173 	WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
174 	WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
175 	WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
176 
177 	WREG32(mmVCE_LMI_CTRL, 0x00398000);
178 	WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
179 	WREG32(mmVCE_LMI_SWAP_CNTL, 0);
180 	WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
181 	WREG32(mmVCE_LMI_VM_CTRL, 0);
182 
183 	WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
184 
185 	offset = AMDGPU_VCE_FIRMWARE_OFFSET;
186 	size = VCE_V2_0_FW_SIZE;
187 	WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
188 	WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
189 
190 	offset += size;
191 	size = VCE_V2_0_STACK_SIZE;
192 	WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
193 	WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
194 
195 	offset += size;
196 	size = VCE_V2_0_DATA_SIZE;
197 	WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
198 	WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
199 
200 	WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
201 	WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1);
202 }
203 
204 static bool vce_v2_0_is_idle(void *handle)
205 {
206 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
207 
208 	return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK);
209 }
210 
211 static int vce_v2_0_wait_for_idle(struct amdgpu_ip_block *ip_block)
212 {
213 	struct amdgpu_device *adev = ip_block->adev;
214 	unsigned i;
215 
216 	for (i = 0; i < adev->usec_timeout; i++) {
217 		if (vce_v2_0_is_idle(adev))
218 			return 0;
219 	}
220 	return -ETIMEDOUT;
221 }
222 
223 /**
224  * vce_v2_0_start - start VCE block
225  *
226  * @adev: amdgpu_device pointer
227  *
228  * Setup and start the VCE block
229  */
230 static int vce_v2_0_start(struct amdgpu_device *adev)
231 {
232 	struct amdgpu_ring *ring;
233 	int r;
234 
235 	/* set BUSY flag */
236 	WREG32_P(mmVCE_STATUS, 1, ~1);
237 
238 	vce_v2_0_init_cg(adev);
239 	vce_v2_0_disable_cg(adev);
240 
241 	vce_v2_0_mc_resume(adev);
242 
243 	ring = &adev->vce.ring[0];
244 	WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr));
245 	WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
246 	WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
247 	WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
248 	WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
249 
250 	ring = &adev->vce.ring[1];
251 	WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr));
252 	WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
253 	WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
254 	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
255 	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
256 
257 	WREG32_FIELD(VCE_VCPU_CNTL, CLK_EN, 1);
258 	WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 1);
259 	mdelay(100);
260 	WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 0);
261 
262 	r = vce_v2_0_firmware_loaded(adev);
263 
264 	/* clear BUSY flag */
265 	WREG32_P(mmVCE_STATUS, 0, ~1);
266 
267 	if (r) {
268 		DRM_ERROR("VCE not responding, giving up!!!\n");
269 		return r;
270 	}
271 
272 	return 0;
273 }
274 
275 static int vce_v2_0_stop(struct amdgpu_device *adev)
276 {
277 	struct amdgpu_ip_block *ip_block;
278 	int i;
279 	int status;
280 
281 
282 	if (vce_v2_0_lmi_clean(adev)) {
283 		DRM_INFO("vce is not idle \n");
284 		return 0;
285 	}
286 
287 	ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCN);
288 	if (!ip_block)
289 		return -EINVAL;
290 
291 	if (vce_v2_0_wait_for_idle(ip_block)) {
292 		DRM_INFO("VCE is busy, Can't set clock gating");
293 		return 0;
294 	}
295 
296 	/* Stall UMC and register bus before resetting VCPU */
297 	WREG32_P(mmVCE_LMI_CTRL2, 1 << 8, ~(1 << 8));
298 
299 	for (i = 0; i < 100; ++i) {
300 		status = RREG32(mmVCE_LMI_STATUS);
301 		if (status & 0x240)
302 			break;
303 		mdelay(1);
304 	}
305 
306 	WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x80001);
307 
308 	/* put LMI, VCPU, RBC etc... into reset */
309 	WREG32_P(mmVCE_SOFT_RESET, 1, ~0x1);
310 
311 	WREG32(mmVCE_STATUS, 0);
312 
313 	return 0;
314 }
315 
316 static void vce_v2_0_set_sw_cg(struct amdgpu_device *adev, bool gated)
317 {
318 	u32 tmp;
319 
320 	if (gated) {
321 		tmp = RREG32(mmVCE_CLOCK_GATING_B);
322 		tmp |= 0xe70000;
323 		WREG32(mmVCE_CLOCK_GATING_B, tmp);
324 
325 		tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
326 		tmp |= 0xff000000;
327 		WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
328 
329 		tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
330 		tmp &= ~0x3fc;
331 		WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
332 
333 		WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
334 	} else {
335 		tmp = RREG32(mmVCE_CLOCK_GATING_B);
336 		tmp |= 0xe7;
337 		tmp &= ~0xe70000;
338 		WREG32(mmVCE_CLOCK_GATING_B, tmp);
339 
340 		tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
341 		tmp |= 0x1fe000;
342 		tmp &= ~0xff000000;
343 		WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
344 
345 		tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
346 		tmp |= 0x3fc;
347 		WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
348 	}
349 }
350 
351 static void vce_v2_0_set_dyn_cg(struct amdgpu_device *adev, bool gated)
352 {
353 	u32 orig, tmp;
354 
355 /* LMI_MC/LMI_UMC always set in dynamic,
356  * set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0}
357  */
358 	tmp = RREG32(mmVCE_CLOCK_GATING_B);
359 	tmp &= ~0x00060006;
360 
361 /* Exception for ECPU, IH, SEM, SYS blocks needs to be turned on/off by SW */
362 	if (gated) {
363 		tmp |= 0xe10000;
364 		WREG32(mmVCE_CLOCK_GATING_B, tmp);
365 	} else {
366 		tmp |= 0xe1;
367 		tmp &= ~0xe10000;
368 		WREG32(mmVCE_CLOCK_GATING_B, tmp);
369 	}
370 
371 	orig = tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
372 	tmp &= ~0x1fe000;
373 	tmp &= ~0xff000000;
374 	if (tmp != orig)
375 		WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
376 
377 	orig = tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
378 	tmp &= ~0x3fc;
379 	if (tmp != orig)
380 		WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
381 
382 	/* set VCE_UENC_REG_CLOCK_GATING always in dynamic mode */
383 	WREG32(mmVCE_UENC_REG_CLOCK_GATING, 0x00);
384 
385 	if(gated)
386 		WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
387 }
388 
389 static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable,
390 								bool sw_cg)
391 {
392 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) {
393 		if (sw_cg)
394 			vce_v2_0_set_sw_cg(adev, true);
395 		else
396 			vce_v2_0_set_dyn_cg(adev, true);
397 	} else {
398 		vce_v2_0_disable_cg(adev);
399 
400 		if (sw_cg)
401 			vce_v2_0_set_sw_cg(adev, false);
402 		else
403 			vce_v2_0_set_dyn_cg(adev, false);
404 	}
405 }
406 
407 static int vce_v2_0_early_init(struct amdgpu_ip_block *ip_block)
408 {
409 	struct amdgpu_device *adev = ip_block->adev;
410 
411 	adev->vce.num_rings = 2;
412 
413 	vce_v2_0_set_ring_funcs(adev);
414 	vce_v2_0_set_irq_funcs(adev);
415 
416 	return 0;
417 }
418 
419 static int vce_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
420 {
421 	struct amdgpu_ring *ring;
422 	int r, i;
423 	struct amdgpu_device *adev = ip_block->adev;
424 
425 	/* VCE */
426 	r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 167, &adev->vce.irq);
427 	if (r)
428 		return r;
429 
430 	r = amdgpu_vce_sw_init(adev, VCE_V2_0_FW_SIZE +
431 		VCE_V2_0_STACK_SIZE + VCE_V2_0_DATA_SIZE);
432 	if (r)
433 		return r;
434 
435 	r = amdgpu_vce_resume(adev);
436 	if (r)
437 		return r;
438 
439 	for (i = 0; i < adev->vce.num_rings; i++) {
440 		enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i);
441 
442 		ring = &adev->vce.ring[i];
443 		sprintf(ring->name, "vce%d", i);
444 		r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0,
445 				     hw_prio, NULL);
446 		if (r)
447 			return r;
448 	}
449 
450 	return r;
451 }
452 
453 static int vce_v2_0_sw_fini(struct amdgpu_ip_block *ip_block)
454 {
455 	int r;
456 	struct amdgpu_device *adev = ip_block->adev;
457 
458 	r = amdgpu_vce_suspend(adev);
459 	if (r)
460 		return r;
461 
462 	return amdgpu_vce_sw_fini(adev);
463 }
464 
465 static int vce_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
466 {
467 	int r, i;
468 	struct amdgpu_device *adev = ip_block->adev;
469 
470 	amdgpu_asic_set_vce_clocks(adev, 10000, 10000);
471 	vce_v2_0_enable_mgcg(adev, true, false);
472 
473 	for (i = 0; i < adev->vce.num_rings; i++) {
474 		r = amdgpu_ring_test_helper(&adev->vce.ring[i]);
475 		if (r)
476 			return r;
477 	}
478 
479 	DRM_INFO("VCE initialized successfully.\n");
480 
481 	return 0;
482 }
483 
484 static int vce_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
485 {
486 	cancel_delayed_work_sync(&ip_block->adev->vce.idle_work);
487 
488 	return 0;
489 }
490 
491 static int vce_v2_0_suspend(struct amdgpu_ip_block *ip_block)
492 {
493 	int r;
494 	struct amdgpu_device *adev = ip_block->adev;
495 
496 
497 	/*
498 	 * Proper cleanups before halting the HW engine:
499 	 *   - cancel the delayed idle work
500 	 *   - enable powergating
501 	 *   - enable clockgating
502 	 *   - disable dpm
503 	 *
504 	 * TODO: to align with the VCN implementation, move the
505 	 * jobs for clockgating/powergating/dpm setting to
506 	 * ->set_powergating_state().
507 	 */
508 	cancel_delayed_work_sync(&adev->vce.idle_work);
509 
510 	if (adev->pm.dpm_enabled) {
511 		amdgpu_dpm_enable_vce(adev, false);
512 	} else {
513 		amdgpu_asic_set_vce_clocks(adev, 0, 0);
514 		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
515 						       AMD_PG_STATE_GATE);
516 		amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
517 						       AMD_CG_STATE_GATE);
518 	}
519 
520 	r = vce_v2_0_hw_fini(ip_block);
521 	if (r)
522 		return r;
523 
524 	return amdgpu_vce_suspend(adev);
525 }
526 
527 static int vce_v2_0_resume(struct amdgpu_ip_block *ip_block)
528 {
529 	int r;
530 
531 	r = amdgpu_vce_resume(ip_block->adev);
532 	if (r)
533 		return r;
534 
535 	return vce_v2_0_hw_init(ip_block);
536 }
537 
538 static int vce_v2_0_soft_reset(struct amdgpu_ip_block *ip_block)
539 {
540 	struct amdgpu_device *adev = ip_block->adev;
541 
542 	WREG32_FIELD(SRBM_SOFT_RESET, SOFT_RESET_VCE, 1);
543 	mdelay(5);
544 
545 	return vce_v2_0_start(adev);
546 }
547 
548 static int vce_v2_0_set_interrupt_state(struct amdgpu_device *adev,
549 					struct amdgpu_irq_src *source,
550 					unsigned type,
551 					enum amdgpu_interrupt_state state)
552 {
553 	uint32_t val = 0;
554 
555 	if (state == AMDGPU_IRQ_STATE_ENABLE)
556 		val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
557 
558 	WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
559 	return 0;
560 }
561 
562 static int vce_v2_0_process_interrupt(struct amdgpu_device *adev,
563 				      struct amdgpu_irq_src *source,
564 				      struct amdgpu_iv_entry *entry)
565 {
566 	DRM_DEBUG("IH: VCE\n");
567 	switch (entry->src_data[0]) {
568 	case 0:
569 	case 1:
570 		amdgpu_fence_process(&adev->vce.ring[entry->src_data[0]]);
571 		break;
572 	default:
573 		DRM_ERROR("Unhandled interrupt: %d %d\n",
574 			  entry->src_id, entry->src_data[0]);
575 		break;
576 	}
577 
578 	return 0;
579 }
580 
581 static int vce_v2_0_set_clockgating_state(void *handle,
582 					  enum amd_clockgating_state state)
583 {
584 	bool gate = false;
585 	bool sw_cg = false;
586 
587 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
588 
589 	if (state == AMD_CG_STATE_GATE) {
590 		gate = true;
591 		sw_cg = true;
592 	}
593 
594 	vce_v2_0_enable_mgcg(adev, gate, sw_cg);
595 
596 	return 0;
597 }
598 
599 static int vce_v2_0_set_powergating_state(void *handle,
600 					  enum amd_powergating_state state)
601 {
602 	/* This doesn't actually powergate the VCE block.
603 	 * That's done in the dpm code via the SMC.  This
604 	 * just re-inits the block as necessary.  The actual
605 	 * gating still happens in the dpm code.  We should
606 	 * revisit this when there is a cleaner line between
607 	 * the smc and the hw blocks
608 	 */
609 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
610 
611 	if (state == AMD_PG_STATE_GATE)
612 		return vce_v2_0_stop(adev);
613 	else
614 		return vce_v2_0_start(adev);
615 }
616 
617 static const struct amd_ip_funcs vce_v2_0_ip_funcs = {
618 	.name = "vce_v2_0",
619 	.early_init = vce_v2_0_early_init,
620 	.sw_init = vce_v2_0_sw_init,
621 	.sw_fini = vce_v2_0_sw_fini,
622 	.hw_init = vce_v2_0_hw_init,
623 	.hw_fini = vce_v2_0_hw_fini,
624 	.suspend = vce_v2_0_suspend,
625 	.resume = vce_v2_0_resume,
626 	.is_idle = vce_v2_0_is_idle,
627 	.wait_for_idle = vce_v2_0_wait_for_idle,
628 	.soft_reset = vce_v2_0_soft_reset,
629 	.set_clockgating_state = vce_v2_0_set_clockgating_state,
630 	.set_powergating_state = vce_v2_0_set_powergating_state,
631 };
632 
633 static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
634 	.type = AMDGPU_RING_TYPE_VCE,
635 	.align_mask = 0xf,
636 	.nop = VCE_CMD_NO_OP,
637 	.support_64bit_ptrs = false,
638 	.no_user_fence = true,
639 	.get_rptr = vce_v2_0_ring_get_rptr,
640 	.get_wptr = vce_v2_0_ring_get_wptr,
641 	.set_wptr = vce_v2_0_ring_set_wptr,
642 	.parse_cs = amdgpu_vce_ring_parse_cs,
643 	.emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence  x1 no user fence */
644 	.emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */
645 	.emit_ib = amdgpu_vce_ring_emit_ib,
646 	.emit_fence = amdgpu_vce_ring_emit_fence,
647 	.test_ring = amdgpu_vce_ring_test_ring,
648 	.test_ib = amdgpu_vce_ring_test_ib,
649 	.insert_nop = amdgpu_ring_insert_nop,
650 	.pad_ib = amdgpu_ring_generic_pad_ib,
651 	.begin_use = amdgpu_vce_ring_begin_use,
652 	.end_use = amdgpu_vce_ring_end_use,
653 };
654 
655 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
656 {
657 	int i;
658 
659 	for (i = 0; i < adev->vce.num_rings; i++) {
660 		adev->vce.ring[i].funcs = &vce_v2_0_ring_funcs;
661 		adev->vce.ring[i].me = i;
662 	}
663 }
664 
665 static const struct amdgpu_irq_src_funcs vce_v2_0_irq_funcs = {
666 	.set = vce_v2_0_set_interrupt_state,
667 	.process = vce_v2_0_process_interrupt,
668 };
669 
670 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev)
671 {
672 	adev->vce.irq.num_types = 1;
673 	adev->vce.irq.funcs = &vce_v2_0_irq_funcs;
674 };
675 
676 const struct amdgpu_ip_block_version vce_v2_0_ip_block =
677 {
678 		.type = AMD_IP_BLOCK_TYPE_VCE,
679 		.major = 2,
680 		.minor = 0,
681 		.rev = 0,
682 		.funcs = &vce_v2_0_ip_funcs,
683 };
684