xref: /linux/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c (revision 6dfafbd0299a60bfb5d5e277fdf100037c7ded07)
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(struct amdgpu_ip_block *ip_block)
205 {
206 	struct amdgpu_device *adev = ip_block->adev;
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(ip_block))
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_VCE);
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 	int r;
411 
412 	r = amdgpu_vce_early_init(adev);
413 	if (r)
414 		return r;
415 
416 	adev->vce.num_rings = 2;
417 
418 	vce_v2_0_set_ring_funcs(adev);
419 	vce_v2_0_set_irq_funcs(adev);
420 
421 	return 0;
422 }
423 
424 static int vce_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
425 {
426 	struct amdgpu_ring *ring;
427 	int r, i;
428 	struct amdgpu_device *adev = ip_block->adev;
429 
430 	/* VCE */
431 	r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 167, &adev->vce.irq);
432 	if (r)
433 		return r;
434 
435 	r = amdgpu_vce_sw_init(adev, VCE_V2_0_FW_SIZE +
436 		VCE_V2_0_STACK_SIZE + VCE_V2_0_DATA_SIZE);
437 	if (r)
438 		return r;
439 
440 	r = amdgpu_vce_resume(adev);
441 	if (r)
442 		return r;
443 
444 	for (i = 0; i < adev->vce.num_rings; i++) {
445 		enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i);
446 
447 		ring = &adev->vce.ring[i];
448 		sprintf(ring->name, "vce%d", i);
449 		r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0,
450 				     hw_prio, NULL);
451 		if (r)
452 			return r;
453 	}
454 
455 	return r;
456 }
457 
458 static int vce_v2_0_sw_fini(struct amdgpu_ip_block *ip_block)
459 {
460 	int r;
461 	struct amdgpu_device *adev = ip_block->adev;
462 
463 	r = amdgpu_vce_suspend(adev);
464 	if (r)
465 		return r;
466 
467 	return amdgpu_vce_sw_fini(adev);
468 }
469 
470 static int vce_v2_0_hw_init(struct amdgpu_ip_block *ip_block)
471 {
472 	int r, i;
473 	struct amdgpu_device *adev = ip_block->adev;
474 
475 	amdgpu_asic_set_vce_clocks(adev, 10000, 10000);
476 	vce_v2_0_enable_mgcg(adev, true, false);
477 
478 	for (i = 0; i < adev->vce.num_rings; i++) {
479 		r = amdgpu_ring_test_helper(&adev->vce.ring[i]);
480 		if (r)
481 			return r;
482 	}
483 
484 	DRM_INFO("VCE initialized successfully.\n");
485 
486 	return 0;
487 }
488 
489 static int vce_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
490 {
491 	cancel_delayed_work_sync(&ip_block->adev->vce.idle_work);
492 
493 	return 0;
494 }
495 
496 static int vce_v2_0_suspend(struct amdgpu_ip_block *ip_block)
497 {
498 	int r;
499 	struct amdgpu_device *adev = ip_block->adev;
500 
501 
502 	/*
503 	 * Proper cleanups before halting the HW engine:
504 	 *   - cancel the delayed idle work
505 	 *   - enable powergating
506 	 *   - enable clockgating
507 	 *   - disable dpm
508 	 *
509 	 * TODO: to align with the VCN implementation, move the
510 	 * jobs for clockgating/powergating/dpm setting to
511 	 * ->set_powergating_state().
512 	 */
513 	cancel_delayed_work_sync(&adev->vce.idle_work);
514 
515 	if (adev->pm.dpm_enabled) {
516 		amdgpu_dpm_enable_vce(adev, false);
517 	} else {
518 		amdgpu_asic_set_vce_clocks(adev, 0, 0);
519 		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
520 						       AMD_PG_STATE_GATE);
521 		amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
522 						       AMD_CG_STATE_GATE);
523 	}
524 
525 	r = vce_v2_0_hw_fini(ip_block);
526 	if (r)
527 		return r;
528 
529 	return amdgpu_vce_suspend(adev);
530 }
531 
532 static int vce_v2_0_resume(struct amdgpu_ip_block *ip_block)
533 {
534 	int r;
535 
536 	r = amdgpu_vce_resume(ip_block->adev);
537 	if (r)
538 		return r;
539 
540 	return vce_v2_0_hw_init(ip_block);
541 }
542 
543 static int vce_v2_0_soft_reset(struct amdgpu_ip_block *ip_block)
544 {
545 	struct amdgpu_device *adev = ip_block->adev;
546 
547 	WREG32_FIELD(SRBM_SOFT_RESET, SOFT_RESET_VCE, 1);
548 	mdelay(5);
549 
550 	return vce_v2_0_start(adev);
551 }
552 
553 static int vce_v2_0_set_interrupt_state(struct amdgpu_device *adev,
554 					struct amdgpu_irq_src *source,
555 					unsigned type,
556 					enum amdgpu_interrupt_state state)
557 {
558 	uint32_t val = 0;
559 
560 	if (state == AMDGPU_IRQ_STATE_ENABLE)
561 		val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;
562 
563 	WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
564 	return 0;
565 }
566 
567 static int vce_v2_0_process_interrupt(struct amdgpu_device *adev,
568 				      struct amdgpu_irq_src *source,
569 				      struct amdgpu_iv_entry *entry)
570 {
571 	DRM_DEBUG("IH: VCE\n");
572 	switch (entry->src_data[0]) {
573 	case 0:
574 	case 1:
575 		amdgpu_fence_process(&adev->vce.ring[entry->src_data[0]]);
576 		break;
577 	default:
578 		DRM_ERROR("Unhandled interrupt: %d %d\n",
579 			  entry->src_id, entry->src_data[0]);
580 		break;
581 	}
582 
583 	return 0;
584 }
585 
586 static int vce_v2_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
587 					  enum amd_clockgating_state state)
588 {
589 	bool gate = false;
590 	bool sw_cg = false;
591 
592 	struct amdgpu_device *adev = ip_block->adev;
593 
594 	if (state == AMD_CG_STATE_GATE) {
595 		gate = true;
596 		sw_cg = true;
597 	}
598 
599 	vce_v2_0_enable_mgcg(adev, gate, sw_cg);
600 
601 	return 0;
602 }
603 
604 static int vce_v2_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
605 					  enum amd_powergating_state state)
606 {
607 	/* This doesn't actually powergate the VCE block.
608 	 * That's done in the dpm code via the SMC.  This
609 	 * just re-inits the block as necessary.  The actual
610 	 * gating still happens in the dpm code.  We should
611 	 * revisit this when there is a cleaner line between
612 	 * the smc and the hw blocks
613 	 */
614 	struct amdgpu_device *adev = ip_block->adev;
615 
616 	if (state == AMD_PG_STATE_GATE)
617 		return vce_v2_0_stop(adev);
618 	else
619 		return vce_v2_0_start(adev);
620 }
621 
622 static const struct amd_ip_funcs vce_v2_0_ip_funcs = {
623 	.name = "vce_v2_0",
624 	.early_init = vce_v2_0_early_init,
625 	.sw_init = vce_v2_0_sw_init,
626 	.sw_fini = vce_v2_0_sw_fini,
627 	.hw_init = vce_v2_0_hw_init,
628 	.hw_fini = vce_v2_0_hw_fini,
629 	.suspend = vce_v2_0_suspend,
630 	.resume = vce_v2_0_resume,
631 	.is_idle = vce_v2_0_is_idle,
632 	.wait_for_idle = vce_v2_0_wait_for_idle,
633 	.soft_reset = vce_v2_0_soft_reset,
634 	.set_clockgating_state = vce_v2_0_set_clockgating_state,
635 	.set_powergating_state = vce_v2_0_set_powergating_state,
636 };
637 
638 static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
639 	.type = AMDGPU_RING_TYPE_VCE,
640 	.align_mask = 0xf,
641 	.nop = VCE_CMD_NO_OP,
642 	.support_64bit_ptrs = false,
643 	.no_user_fence = true,
644 	.get_rptr = vce_v2_0_ring_get_rptr,
645 	.get_wptr = vce_v2_0_ring_get_wptr,
646 	.set_wptr = vce_v2_0_ring_set_wptr,
647 	.parse_cs = amdgpu_vce_ring_parse_cs,
648 	.emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence  x1 no user fence */
649 	.emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */
650 	.emit_ib = amdgpu_vce_ring_emit_ib,
651 	.emit_fence = amdgpu_vce_ring_emit_fence,
652 	.test_ring = amdgpu_vce_ring_test_ring,
653 	.test_ib = amdgpu_vce_ring_test_ib,
654 	.insert_nop = amdgpu_ring_insert_nop,
655 	.pad_ib = amdgpu_ring_generic_pad_ib,
656 	.begin_use = amdgpu_vce_ring_begin_use,
657 	.end_use = amdgpu_vce_ring_end_use,
658 };
659 
660 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
661 {
662 	int i;
663 
664 	for (i = 0; i < adev->vce.num_rings; i++) {
665 		adev->vce.ring[i].funcs = &vce_v2_0_ring_funcs;
666 		adev->vce.ring[i].me = i;
667 	}
668 }
669 
670 static const struct amdgpu_irq_src_funcs vce_v2_0_irq_funcs = {
671 	.set = vce_v2_0_set_interrupt_state,
672 	.process = vce_v2_0_process_interrupt,
673 };
674 
675 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev)
676 {
677 	adev->vce.irq.num_types = 1;
678 	adev->vce.irq.funcs = &vce_v2_0_irq_funcs;
679 };
680 
681 const struct amdgpu_ip_block_version vce_v2_0_ip_block =
682 {
683 		.type = AMD_IP_BLOCK_TYPE_VCE,
684 		.major = 2,
685 		.minor = 0,
686 		.rev = 0,
687 		.funcs = &vce_v2_0_ip_funcs,
688 };
689