Home | History | Annotate | Line # | Download | only in radeon
      1 /*	$NetBSD: radeon_uvd_v1_0.c,v 1.6 2021/12/19 00:25:04 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2013 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: Christian Knig <christian.koenig (at) amd.com>
     25  */
     26 
     27 #include <sys/cdefs.h>
     28 __KERNEL_RCSID(0, "$NetBSD: radeon_uvd_v1_0.c,v 1.6 2021/12/19 00:25:04 riastradh Exp $");
     29 
     30 #include <linux/firmware.h>
     31 
     32 #include "radeon.h"
     33 #include "radeon_asic.h"
     34 #include "r600d.h"
     35 
     36 /**
     37  * uvd_v1_0_get_rptr - get read pointer
     38  *
     39  * @rdev: radeon_device pointer
     40  * @ring: radeon_ring pointer
     41  *
     42  * Returns the current hardware read pointer
     43  */
     44 uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
     45 			   struct radeon_ring *ring)
     46 {
     47 	return RREG32(UVD_RBC_RB_RPTR);
     48 }
     49 
     50 /**
     51  * uvd_v1_0_get_wptr - get write pointer
     52  *
     53  * @rdev: radeon_device pointer
     54  * @ring: radeon_ring pointer
     55  *
     56  * Returns the current hardware write pointer
     57  */
     58 uint32_t uvd_v1_0_get_wptr(struct radeon_device *rdev,
     59 			   struct radeon_ring *ring)
     60 {
     61 	return RREG32(UVD_RBC_RB_WPTR);
     62 }
     63 
     64 /**
     65  * uvd_v1_0_set_wptr - set write pointer
     66  *
     67  * @rdev: radeon_device pointer
     68  * @ring: radeon_ring pointer
     69  *
     70  * Commits the write pointer to the hardware
     71  */
     72 void uvd_v1_0_set_wptr(struct radeon_device *rdev,
     73 		       struct radeon_ring *ring)
     74 {
     75 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
     76 }
     77 
     78 /**
     79  * uvd_v1_0_fence_emit - emit an fence & trap command
     80  *
     81  * @rdev: radeon_device pointer
     82  * @fence: fence to emit
     83  *
     84  * Write a fence and a trap command to the ring.
     85  */
     86 void uvd_v1_0_fence_emit(struct radeon_device *rdev,
     87 			 struct radeon_fence *fence)
     88 {
     89 	struct radeon_ring *ring = &rdev->ring[fence->ring];
     90 	uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr;
     91 
     92 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
     93 	radeon_ring_write(ring, addr & 0xffffffff);
     94 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
     95 	radeon_ring_write(ring, fence->seq);
     96 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
     97 	radeon_ring_write(ring, 0);
     98 
     99 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0));
    100 	radeon_ring_write(ring, 0);
    101 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0));
    102 	radeon_ring_write(ring, 0);
    103 	radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
    104 	radeon_ring_write(ring, 2);
    105 	return;
    106 }
    107 
    108 /**
    109  * uvd_v1_0_resume - memory controller programming
    110  *
    111  * @rdev: radeon_device pointer
    112  *
    113  * Let the UVD memory controller know it's offsets
    114  */
    115 int uvd_v1_0_resume(struct radeon_device *rdev)
    116 {
    117 	uint64_t addr;
    118 	uint32_t size;
    119 	int r;
    120 
    121 	r = radeon_uvd_resume(rdev);
    122 	if (r)
    123 		return r;
    124 
    125 	/* programm the VCPU memory controller bits 0-27 */
    126 	addr = (rdev->uvd.gpu_addr >> 3) + 16;
    127 	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size) >> 3;
    128 	WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
    129 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
    130 
    131 	addr += size;
    132 	size = RADEON_UVD_HEAP_SIZE >> 3;
    133 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
    134 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
    135 
    136 	addr += size;
    137 	size = (RADEON_UVD_STACK_SIZE +
    138 	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
    139 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
    140 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
    141 
    142 	/* bits 28-31 */
    143 	addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
    144 	WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));
    145 
    146 	/* bits 32-39 */
    147 	addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
    148 	WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1U << 31));
    149 
    150 	WREG32(UVD_FW_START, *((uint32_t*)rdev->uvd.cpu_addr));
    151 
    152 	return 0;
    153 }
    154 
    155 /**
    156  * uvd_v1_0_init - start and test UVD block
    157  *
    158  * @rdev: radeon_device pointer
    159  *
    160  * Initialize the hardware, boot up the VCPU and do some testing
    161  */
    162 int uvd_v1_0_init(struct radeon_device *rdev)
    163 {
    164 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
    165 	uint32_t tmp;
    166 	int r;
    167 
    168 	/* raise clocks while booting up the VCPU */
    169 	if (rdev->family < CHIP_RV740)
    170 		radeon_set_uvd_clocks(rdev, 10000, 10000);
    171 	else
    172 		radeon_set_uvd_clocks(rdev, 53300, 40000);
    173 
    174 	r = uvd_v1_0_start(rdev);
    175 	if (r)
    176 		goto done;
    177 
    178 	ring->ready = true;
    179 	r = radeon_ring_test(rdev, R600_RING_TYPE_UVD_INDEX, ring);
    180 	if (r) {
    181 		ring->ready = false;
    182 		goto done;
    183 	}
    184 
    185 	r = radeon_ring_lock(rdev, ring, 10);
    186 	if (r) {
    187 		DRM_ERROR("radeon: ring failed to lock UVD ring (%d).\n", r);
    188 		goto done;
    189 	}
    190 
    191 	tmp = PACKET0(UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);
    192 	radeon_ring_write(ring, tmp);
    193 	radeon_ring_write(ring, 0xFFFFF);
    194 
    195 	tmp = PACKET0(UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);
    196 	radeon_ring_write(ring, tmp);
    197 	radeon_ring_write(ring, 0xFFFFF);
    198 
    199 	tmp = PACKET0(UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);
    200 	radeon_ring_write(ring, tmp);
    201 	radeon_ring_write(ring, 0xFFFFF);
    202 
    203 	/* Clear timeout status bits */
    204 	radeon_ring_write(ring, PACKET0(UVD_SEMA_TIMEOUT_STATUS, 0));
    205 	radeon_ring_write(ring, 0x8);
    206 
    207 	radeon_ring_write(ring, PACKET0(UVD_SEMA_CNTL, 0));
    208 	radeon_ring_write(ring, 3);
    209 
    210 	radeon_ring_unlock_commit(rdev, ring, false);
    211 
    212 done:
    213 	/* lower clocks again */
    214 	radeon_set_uvd_clocks(rdev, 0, 0);
    215 
    216 	if (!r) {
    217 		switch (rdev->family) {
    218 		case CHIP_RV610:
    219 		case CHIP_RV630:
    220 		case CHIP_RV620:
    221 			/* 64byte granularity workaround */
    222 			WREG32(MC_CONFIG, 0);
    223 			WREG32(MC_CONFIG, 1 << 4);
    224 			WREG32(RS_DQ_RD_RET_CONF, 0x3f);
    225 			WREG32(MC_CONFIG, 0x1f);
    226 
    227 			/* fall through */
    228 		case CHIP_RV670:
    229 		case CHIP_RV635:
    230 
    231 			/* write clean workaround */
    232 			WREG32_P(UVD_VCPU_CNTL, 0x10, ~0x10);
    233 			break;
    234 
    235 		default:
    236 			/* TODO: Do we need more? */
    237 			break;
    238 		}
    239 
    240 		DRM_INFO("UVD initialized successfully.\n");
    241 	}
    242 
    243 	return r;
    244 }
    245 
    246 /**
    247  * uvd_v1_0_fini - stop the hardware block
    248  *
    249  * @rdev: radeon_device pointer
    250  *
    251  * Stop the UVD block, mark ring as not ready any more
    252  */
    253 void uvd_v1_0_fini(struct radeon_device *rdev)
    254 {
    255 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
    256 
    257 	uvd_v1_0_stop(rdev);
    258 	ring->ready = false;
    259 }
    260 
    261 /**
    262  * uvd_v1_0_start - start UVD block
    263  *
    264  * @rdev: radeon_device pointer
    265  *
    266  * Setup and start the UVD block
    267  */
    268 int uvd_v1_0_start(struct radeon_device *rdev)
    269 {
    270 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
    271 	uint32_t rb_bufsz;
    272 	int i, j, r;
    273 
    274 	/* disable byte swapping */
    275 	u32 lmi_swap_cntl = 0;
    276 	u32 mp_swap_cntl = 0;
    277 
    278 	/* disable clock gating */
    279 	WREG32(UVD_CGC_GATE, 0);
    280 
    281 	/* disable interupt */
    282 	WREG32_P(UVD_MASTINT_EN, 0, ~(1 << 1));
    283 
    284 	/* Stall UMC and register bus before resetting VCPU */
    285 	WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
    286 	WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
    287 	mdelay(1);
    288 
    289 	/* put LMI, VCPU, RBC etc... into reset */
    290 	WREG32(UVD_SOFT_RESET, LMI_SOFT_RESET | VCPU_SOFT_RESET |
    291 	       LBSI_SOFT_RESET | RBC_SOFT_RESET | CSM_SOFT_RESET |
    292 	       CXW_SOFT_RESET | TAP_SOFT_RESET | LMI_UMC_SOFT_RESET);
    293 	mdelay(5);
    294 
    295 	/* take UVD block out of reset */
    296 	WREG32_P(SRBM_SOFT_RESET, 0, ~SOFT_RESET_UVD);
    297 	mdelay(5);
    298 
    299 	/* initialize UVD memory controller */
    300 	WREG32(UVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) |
    301 			     (1 << 21) | (1 << 9) | (1 << 20));
    302 
    303 #ifdef __BIG_ENDIAN
    304 	/* swap (8 in 32) RB and IB */
    305 	lmi_swap_cntl = 0xa;
    306 	mp_swap_cntl = 0;
    307 #endif
    308 	WREG32(UVD_LMI_SWAP_CNTL, lmi_swap_cntl);
    309 	WREG32(UVD_MP_SWAP_CNTL, mp_swap_cntl);
    310 
    311 	WREG32(UVD_MPC_SET_MUXA0, 0x40c2040);
    312 	WREG32(UVD_MPC_SET_MUXA1, 0x0);
    313 	WREG32(UVD_MPC_SET_MUXB0, 0x40c2040);
    314 	WREG32(UVD_MPC_SET_MUXB1, 0x0);
    315 	WREG32(UVD_MPC_SET_ALU, 0);
    316 	WREG32(UVD_MPC_SET_MUX, 0x88);
    317 
    318 	/* take all subblocks out of reset, except VCPU */
    319 	WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
    320 	mdelay(5);
    321 
    322 	/* enable VCPU clock */
    323 	WREG32(UVD_VCPU_CNTL,  1 << 9);
    324 
    325 	/* enable UMC */
    326 	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
    327 
    328 	WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
    329 
    330 	/* boot up the VCPU */
    331 	WREG32(UVD_SOFT_RESET, 0);
    332 	mdelay(10);
    333 
    334 	for (i = 0; i < 10; ++i) {
    335 		uint32_t status;
    336 		for (j = 0; j < 100; ++j) {
    337 			status = RREG32(UVD_STATUS);
    338 			if (status & 2)
    339 				break;
    340 			mdelay(10);
    341 		}
    342 		r = 0;
    343 		if (status & 2)
    344 			break;
    345 
    346 		DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");
    347 		WREG32_P(UVD_SOFT_RESET, VCPU_SOFT_RESET, ~VCPU_SOFT_RESET);
    348 		mdelay(10);
    349 		WREG32_P(UVD_SOFT_RESET, 0, ~VCPU_SOFT_RESET);
    350 		mdelay(10);
    351 		r = -1;
    352 	}
    353 
    354 	if (r) {
    355 		DRM_ERROR("UVD not responding, giving up!!!\n");
    356 		return r;
    357 	}
    358 
    359 	/* enable interupt */
    360 	WREG32_P(UVD_MASTINT_EN, 3<<1, ~(3 << 1));
    361 
    362 	/* force RBC into idle state */
    363 	WREG32(UVD_RBC_RB_CNTL, 0x11010101);
    364 
    365 	/* Set the write pointer delay */
    366 	WREG32(UVD_RBC_RB_WPTR_CNTL, 0);
    367 
    368 	/* programm the 4GB memory segment for rptr and ring buffer */
    369 	WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) |
    370 				   (0x7 << 16) | (0x1U << 31));
    371 
    372 	/* Initialize the ring buffer's read and write pointers */
    373 	WREG32(UVD_RBC_RB_RPTR, 0x0);
    374 
    375 	ring->wptr = RREG32(UVD_RBC_RB_RPTR);
    376 	WREG32(UVD_RBC_RB_WPTR, ring->wptr);
    377 
    378 	/* set the ring address */
    379 	WREG32(UVD_RBC_RB_BASE, ring->gpu_addr);
    380 
    381 	/* Set ring buffer size */
    382 	rb_bufsz = order_base_2(ring->ring_size);
    383 	rb_bufsz = (0x1 << 8) | rb_bufsz;
    384 	WREG32_P(UVD_RBC_RB_CNTL, rb_bufsz, ~0x11f1f);
    385 
    386 	return 0;
    387 }
    388 
    389 /**
    390  * uvd_v1_0_stop - stop UVD block
    391  *
    392  * @rdev: radeon_device pointer
    393  *
    394  * stop the UVD block
    395  */
    396 void uvd_v1_0_stop(struct radeon_device *rdev)
    397 {
    398 	/* force RBC into idle state */
    399 	WREG32(UVD_RBC_RB_CNTL, 0x11010101);
    400 
    401 	/* Stall UMC and register bus before resetting VCPU */
    402 	WREG32_P(UVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
    403 	WREG32_P(UVD_RB_ARB_CTRL, 1 << 3, ~(1 << 3));
    404 	mdelay(1);
    405 
    406 	/* put VCPU into reset */
    407 	WREG32(UVD_SOFT_RESET, VCPU_SOFT_RESET);
    408 	mdelay(5);
    409 
    410 	/* disable VCPU clock */
    411 	WREG32(UVD_VCPU_CNTL, 0x0);
    412 
    413 	/* Unstall UMC and register bus */
    414 	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
    415 	WREG32_P(UVD_RB_ARB_CTRL, 0, ~(1 << 3));
    416 }
    417 
    418 /**
    419  * uvd_v1_0_ring_test - register write test
    420  *
    421  * @rdev: radeon_device pointer
    422  * @ring: radeon_ring pointer
    423  *
    424  * Test if we can successfully write to the context register
    425  */
    426 int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
    427 {
    428 	uint32_t tmp = 0;
    429 	unsigned i;
    430 	int r;
    431 
    432 	WREG32(UVD_CONTEXT_ID, 0xCAFEDEAD);
    433 	r = radeon_ring_lock(rdev, ring, 3);
    434 	if (r) {
    435 		DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n",
    436 			  ring->idx, r);
    437 		return r;
    438 	}
    439 	radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0));
    440 	radeon_ring_write(ring, 0xDEADBEEF);
    441 	radeon_ring_unlock_commit(rdev, ring, false);
    442 	for (i = 0; i < rdev->usec_timeout; i++) {
    443 		tmp = RREG32(UVD_CONTEXT_ID);
    444 		if (tmp == 0xDEADBEEF)
    445 			break;
    446 		udelay(1);
    447 	}
    448 
    449 	if (i < rdev->usec_timeout) {
    450 		DRM_INFO("ring test on %d succeeded in %d usecs\n",
    451 			 ring->idx, i);
    452 	} else {
    453 		DRM_ERROR("radeon: ring %d test failed (0x%08X)\n",
    454 			  ring->idx, tmp);
    455 		r = -EINVAL;
    456 	}
    457 	return r;
    458 }
    459 
    460 /**
    461  * uvd_v1_0_semaphore_emit - emit semaphore command
    462  *
    463  * @rdev: radeon_device pointer
    464  * @ring: radeon_ring pointer
    465  * @semaphore: semaphore to emit commands for
    466  * @emit_wait: true if we should emit a wait command
    467  *
    468  * Emit a semaphore command (either wait or signal) to the UVD ring.
    469  */
    470 bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
    471 			     struct radeon_ring *ring,
    472 			     struct radeon_semaphore *semaphore,
    473 			     bool emit_wait)
    474 {
    475 	/* disable semaphores for UVD V1 hardware */
    476 	return false;
    477 }
    478 
    479 /**
    480  * uvd_v1_0_ib_execute - execute indirect buffer
    481  *
    482  * @rdev: radeon_device pointer
    483  * @ib: indirect buffer to execute
    484  *
    485  * Write ring commands to execute the indirect buffer
    486  */
    487 void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
    488 {
    489 	struct radeon_ring *ring = &rdev->ring[ib->ring];
    490 
    491 	radeon_ring_write(ring, PACKET0(UVD_RBC_IB_BASE, 0));
    492 	radeon_ring_write(ring, ib->gpu_addr);
    493 	radeon_ring_write(ring, PACKET0(UVD_RBC_IB_SIZE, 0));
    494 	radeon_ring_write(ring, ib->length_dw);
    495 }
    496 
    497 /**
    498  * uvd_v1_0_ib_test - test ib execution
    499  *
    500  * @rdev: radeon_device pointer
    501  * @ring: radeon_ring pointer
    502  *
    503  * Test if we can successfully execute an IB
    504  */
    505 int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
    506 {
    507 	struct radeon_fence *fence = NULL;
    508 	int r;
    509 
    510 	if (rdev->family < CHIP_RV740)
    511 		r = radeon_set_uvd_clocks(rdev, 10000, 10000);
    512 	else
    513 		r = radeon_set_uvd_clocks(rdev, 53300, 40000);
    514 	if (r) {
    515 		DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r);
    516 		return r;
    517 	}
    518 
    519 	r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
    520 	if (r) {
    521 		DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
    522 		goto error;
    523 	}
    524 
    525 	r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, &fence);
    526 	if (r) {
    527 		DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
    528 		goto error;
    529 	}
    530 
    531 	r = radeon_fence_wait_timeout(fence, false, usecs_to_jiffies(
    532 		RADEON_USEC_IB_TEST_TIMEOUT));
    533 	if (r < 0) {
    534 		DRM_ERROR("radeon: fence wait failed (%d).\n", r);
    535 		goto error;
    536 	} else if (r == 0) {
    537 		DRM_ERROR("radeon: fence wait timed out.\n");
    538 		r = -ETIMEDOUT;
    539 		goto error;
    540 	}
    541 	r = 0;
    542 	DRM_INFO("ib test on ring %d succeeded\n",  ring->idx);
    543 error:
    544 	radeon_fence_unref(&fence);
    545 	radeon_set_uvd_clocks(rdev, 0, 0);
    546 	return r;
    547 }
    548