1 /* $NetBSD: radeon_uvd_v2_2.c,v 1.3 2021/12/18 23:45:43 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_v2_2.c,v 1.3 2021/12/18 23:45:43 riastradh Exp $"); 29 30 #include <linux/firmware.h> 31 32 #include "radeon.h" 33 #include "radeon_asic.h" 34 #include "rv770d.h" 35 36 /** 37 * uvd_v2_2_fence_emit - emit an fence & trap command 38 * 39 * @rdev: radeon_device pointer 40 * @fence: fence to emit 41 * 42 * Write a fence and a trap command to the ring. 43 */ 44 void uvd_v2_2_fence_emit(struct radeon_device *rdev, 45 struct radeon_fence *fence) 46 { 47 struct radeon_ring *ring = &rdev->ring[fence->ring]; 48 uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr; 49 50 radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0)); 51 radeon_ring_write(ring, fence->seq); 52 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0)); 53 radeon_ring_write(ring, lower_32_bits(addr)); 54 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0)); 55 radeon_ring_write(ring, upper_32_bits(addr) & 0xff); 56 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0)); 57 radeon_ring_write(ring, 0); 58 59 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA0, 0)); 60 radeon_ring_write(ring, 0); 61 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_DATA1, 0)); 62 radeon_ring_write(ring, 0); 63 radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0)); 64 radeon_ring_write(ring, 2); 65 } 66 67 /** 68 * uvd_v2_2_semaphore_emit - emit semaphore command 69 * 70 * @rdev: radeon_device pointer 71 * @ring: radeon_ring pointer 72 * @semaphore: semaphore to emit commands for 73 * @emit_wait: true if we should emit a wait command 74 * 75 * Emit a semaphore command (either wait or signal) to the UVD ring. 76 */ 77 bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, 78 struct radeon_ring *ring, 79 struct radeon_semaphore *semaphore, 80 bool emit_wait) 81 { 82 uint64_t addr = semaphore->gpu_addr; 83 84 radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); 85 radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); 86 87 radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); 88 radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); 89 90 radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); 91 radeon_ring_write(ring, emit_wait ? 1 : 0); 92 93 return true; 94 } 95 96 /** 97 * uvd_v2_2_resume - memory controller programming 98 * 99 * @rdev: radeon_device pointer 100 * 101 * Let the UVD memory controller know it's offsets 102 */ 103 int uvd_v2_2_resume(struct radeon_device *rdev) 104 { 105 uint64_t addr; 106 uint32_t chip_id, size; 107 int r; 108 109 /* RV770 uses V1.0 MC */ 110 if (rdev->family == CHIP_RV770) 111 return uvd_v1_0_resume(rdev); 112 113 r = radeon_uvd_resume(rdev); 114 if (r) 115 return r; 116 117 /* programm the VCPU memory controller bits 0-27 */ 118 addr = rdev->uvd.gpu_addr >> 3; 119 size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; 120 WREG32(UVD_VCPU_CACHE_OFFSET0, addr); 121 WREG32(UVD_VCPU_CACHE_SIZE0, size); 122 123 addr += size; 124 size = RADEON_UVD_HEAP_SIZE >> 3; 125 WREG32(UVD_VCPU_CACHE_OFFSET1, addr); 126 WREG32(UVD_VCPU_CACHE_SIZE1, size); 127 128 addr += size; 129 size = (RADEON_UVD_STACK_SIZE + 130 (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3; 131 WREG32(UVD_VCPU_CACHE_OFFSET2, addr); 132 WREG32(UVD_VCPU_CACHE_SIZE2, size); 133 134 /* bits 28-31 */ 135 addr = (rdev->uvd.gpu_addr >> 28) & 0xF; 136 WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0)); 137 138 /* bits 32-39 */ 139 addr = (rdev->uvd.gpu_addr >> 32) & 0xFF; 140 WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1U << 31)); 141 142 /* tell firmware which hardware it is running on */ 143 switch (rdev->family) { 144 default: 145 return -EINVAL; 146 case CHIP_RV710: 147 chip_id = 0x01000005; 148 break; 149 case CHIP_RV730: 150 chip_id = 0x01000006; 151 break; 152 case CHIP_RV740: 153 chip_id = 0x01000007; 154 break; 155 case CHIP_CYPRESS: 156 case CHIP_HEMLOCK: 157 chip_id = 0x01000008; 158 break; 159 case CHIP_JUNIPER: 160 chip_id = 0x01000009; 161 break; 162 case CHIP_REDWOOD: 163 chip_id = 0x0100000a; 164 break; 165 case CHIP_CEDAR: 166 chip_id = 0x0100000b; 167 break; 168 case CHIP_SUMO: 169 case CHIP_SUMO2: 170 chip_id = 0x0100000c; 171 break; 172 case CHIP_PALM: 173 chip_id = 0x0100000e; 174 break; 175 case CHIP_CAYMAN: 176 chip_id = 0x0100000f; 177 break; 178 case CHIP_BARTS: 179 chip_id = 0x01000010; 180 break; 181 case CHIP_TURKS: 182 chip_id = 0x01000011; 183 break; 184 case CHIP_CAICOS: 185 chip_id = 0x01000012; 186 break; 187 case CHIP_TAHITI: 188 chip_id = 0x01000014; 189 break; 190 case CHIP_VERDE: 191 chip_id = 0x01000015; 192 break; 193 case CHIP_PITCAIRN: 194 case CHIP_OLAND: 195 chip_id = 0x01000016; 196 break; 197 case CHIP_ARUBA: 198 chip_id = 0x01000017; 199 break; 200 } 201 WREG32(UVD_VCPU_CHIP_ID, chip_id); 202 203 return 0; 204 } 205