1 /* $NetBSD: radeon_vce_v1_0.c,v 1.2 2021/12/18 23:45:43 riastradh Exp $ */ 2 3 /* 4 * Copyright 2013 Advanced Micro Devices, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * The above copyright notice and this permission notice (including the 24 * next paragraph) shall be included in all copies or substantial portions 25 * of the Software. 26 * 27 * Authors: Christian Knig <christian.koenig (at) amd.com> 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: radeon_vce_v1_0.c,v 1.2 2021/12/18 23:45:43 riastradh Exp $"); 32 33 #include <linux/firmware.h> 34 35 #include "radeon.h" 36 #include "radeon_asic.h" 37 #include "sid.h" 38 39 #define VCE_V1_0_FW_SIZE (256 * 1024) 40 #define VCE_V1_0_STACK_SIZE (64 * 1024) 41 #define VCE_V1_0_DATA_SIZE (7808 * (RADEON_MAX_VCE_HANDLES + 1)) 42 43 struct vce_v1_0_fw_signature 44 { 45 int32_t off; 46 uint32_t len; 47 int32_t num; 48 struct { 49 uint32_t chip_id; 50 uint32_t keyselect; 51 uint32_t nonce[4]; 52 uint32_t sigval[4]; 53 } val[8]; 54 }; 55 56 /** 57 * vce_v1_0_get_rptr - get read pointer 58 * 59 * @rdev: radeon_device pointer 60 * @ring: radeon_ring pointer 61 * 62 * Returns the current hardware read pointer 63 */ 64 uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev, 65 struct radeon_ring *ring) 66 { 67 if (ring->idx == TN_RING_TYPE_VCE1_INDEX) 68 return RREG32(VCE_RB_RPTR); 69 else 70 return RREG32(VCE_RB_RPTR2); 71 } 72 73 /** 74 * vce_v1_0_get_wptr - get write pointer 75 * 76 * @rdev: radeon_device pointer 77 * @ring: radeon_ring pointer 78 * 79 * Returns the current hardware write pointer 80 */ 81 uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev, 82 struct radeon_ring *ring) 83 { 84 if (ring->idx == TN_RING_TYPE_VCE1_INDEX) 85 return RREG32(VCE_RB_WPTR); 86 else 87 return RREG32(VCE_RB_WPTR2); 88 } 89 90 /** 91 * vce_v1_0_set_wptr - set write pointer 92 * 93 * @rdev: radeon_device pointer 94 * @ring: radeon_ring pointer 95 * 96 * Commits the write pointer to the hardware 97 */ 98 void vce_v1_0_set_wptr(struct radeon_device *rdev, 99 struct radeon_ring *ring) 100 { 101 if (ring->idx == TN_RING_TYPE_VCE1_INDEX) 102 WREG32(VCE_RB_WPTR, ring->wptr); 103 else 104 WREG32(VCE_RB_WPTR2, ring->wptr); 105 } 106 107 void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable) 108 { 109 u32 tmp; 110 111 if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) { 112 tmp = RREG32(VCE_CLOCK_GATING_A); 113 tmp |= CGC_DYN_CLOCK_MODE; 114 WREG32(VCE_CLOCK_GATING_A, tmp); 115 116 tmp = RREG32(VCE_UENC_CLOCK_GATING); 117 tmp &= ~0x1ff000; 118 tmp |= 0xff800000; 119 WREG32(VCE_UENC_CLOCK_GATING, tmp); 120 121 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 122 tmp &= ~0x3ff; 123 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 124 } else { 125 tmp = RREG32(VCE_CLOCK_GATING_A); 126 tmp &= ~CGC_DYN_CLOCK_MODE; 127 WREG32(VCE_CLOCK_GATING_A, tmp); 128 129 tmp = RREG32(VCE_UENC_CLOCK_GATING); 130 tmp |= 0x1ff000; 131 tmp &= ~0xff800000; 132 WREG32(VCE_UENC_CLOCK_GATING, tmp); 133 134 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 135 tmp |= 0x3ff; 136 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 137 } 138 } 139 140 static void vce_v1_0_init_cg(struct radeon_device *rdev) 141 { 142 u32 tmp; 143 144 tmp = RREG32(VCE_CLOCK_GATING_A); 145 tmp |= CGC_DYN_CLOCK_MODE; 146 WREG32(VCE_CLOCK_GATING_A, tmp); 147 148 tmp = RREG32(VCE_CLOCK_GATING_B); 149 tmp |= 0x1e; 150 tmp &= ~0xe100e1; 151 WREG32(VCE_CLOCK_GATING_B, tmp); 152 153 tmp = RREG32(VCE_UENC_CLOCK_GATING); 154 tmp &= ~0xff9ff000; 155 WREG32(VCE_UENC_CLOCK_GATING, tmp); 156 157 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 158 tmp &= ~0x3ff; 159 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 160 } 161 162 int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data) 163 { 164 struct vce_v1_0_fw_signature *sign = (void*)rdev->vce_fw->data; 165 uint32_t chip_id; 166 int i; 167 168 switch (rdev->family) { 169 case CHIP_TAHITI: 170 chip_id = 0x01000014; 171 break; 172 case CHIP_VERDE: 173 chip_id = 0x01000015; 174 break; 175 case CHIP_PITCAIRN: 176 case CHIP_OLAND: 177 chip_id = 0x01000016; 178 break; 179 case CHIP_ARUBA: 180 chip_id = 0x01000017; 181 break; 182 default: 183 return -EINVAL; 184 } 185 186 for (i = 0; i < le32_to_cpu(sign->num); ++i) { 187 if (le32_to_cpu(sign->val[i].chip_id) == chip_id) 188 break; 189 } 190 191 if (i == le32_to_cpu(sign->num)) 192 return -EINVAL; 193 194 data += (256 - 64) / 4; 195 data[0] = sign->val[i].nonce[0]; 196 data[1] = sign->val[i].nonce[1]; 197 data[2] = sign->val[i].nonce[2]; 198 data[3] = sign->val[i].nonce[3]; 199 data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64); 200 201 memset(&data[5], 0, 44); 202 memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign)); 203 204 data += (le32_to_cpu(sign->len) + 64) / 4; 205 data[0] = sign->val[i].sigval[0]; 206 data[1] = sign->val[i].sigval[1]; 207 data[2] = sign->val[i].sigval[2]; 208 data[3] = sign->val[i].sigval[3]; 209 210 rdev->vce.keyselect = le32_to_cpu(sign->val[i].keyselect); 211 212 return 0; 213 } 214 215 unsigned vce_v1_0_bo_size(struct radeon_device *rdev) 216 { 217 WARN_ON(VCE_V1_0_FW_SIZE < rdev->vce_fw->size); 218 return VCE_V1_0_FW_SIZE + VCE_V1_0_STACK_SIZE + VCE_V1_0_DATA_SIZE; 219 } 220 221 int vce_v1_0_resume(struct radeon_device *rdev) 222 { 223 uint64_t addr = rdev->vce.gpu_addr; 224 uint32_t size; 225 int i; 226 227 WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16)); 228 WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 229 WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 230 WREG32(VCE_CLOCK_GATING_B, 0); 231 232 WREG32_P(VCE_LMI_FW_PERIODIC_CTRL, 0x4, ~0x4); 233 234 WREG32(VCE_LMI_CTRL, 0x00398000); 235 WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1); 236 WREG32(VCE_LMI_SWAP_CNTL, 0); 237 WREG32(VCE_LMI_SWAP_CNTL1, 0); 238 WREG32(VCE_LMI_VM_CTRL, 0); 239 240 WREG32(VCE_VCPU_SCRATCH7, RADEON_MAX_VCE_HANDLES); 241 242 addr += 256; 243 size = VCE_V1_0_FW_SIZE; 244 WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff); 245 WREG32(VCE_VCPU_CACHE_SIZE0, size); 246 247 addr += size; 248 size = VCE_V1_0_STACK_SIZE; 249 WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff); 250 WREG32(VCE_VCPU_CACHE_SIZE1, size); 251 252 addr += size; 253 size = VCE_V1_0_DATA_SIZE; 254 WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff); 255 WREG32(VCE_VCPU_CACHE_SIZE2, size); 256 257 WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100); 258 259 WREG32(VCE_LMI_FW_START_KEYSEL, rdev->vce.keyselect); 260 261 for (i = 0; i < 10; ++i) { 262 mdelay(10); 263 if (RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_DONE) 264 break; 265 } 266 267 if (i == 10) 268 return -ETIMEDOUT; 269 270 if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_PASS)) 271 return -EINVAL; 272 273 for (i = 0; i < 10; ++i) { 274 mdelay(10); 275 if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_BUSY)) 276 break; 277 } 278 279 if (i == 10) 280 return -ETIMEDOUT; 281 282 vce_v1_0_init_cg(rdev); 283 284 return 0; 285 } 286 287 /** 288 * vce_v1_0_start - start VCE block 289 * 290 * @rdev: radeon_device pointer 291 * 292 * Setup and start the VCE block 293 */ 294 int vce_v1_0_start(struct radeon_device *rdev) 295 { 296 struct radeon_ring *ring; 297 int i, j, r; 298 299 /* set BUSY flag */ 300 WREG32_P(VCE_STATUS, 1, ~1); 301 302 ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; 303 WREG32(VCE_RB_RPTR, ring->wptr); 304 WREG32(VCE_RB_WPTR, ring->wptr); 305 WREG32(VCE_RB_BASE_LO, ring->gpu_addr); 306 WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); 307 WREG32(VCE_RB_SIZE, ring->ring_size / 4); 308 309 ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; 310 WREG32(VCE_RB_RPTR2, ring->wptr); 311 WREG32(VCE_RB_WPTR2, ring->wptr); 312 WREG32(VCE_RB_BASE_LO2, ring->gpu_addr); 313 WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); 314 WREG32(VCE_RB_SIZE2, ring->ring_size / 4); 315 316 WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN); 317 318 WREG32_P(VCE_SOFT_RESET, 319 VCE_ECPU_SOFT_RESET | 320 VCE_FME_SOFT_RESET, ~( 321 VCE_ECPU_SOFT_RESET | 322 VCE_FME_SOFT_RESET)); 323 324 mdelay(100); 325 326 WREG32_P(VCE_SOFT_RESET, 0, ~( 327 VCE_ECPU_SOFT_RESET | 328 VCE_FME_SOFT_RESET)); 329 330 for (i = 0; i < 10; ++i) { 331 uint32_t status; 332 for (j = 0; j < 100; ++j) { 333 status = RREG32(VCE_STATUS); 334 if (status & 2) 335 break; 336 mdelay(10); 337 } 338 r = 0; 339 if (status & 2) 340 break; 341 342 DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); 343 WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET); 344 mdelay(10); 345 WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET); 346 mdelay(10); 347 r = -1; 348 } 349 350 /* clear BUSY flag */ 351 WREG32_P(VCE_STATUS, 0, ~1); 352 353 if (r) { 354 DRM_ERROR("VCE not responding, giving up!!!\n"); 355 return r; 356 } 357 358 return 0; 359 } 360 361 int vce_v1_0_init(struct radeon_device *rdev) 362 { 363 struct radeon_ring *ring; 364 int r; 365 366 r = vce_v1_0_start(rdev); 367 if (r) 368 return r; 369 370 ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; 371 ring->ready = true; 372 r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring); 373 if (r) { 374 ring->ready = false; 375 return r; 376 } 377 378 ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; 379 ring->ready = true; 380 r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring); 381 if (r) { 382 ring->ready = false; 383 return r; 384 } 385 386 DRM_INFO("VCE initialized successfully.\n"); 387 388 return 0; 389 } 390