1/* $NetBSD: radeon_vce_v2_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 K��nig <christian.koenig@amd.com> 28 */ 29 30#include <sys/cdefs.h> 31__KERNEL_RCSID(0, "$NetBSD: radeon_vce_v2_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 "cikd.h" 38 39#define VCE_V2_0_FW_SIZE (256 * 1024) 40#define VCE_V2_0_STACK_SIZE (64 * 1024) 41#define VCE_V2_0_DATA_SIZE (23552 * RADEON_MAX_VCE_HANDLES) 42 43static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated) 44{ 45 u32 tmp; 46 47 if (gated) { 48 tmp = RREG32(VCE_CLOCK_GATING_B); 49 tmp |= 0xe70000; 50 WREG32(VCE_CLOCK_GATING_B, tmp); 51 52 tmp = RREG32(VCE_UENC_CLOCK_GATING); 53 tmp |= 0xff000000; 54 WREG32(VCE_UENC_CLOCK_GATING, tmp); 55 56 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 57 tmp &= ~0x3fc; 58 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 59 60 WREG32(VCE_CGTT_CLK_OVERRIDE, 0); 61 } else { 62 tmp = RREG32(VCE_CLOCK_GATING_B); 63 tmp |= 0xe7; 64 tmp &= ~0xe70000; 65 WREG32(VCE_CLOCK_GATING_B, tmp); 66 67 tmp = RREG32(VCE_UENC_CLOCK_GATING); 68 tmp |= 0x1fe000; 69 tmp &= ~0xff000000; 70 WREG32(VCE_UENC_CLOCK_GATING, tmp); 71 72 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 73 tmp |= 0x3fc; 74 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 75 } 76} 77 78static void vce_v2_0_set_dyn_cg(struct radeon_device *rdev, bool gated) 79{ 80 u32 orig, tmp; 81 82 tmp = RREG32(VCE_CLOCK_GATING_B); 83 tmp &= ~0x00060006; 84 if (gated) { 85 tmp |= 0xe10000; 86 } else { 87 tmp |= 0xe1; 88 tmp &= ~0xe10000; 89 } 90 WREG32(VCE_CLOCK_GATING_B, tmp); 91 92 orig = tmp = RREG32(VCE_UENC_CLOCK_GATING); 93 tmp &= ~0x1fe000; 94 tmp &= ~0xff000000; 95 if (tmp != orig) 96 WREG32(VCE_UENC_CLOCK_GATING, tmp); 97 98 orig = tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 99 tmp &= ~0x3fc; 100 if (tmp != orig) 101 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 102 103 if (gated) 104 WREG32(VCE_CGTT_CLK_OVERRIDE, 0); 105} 106 107static void vce_v2_0_disable_cg(struct radeon_device *rdev) 108{ 109 WREG32(VCE_CGTT_CLK_OVERRIDE, 7); 110} 111 112/* 113 * Local variable sw_cg is used for debugging purposes, in case we 114 * ran into problems with dynamic clock gating. Don't remove it. 115 */ 116void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable) 117{ 118 bool sw_cg = false; 119 120 if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) { 121 if (sw_cg) 122 vce_v2_0_set_sw_cg(rdev, true); 123 else 124 vce_v2_0_set_dyn_cg(rdev, true); 125 } else { 126 vce_v2_0_disable_cg(rdev); 127 128 if (sw_cg) 129 vce_v2_0_set_sw_cg(rdev, false); 130 else 131 vce_v2_0_set_dyn_cg(rdev, false); 132 } 133} 134 135static void vce_v2_0_init_cg(struct radeon_device *rdev) 136{ 137 u32 tmp; 138 139 tmp = RREG32(VCE_CLOCK_GATING_A); 140 tmp &= ~(CGC_CLK_GATE_DLY_TIMER_MASK | CGC_CLK_GATER_OFF_DLY_TIMER_MASK); 141 tmp |= (CGC_CLK_GATE_DLY_TIMER(0) | CGC_CLK_GATER_OFF_DLY_TIMER(4)); 142 tmp |= CGC_UENC_WAIT_AWAKE; 143 WREG32(VCE_CLOCK_GATING_A, tmp); 144 145 tmp = RREG32(VCE_UENC_CLOCK_GATING); 146 tmp &= ~(CLOCK_ON_DELAY_MASK | CLOCK_OFF_DELAY_MASK); 147 tmp |= (CLOCK_ON_DELAY(0) | CLOCK_OFF_DELAY(4)); 148 WREG32(VCE_UENC_CLOCK_GATING, tmp); 149 150 tmp = RREG32(VCE_CLOCK_GATING_B); 151 tmp |= 0x10; 152 tmp &= ~0x100000; 153 WREG32(VCE_CLOCK_GATING_B, tmp); 154} 155 156unsigned vce_v2_0_bo_size(struct radeon_device *rdev) 157{ 158 WARN_ON(rdev->vce_fw->size > VCE_V2_0_FW_SIZE); 159 return VCE_V2_0_FW_SIZE + VCE_V2_0_STACK_SIZE + VCE_V2_0_DATA_SIZE; 160} 161 162int vce_v2_0_resume(struct radeon_device *rdev) 163{ 164 uint64_t addr = rdev->vce.gpu_addr; 165 uint32_t size; 166 167 WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16)); 168 WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 169 WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 170 WREG32(VCE_CLOCK_GATING_B, 0xf7); 171 172 WREG32(VCE_LMI_CTRL, 0x00398000); 173 WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1); 174 WREG32(VCE_LMI_SWAP_CNTL, 0); 175 WREG32(VCE_LMI_SWAP_CNTL1, 0); 176 WREG32(VCE_LMI_VM_CTRL, 0); 177 178 WREG32(VCE_LMI_VCPU_CACHE_40BIT_BAR, addr >> 8); 179 180 addr &= 0xff; 181 size = VCE_V2_0_FW_SIZE; 182 WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff); 183 WREG32(VCE_VCPU_CACHE_SIZE0, size); 184 185 addr += size; 186 size = VCE_V2_0_STACK_SIZE; 187 WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff); 188 WREG32(VCE_VCPU_CACHE_SIZE1, size); 189 190 addr += size; 191 size = VCE_V2_0_DATA_SIZE; 192 WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff); 193 WREG32(VCE_VCPU_CACHE_SIZE2, size); 194 195 WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100); 196 197 WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 198 ~VCE_SYS_INT_TRAP_INTERRUPT_EN); 199 200 vce_v2_0_init_cg(rdev); 201 202 return 0; 203} 204