xref: /dflybsd-src/sys/dev/drm/radeon/uvd_v1_0.c (revision d78d3a2272f5ecf9e0b570e362128240417a1b85)
14cd92098Szrj /*
24cd92098Szrj  * Copyright 2013 Advanced Micro Devices, Inc.
34cd92098Szrj  *
44cd92098Szrj  * Permission is hereby granted, free of charge, to any person obtaining a
54cd92098Szrj  * copy of this software and associated documentation files (the "Software"),
64cd92098Szrj  * to deal in the Software without restriction, including without limitation
74cd92098Szrj  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84cd92098Szrj  * and/or sell copies of the Software, and to permit persons to whom the
94cd92098Szrj  * Software is furnished to do so, subject to the following conditions:
104cd92098Szrj  *
114cd92098Szrj  * The above copyright notice and this permission notice shall be included in
124cd92098Szrj  * all copies or substantial portions of the Software.
134cd92098Szrj  *
144cd92098Szrj  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154cd92098Szrj  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164cd92098Szrj  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
174cd92098Szrj  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184cd92098Szrj  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194cd92098Szrj  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204cd92098Szrj  * OTHER DEALINGS IN THE SOFTWARE.
214cd92098Szrj  *
224cd92098Szrj  * Authors: Christian König <christian.koenig@amd.com>
234cd92098Szrj  */
244cd92098Szrj 
25591d5043SFrançois Tigeot #include <linux/firmware.h>
264cd92098Szrj #include <drm/drmP.h>
274cd92098Szrj #include "radeon.h"
284cd92098Szrj #include "radeon_asic.h"
294cd92098Szrj #include "r600d.h"
304cd92098Szrj 
314cd92098Szrj /**
324cd92098Szrj  * uvd_v1_0_get_rptr - get read pointer
334cd92098Szrj  *
344cd92098Szrj  * @rdev: radeon_device pointer
354cd92098Szrj  * @ring: radeon_ring pointer
364cd92098Szrj  *
374cd92098Szrj  * Returns the current hardware read pointer
384cd92098Szrj  */
uvd_v1_0_get_rptr(struct radeon_device * rdev,struct radeon_ring * ring)394cd92098Szrj uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
404cd92098Szrj 			   struct radeon_ring *ring)
414cd92098Szrj {
424cd92098Szrj 	return RREG32(UVD_RBC_RB_RPTR);
434cd92098Szrj }
444cd92098Szrj 
454cd92098Szrj /**
464cd92098Szrj  * uvd_v1_0_get_wptr - get write pointer
474cd92098Szrj  *
484cd92098Szrj  * @rdev: radeon_device pointer
494cd92098Szrj  * @ring: radeon_ring pointer
504cd92098Szrj  *
514cd92098Szrj  * Returns the current hardware write pointer
524cd92098Szrj  */
uvd_v1_0_get_wptr(struct radeon_device * rdev,struct radeon_ring * ring)534cd92098Szrj uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev,
544cd92098Szrj 			   struct radeon_ring *ring)
554cd92098Szrj {
564cd92098Szrj 	return RREG32(UVD_RBC_RB_WPTR);
574cd92098Szrj }
584cd92098Szrj 
594cd92098Szrj /**
604cd92098Szrj  * uvd_v1_0_set_wptr - set write pointer
614cd92098Szrj  *
624cd92098Szrj  * @rdev: radeon_device pointer
634cd92098Szrj  * @ring: radeon_ring pointer
644cd92098Szrj  *
654cd92098Szrj  * Commits the write pointer to the hardware
664cd92098Szrj  */
uvd_v1_0_set_wptr(struct radeon_device * rdev,struct radeon_ring * ring)674cd92098Szrj void uvd_v1_0_set_wptr(struct radeon_device *rdev,
684cd92098Szrj 		       struct radeon_ring *ring)
694cd92098Szrj {
704cd92098Szrj 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
714cd92098Szrj }
724cd92098Szrj 
734cd92098Szrj /**
74591d5043SFrançois Tigeot  * uvd_v1_0_fence_emit - emit an fence & trap command
75591d5043SFrançois Tigeot  *
76591d5043SFrançois Tigeot  * @rdev: radeon_device pointer
77591d5043SFrançois Tigeot  * @fence: fence to emit
78591d5043SFrançois Tigeot  *
79591d5043SFrançois Tigeot  * Write a fence and a trap command to the ring.
80591d5043SFrançois Tigeot  */
uvd_v1_0_fence_emit(struct radeon_device * rdev,struct radeon_fence * fence)81591d5043SFrançois Tigeot void uvd_v1_0_fence_emit(struct radeon_device *rdev,
82591d5043SFrançois Tigeot 			 struct radeon_fence *fence)
83591d5043SFrançois Tigeot {
84591d5043SFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[fence->ring];
85591d5043SFrançois Tigeot 	uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr;
86591d5043SFrançois Tigeot 
87591d5043SFrançois Tigeot 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
88591d5043SFrançois Tigeot 	radeon_ring_write(ring, addr & 0xffffffff);
89591d5043SFrançois Tigeot 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
90591d5043SFrançois Tigeot 	radeon_ring_write(ring, fence->seq);
91591d5043SFrançois Tigeot 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
92591d5043SFrançois Tigeot 	radeon_ring_write(ring, 0);
93591d5043SFrançois Tigeot 
94591d5043SFrançois Tigeot 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
95591d5043SFrançois Tigeot 	radeon_ring_write(ring, 0);
96591d5043SFrançois Tigeot 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
97591d5043SFrançois Tigeot 	radeon_ring_write(ring, 0);
98591d5043SFrançois Tigeot 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
99591d5043SFrançois Tigeot 	radeon_ring_write(ring, 2);
100591d5043SFrançois Tigeot 	return;
101591d5043SFrançois Tigeot }
102591d5043SFrançois Tigeot 
103591d5043SFrançois Tigeot /**
104591d5043SFrançois Tigeot  * uvd_v1_0_resume - memory controller programming
105591d5043SFrançois Tigeot  *
106591d5043SFrançois Tigeot  * @rdev: radeon_device pointer
107591d5043SFrançois Tigeot  *
108591d5043SFrançois Tigeot  * Let the UVD memory controller know it's offsets
109591d5043SFrançois Tigeot  */
uvd_v1_0_resume(struct radeon_device * rdev)110591d5043SFrançois Tigeot int uvd_v1_0_resume(struct radeon_device *rdev)
111591d5043SFrançois Tigeot {
112591d5043SFrançois Tigeot 	uint64_t addr;
113591d5043SFrançois Tigeot 	uint32_t size;
114591d5043SFrançois Tigeot 	int r;
115591d5043SFrançois Tigeot 
116591d5043SFrançois Tigeot 	r = radeon_uvd_resume(rdev);
117591d5043SFrançois Tigeot 	if (r)
118591d5043SFrançois Tigeot 		return r;
119591d5043SFrançois Tigeot 
120591d5043SFrançois Tigeot 	/* programm the VCPU memory controller bits 0-27 */
121591d5043SFrançois Tigeot 	addr = (rdev->uvd.gpu_addr >> 3) + 16;
122591d5043SFrançois Tigeot 	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->datasize) >> 3;
123591d5043SFrançois Tigeot 	WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
124591d5043SFrançois Tigeot 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
125591d5043SFrançois Tigeot 
126591d5043SFrançois Tigeot 	addr += size;
127*d78d3a22SFrançois Tigeot 	size = RADEON_UVD_HEAP_SIZE >> 3;
128591d5043SFrançois Tigeot 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
129591d5043SFrançois Tigeot 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
130591d5043SFrançois Tigeot 
131591d5043SFrançois Tigeot 	addr += size;
132*d78d3a22SFrançois Tigeot 	size = (RADEON_UVD_STACK_SIZE +
133*d78d3a22SFrançois Tigeot 	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
134591d5043SFrançois Tigeot 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
135591d5043SFrançois Tigeot 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
136591d5043SFrançois Tigeot 
137591d5043SFrançois Tigeot 	/* bits 28-31 */
138591d5043SFrançois Tigeot 	addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
139591d5043SFrançois Tigeot 	WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
140591d5043SFrançois Tigeot 
141591d5043SFrançois Tigeot 	/* bits 32-39 */
142591d5043SFrançois Tigeot 	addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
143591d5043SFrançois Tigeot 	WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
144591d5043SFrançois Tigeot 
145591d5043SFrançois Tigeot 	WREG32(UVD_FW_START, *((uint32_t*)rdev->uvd.cpu_addr));
146591d5043SFrançois Tigeot 
147591d5043SFrançois Tigeot 	return 0;
148591d5043SFrançois Tigeot }
149591d5043SFrançois Tigeot 
150591d5043SFrançois Tigeot /**
1514cd92098Szrj  * uvd_v1_0_init - start and test UVD block
1524cd92098Szrj  *
1534cd92098Szrj  * @rdev: radeon_device pointer
1544cd92098Szrj  *
1554cd92098Szrj  * Initialize the hardware, boot up the VCPU and do some testing
1564cd92098Szrj  */
uvd_v1_0_init(struct radeon_device * rdev)1574cd92098Szrj int uvd_v1_0_init(struct radeon_device *rdev)
1584cd92098Szrj {
1594cd92098Szrj 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
1604cd92098Szrj 	uint32_t tmp;
1614cd92098Szrj 	int r;
1624cd92098Szrj 
1634cd92098Szrj 	/* raise clocks while booting up the VCPU */
164c6f73aabSFrançois Tigeot 	if (rdev->family < CHIP_RV740)
165c6f73aabSFrançois Tigeot 		radeon_set_uvd_clocks(rdev, 10000, 10000);
166c6f73aabSFrançois Tigeot 	else
1674cd92098Szrj 		radeon_set_uvd_clocks(rdev, 53300, 40000);
1684cd92098Szrj 
1694cd92098Szrj 	r = uvd_v1_0_start(rdev);
1704cd92098Szrj 	if (r)
1714cd92098Szrj 		goto done;
1724cd92098Szrj 
1734cd92098Szrj 	ring->ready = true;
1744cd92098Szrj 	r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
1754cd92098Szrj 	if (r) {
1764cd92098Szrj 		ring->ready = false;
1774cd92098Szrj 		goto done;
1784cd92098Szrj 	}
1794cd92098Szrj 
1804cd92098Szrj 	r = radeon_ring_lock(rdev, ring, 10);
1814cd92098Szrj 	if (r) {
1824cd92098Szrj 		DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
1834cd92098Szrj 		goto done;
1844cd92098Szrj 	}
1854cd92098Szrj 
1864cd92098Szrj 	tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
1874cd92098Szrj 	radeon_ring_write(ring, tmp);
1884cd92098Szrj 	radeon_ring_write(ring, 0xFFFFF);
1894cd92098Szrj 
1904cd92098Szrj 	tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
1914cd92098Szrj 	radeon_ring_write(ring, tmp);
1924cd92098Szrj 	radeon_ring_write(ring, 0xFFFFF);
1934cd92098Szrj 
1944cd92098Szrj 	tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
1954cd92098Szrj 	radeon_ring_write(ring, tmp);
1964cd92098Szrj 	radeon_ring_write(ring, 0xFFFFF);
1974cd92098Szrj 
1984cd92098Szrj 	/* Clear timeout status bits */
1994cd92098Szrj 	radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
2004cd92098Szrj 	radeon_ring_write(ring, 0x8);
2014cd92098Szrj 
2024cd92098Szrj 	radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
2034cd92098Szrj 	radeon_ring_write(ring, 3);
2044cd92098Szrj 
205c6f73aabSFrançois Tigeot 	radeon_ring_unlock_commit(rdev, ring, false);
2064cd92098Szrj 
2074cd92098Szrj done:
2084cd92098Szrj 	/* lower clocks again */
2094cd92098Szrj 	radeon_set_uvd_clocks(rdev, 0, 0);
2104cd92098Szrj 
211591d5043SFrançois Tigeot 	if (!r) {
212591d5043SFrançois Tigeot 		switch (rdev->family) {
213591d5043SFrançois Tigeot 		case CHIP_RV610:
214591d5043SFrançois Tigeot 		case CHIP_RV630:
215591d5043SFrançois Tigeot 		case CHIP_RV620:
216591d5043SFrançois Tigeot 			/* 64byte granularity workaround */
217591d5043SFrançois Tigeot 			WREG32(MC_CONFIG, 0);
218591d5043SFrançois Tigeot 			WREG32(MC_CONFIG, 1 << 4);
219591d5043SFrançois Tigeot 			WREG32(RS_DQ_RD_RET_CONF, 0x3f);
220591d5043SFrançois Tigeot 			WREG32(MC_CONFIG, 0x1f);
221591d5043SFrançois Tigeot 
222591d5043SFrançois Tigeot 			/* fall through */
223591d5043SFrançois Tigeot 		case CHIP_RV670:
224591d5043SFrançois Tigeot 		case CHIP_RV635:
225591d5043SFrançois Tigeot 
226591d5043SFrançois Tigeot 			/* write clean workaround */
227591d5043SFrançois Tigeot 			WREG32_P(UVD_VCPU_CNTL, 0x10, ~0x10);
228591d5043SFrançois Tigeot 			break;
229591d5043SFrançois Tigeot 
230591d5043SFrançois Tigeot 		default:
231591d5043SFrançois Tigeot 			/* TODO: Do we need more? */
232591d5043SFrançois Tigeot 			break;
233591d5043SFrançois Tigeot 		}
234591d5043SFrançois Tigeot 
2354cd92098Szrj 		DRM_INFO("UVD initialized successfully.\n");
236591d5043SFrançois Tigeot 	}
2374cd92098Szrj 
2384cd92098Szrj 	return r;
2394cd92098Szrj }
2404cd92098Szrj 
2414cd92098Szrj /**
2424cd92098Szrj  * uvd_v1_0_fini - stop the hardware block
2434cd92098Szrj  *
2444cd92098Szrj  * @rdev: radeon_device pointer
2454cd92098Szrj  *
2464cd92098Szrj  * Stop the UVD block, mark ring as not ready any more
2474cd92098Szrj  */
uvd_v1_0_fini(struct radeon_device * rdev)2484cd92098Szrj void uvd_v1_0_fini(struct radeon_device *rdev)
2494cd92098Szrj {
2504cd92098Szrj 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
2514cd92098Szrj 
2524cd92098Szrj 	uvd_v1_0_stop(rdev);
2534cd92098Szrj 	ring->ready = false;
2544cd92098Szrj }
2554cd92098Szrj 
2564cd92098Szrj /**
2574cd92098Szrj  * uvd_v1_0_start - start UVD block
2584cd92098Szrj  *
2594cd92098Szrj  * @rdev: radeon_device pointer
2604cd92098Szrj  *
2614cd92098Szrj  * Setup and start the UVD block
2624cd92098Szrj  */
uvd_v1_0_start(struct radeon_device * rdev)2634cd92098Szrj int uvd_v1_0_start(struct radeon_device *rdev)
2644cd92098Szrj {
2654cd92098Szrj 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
2664cd92098Szrj 	uint32_t rb_bufsz;
2674cd92098Szrj 	int i, j, r;
2684cd92098Szrj 
2694cd92098Szrj 	/* disable byte swapping */
2704cd92098Szrj 	u32 lmi_swap_cntl = 0;
2714cd92098Szrj 	u32 mp_swap_cntl = 0;
2724cd92098Szrj 
2734cd92098Szrj 	/* disable clock gating */
2744cd92098Szrj 	WREG32(UVD_CGC_GATE, 0);
2754cd92098Szrj 
2764cd92098Szrj 	/* disable interupt */
2774cd92098Szrj 	WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
2784cd92098Szrj 
2794cd92098Szrj 	/* Stall UMC and register bus before resetting VCPU */
2804cd92098Szrj 	WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
2814cd92098Szrj 	WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
2824cd92098Szrj 	mdelay(1);
2834cd92098Szrj 
2844cd92098Szrj 	/* put LMI, VCPU, RBC etc... into reset */
2854cd92098Szrj 	WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
2864cd92098Szrj 	       LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
2874cd92098Szrj 	       CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
2884cd92098Szrj 	mdelay(5);
2894cd92098Szrj 
2904cd92098Szrj 	/* take UVD block out of reset */
2914cd92098Szrj 	WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
2924cd92098Szrj 	mdelay(5);
2934cd92098Szrj 
2944cd92098Szrj 	/* initialize UVD memory controller */
2954cd92098Szrj 	WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
2964cd92098Szrj 			     (1 << 21) | (1 << 9) | (1 << 20));
2974cd92098Szrj 
2984cd92098Szrj #ifdef __BIG_ENDIAN
2994cd92098Szrj 	/* swap (8 in 32) RB and IB */
3004cd92098Szrj 	lmi_swap_cntl = 0xa;
3014cd92098Szrj 	mp_swap_cntl = 0;
3024cd92098Szrj #endif
3034cd92098Szrj 	WREG32(UVD_LMI_SWAP_CNTL, lmi_swap_cntl);
3044cd92098Szrj 	WREG32(UVD_MP_SWAP_CNTL, mp_swap_cntl);
3054cd92098Szrj 
3064cd92098Szrj 	WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
3074cd92098Szrj 	WREG32(UVD_MPC_SET_MUXA1, 0x0);
3084cd92098Szrj 	WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
3094cd92098Szrj 	WREG32(UVD_MPC_SET_MUXB1, 0x0);
3104cd92098Szrj 	WREG32(UVD_MPC_SET_ALU, 0);
3114cd92098Szrj 	WREG32(UVD_MPC_SET_MUX, 0x88);
3124cd92098Szrj 
3134cd92098Szrj 	/* take all subblocks out of reset, except VCPU */
3144cd92098Szrj 	WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
3154cd92098Szrj 	mdelay(5);
3164cd92098Szrj 
3174cd92098Szrj 	/* enable VCPU clock */
3184cd92098Szrj 	WREG32(UVD_VCPU_CNTL,  1 << 9);
3194cd92098Szrj 
3204cd92098Szrj 	/* enable UMC */
3214cd92098Szrj 	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
3224cd92098Szrj 
323591d5043SFrançois Tigeot 	WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
324591d5043SFrançois Tigeot 
3254cd92098Szrj 	/* boot up the VCPU */
3264cd92098Szrj 	WREG32(UVD_SOFT_RESET, 0);
3274cd92098Szrj 	mdelay(10);
3284cd92098Szrj 
3294cd92098Szrj 	for (i = 0; i < 10; ++i) {
3304cd92098Szrj 		uint32_t status;
3314cd92098Szrj 		for (j = 0; j < 100; ++j) {
3324cd92098Szrj 			status = RREG32(UVD_STATUS);
3334cd92098Szrj 			if (status & 2)
3344cd92098Szrj 				break;
3354cd92098Szrj 			mdelay(10);
3364cd92098Szrj 		}
3374cd92098Szrj 		r = 0;
3384cd92098Szrj 		if (status & 2)
3394cd92098Szrj 			break;
3404cd92098Szrj 
3414cd92098Szrj 		DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
3424cd92098Szrj 		WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
3434cd92098Szrj 		mdelay(10);
3444cd92098Szrj 		WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
3454cd92098Szrj 		mdelay(10);
3464cd92098Szrj 		r = -1;
3474cd92098Szrj 	}
3484cd92098Szrj 
3494cd92098Szrj 	if (r) {
3504cd92098Szrj 		DRM_ERROR("UVD not responding, giving up!!!\n");
3514cd92098Szrj 		return r;
3524cd92098Szrj 	}
3534cd92098Szrj 
3544cd92098Szrj 	/* enable interupt */
3554cd92098Szrj 	WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
3564cd92098Szrj 
3574cd92098Szrj 	/* force RBC into idle state */
3584cd92098Szrj 	WREG32(UVD_RBC_RB_CNTL, 0x11010101);
3594cd92098Szrj 
3604cd92098Szrj 	/* Set the write pointer delay */
3614cd92098Szrj 	WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
3624cd92098Szrj 
3634cd92098Szrj 	/* programm the 4GB memory segment for rptr and ring buffer */
3644cd92098Szrj 	WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
3654cd92098Szrj 				   (0x7 << 16) | (0x1 << 31));
3664cd92098Szrj 
3674cd92098Szrj 	/* Initialize the ring buffer's read and write pointers */
3684cd92098Szrj 	WREG32(UVD_RBC_RB_RPTR, 0x0);
3694cd92098Szrj 
370c6f73aabSFrançois Tigeot 	ring->wptr = RREG32(UVD_RBC_RB_RPTR);
3714cd92098Szrj 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
3724cd92098Szrj 
3734cd92098Szrj 	/* set the ring address */
3744cd92098Szrj 	WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
3754cd92098Szrj 
3764cd92098Szrj 	/* Set ring buffer size */
3774cd92098Szrj 	rb_bufsz = order_base_2(ring->ring_size);
3784cd92098Szrj 	rb_bufsz = (0x1 << 8) | rb_bufsz;
3794cd92098Szrj 	WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
3804cd92098Szrj 
3814cd92098Szrj 	return 0;
3824cd92098Szrj }
3834cd92098Szrj 
3844cd92098Szrj /**
3854cd92098Szrj  * uvd_v1_0_stop - stop UVD block
3864cd92098Szrj  *
3874cd92098Szrj  * @rdev: radeon_device pointer
3884cd92098Szrj  *
3894cd92098Szrj  * stop the UVD block
3904cd92098Szrj  */
uvd_v1_0_stop(struct radeon_device * rdev)3914cd92098Szrj void uvd_v1_0_stop(struct radeon_device *rdev)
3924cd92098Szrj {
3934cd92098Szrj 	/* force RBC into idle state */
3944cd92098Szrj 	WREG32(UVD_RBC_RB_CNTL, 0x11010101);
3954cd92098Szrj 
3964cd92098Szrj 	/* Stall UMC and register bus before resetting VCPU */
3974cd92098Szrj 	WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
3984cd92098Szrj 	WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
3994cd92098Szrj 	mdelay(1);
4004cd92098Szrj 
4014cd92098Szrj 	/* put VCPU into reset */
4024cd92098Szrj 	WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
4034cd92098Szrj 	mdelay(5);
4044cd92098Szrj 
4054cd92098Szrj 	/* disable VCPU clock */
4064cd92098Szrj 	WREG32(UVD_VCPU_CNTL, 0x0);
4074cd92098Szrj 
4084cd92098Szrj 	/* Unstall UMC and register bus */
4094cd92098Szrj 	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
4104cd92098Szrj 	WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
4114cd92098Szrj }
4124cd92098Szrj 
4134cd92098Szrj /**
4144cd92098Szrj  * uvd_v1_0_ring_test - register write test
4154cd92098Szrj  *
4164cd92098Szrj  * @rdev: radeon_device pointer
4174cd92098Szrj  * @ring: radeon_ring pointer
4184cd92098Szrj  *
4194cd92098Szrj  * Test if we can successfully write to the context register
4204cd92098Szrj  */
uvd_v1_0_ring_test(struct radeon_device * rdev,struct radeon_ring * ring)4214cd92098Szrj int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
4224cd92098Szrj {
4234cd92098Szrj 	uint32_t tmp = 0;
4244cd92098Szrj 	unsigned i;
4254cd92098Szrj 	int r;
4264cd92098Szrj 
4274cd92098Szrj 	WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
4284cd92098Szrj 	r = radeon_ring_lock(rdev, ring, 3);
4294cd92098Szrj 	if (r) {
4304cd92098Szrj 		DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
4314cd92098Szrj 			  ring->idx, r);
4324cd92098Szrj 		return r;
4334cd92098Szrj 	}
4344cd92098Szrj 	radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
4354cd92098Szrj 	radeon_ring_write(ring, 0xDEADBEEF);
436c6f73aabSFrançois Tigeot 	radeon_ring_unlock_commit(rdev, ring, false);
4374cd92098Szrj 	for (i = 0; i < rdev->usec_timeout; i++) {
4384cd92098Szrj 		tmp = RREG32(UVD_CONTEXT_ID);
4394cd92098Szrj 		if (tmp == 0xDEADBEEF)
4404cd92098Szrj 			break;
4414cd92098Szrj 		DRM_UDELAY(1);
4424cd92098Szrj 	}
4434cd92098Szrj 
4444cd92098Szrj 	if (i < rdev->usec_timeout) {
4454cd92098Szrj 		DRM_INFO("ring test on %d succeeded in %d usecs\n",
4464cd92098Szrj 			 ring->idx, i);
4474cd92098Szrj 	} else {
4484cd92098Szrj 		DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
4494cd92098Szrj 			  ring->idx, tmp);
4504cd92098Szrj 		r = -EINVAL;
4514cd92098Szrj 	}
4524cd92098Szrj 	return r;
4534cd92098Szrj }
4544cd92098Szrj 
4554cd92098Szrj /**
4564cd92098Szrj  * uvd_v1_0_semaphore_emit - emit semaphore command
4574cd92098Szrj  *
4584cd92098Szrj  * @rdev: radeon_device pointer
4594cd92098Szrj  * @ring: radeon_ring pointer
4604cd92098Szrj  * @semaphore: semaphore to emit commands for
4614cd92098Szrj  * @emit_wait: true if we should emit a wait command
4624cd92098Szrj  *
4634cd92098Szrj  * Emit a semaphore command (either wait or signal) to the UVD ring.
4644cd92098Szrj  */
uvd_v1_0_semaphore_emit(struct radeon_device * rdev,struct radeon_ring * ring,struct radeon_semaphore * semaphore,bool emit_wait)465c6f73aabSFrançois Tigeot bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
4664cd92098Szrj 			     struct radeon_ring *ring,
4674cd92098Szrj 			     struct radeon_semaphore *semaphore,
4684cd92098Szrj 			     bool emit_wait)
4694cd92098Szrj {
470c59a5c48SFrançois Tigeot 	/* disable semaphores for UVD V1 hardware */
471c59a5c48SFrançois Tigeot 	return false;
4724cd92098Szrj }
4734cd92098Szrj 
4744cd92098Szrj /**
4754cd92098Szrj  * uvd_v1_0_ib_execute - execute indirect buffer
4764cd92098Szrj  *
4774cd92098Szrj  * @rdev: radeon_device pointer
4784cd92098Szrj  * @ib: indirect buffer to execute
4794cd92098Szrj  *
4804cd92098Szrj  * Write ring commands to execute the indirect buffer
4814cd92098Szrj  */
uvd_v1_0_ib_execute(struct radeon_device * rdev,struct radeon_ib * ib)4824cd92098Szrj void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
4834cd92098Szrj {
4844cd92098Szrj 	struct radeon_ring *ring = &rdev->ring[ib->ring];
4854cd92098Szrj 
4864cd92098Szrj 	radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
4874cd92098Szrj 	radeon_ring_write(ring, ib->gpu_addr);
4884cd92098Szrj 	radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
4894cd92098Szrj 	radeon_ring_write(ring, ib->length_dw);
4904cd92098Szrj }
4914cd92098Szrj 
4924cd92098Szrj /**
4934cd92098Szrj  * uvd_v1_0_ib_test - test ib execution
4944cd92098Szrj  *
4954cd92098Szrj  * @rdev: radeon_device pointer
4964cd92098Szrj  * @ring: radeon_ring pointer
4974cd92098Szrj  *
4984cd92098Szrj  * Test if we can successfully execute an IB
4994cd92098Szrj  */
uvd_v1_0_ib_test(struct radeon_device * rdev,struct radeon_ring * ring)5004cd92098Szrj int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
5014cd92098Szrj {
5024cd92098Szrj 	struct radeon_fence *fence = NULL;
5034cd92098Szrj 	int r;
5044cd92098Szrj 
505c6f73aabSFrançois Tigeot 	if (rdev->family < CHIP_RV740)
506c6f73aabSFrançois Tigeot 		r = radeon_set_uvd_clocks(rdev, 10000, 10000);
507c6f73aabSFrançois Tigeot 	else
5084cd92098Szrj 		r = radeon_set_uvd_clocks(rdev, 53300, 40000);
5094cd92098Szrj 	if (r) {
5104cd92098Szrj 		DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r);
5114cd92098Szrj 		return r;
5124cd92098Szrj 	}
5134cd92098Szrj 
5144cd92098Szrj 	r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
5154cd92098Szrj 	if (r) {
5164cd92098Szrj 		DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
5174cd92098Szrj 		goto error;
5184cd92098Szrj 	}
5194cd92098Szrj 
5204cd92098Szrj 	r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
5214cd92098Szrj 	if (r) {
5224cd92098Szrj 		DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
5234cd92098Szrj 		goto error;
5244cd92098Szrj 	}
5254cd92098Szrj 
526*d78d3a22SFrançois Tigeot 	r = radeon_fence_wait_timeout(fence, false, usecs_to_jiffies(
527*d78d3a22SFrançois Tigeot 		RADEON_USEC_IB_TEST_TIMEOUT));
528*d78d3a22SFrançois Tigeot 	if (r < 0) {
5294cd92098Szrj 		DRM_ERROR("radeon: fence wait failed (%d).\n", r);
5304cd92098Szrj 		goto error;
531*d78d3a22SFrançois Tigeot 	} else if (r == 0) {
532*d78d3a22SFrançois Tigeot 		DRM_ERROR("radeon: fence wait timed out.\n");
533*d78d3a22SFrançois Tigeot 		r = -ETIMEDOUT;
534*d78d3a22SFrançois Tigeot 		goto error;
5354cd92098Szrj 	}
536*d78d3a22SFrançois Tigeot 	r = 0;
5374cd92098Szrj 	DRM_INFO("ib test on ring %d succeeded\n",  ring->idx);
5384cd92098Szrj error:
5394cd92098Szrj 	radeon_fence_unref(&fence);
5404cd92098Szrj 	radeon_set_uvd_clocks(rdev, 0, 0);
5414cd92098Szrj 	return r;
5424cd92098Szrj }
543