1 /* 2 * Copyright 2013 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19 * USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * The above copyright notice and this permission notice (including the 22 * next paragraph) shall be included in all copies or substantial portions 23 * of the Software. 24 * 25 * Authors: Christian König <christian.koenig@amd.com> 26 */ 27 28 #include <linux/firmware.h> 29 #include <drm/drmP.h> 30 #include "radeon.h" 31 #include "radeon_asic.h" 32 #include "cikd.h" 33 34 static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated) 35 { 36 u32 tmp; 37 38 if (gated) { 39 tmp = RREG32(VCE_CLOCK_GATING_B); 40 tmp |= 0xe70000; 41 WREG32(VCE_CLOCK_GATING_B, tmp); 42 43 tmp = RREG32(VCE_UENC_CLOCK_GATING); 44 tmp |= 0xff000000; 45 WREG32(VCE_UENC_CLOCK_GATING, tmp); 46 47 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 48 tmp &= ~0x3fc; 49 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 50 51 WREG32(VCE_CGTT_CLK_OVERRIDE, 0); 52 } else { 53 tmp = RREG32(VCE_CLOCK_GATING_B); 54 tmp |= 0xe7; 55 tmp &= ~0xe70000; 56 WREG32(VCE_CLOCK_GATING_B, tmp); 57 58 tmp = RREG32(VCE_UENC_CLOCK_GATING); 59 tmp |= 0x1fe000; 60 tmp &= ~0xff000000; 61 WREG32(VCE_UENC_CLOCK_GATING, tmp); 62 63 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 64 tmp |= 0x3fc; 65 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 66 } 67 } 68 69 static void vce_v2_0_set_dyn_cg(struct radeon_device *rdev, bool gated) 70 { 71 u32 orig, tmp; 72 73 tmp = RREG32(VCE_CLOCK_GATING_B); 74 tmp &= ~0x00060006; 75 if (gated) { 76 tmp |= 0xe10000; 77 } else { 78 tmp |= 0xe1; 79 tmp &= ~0xe10000; 80 } 81 WREG32(VCE_CLOCK_GATING_B, tmp); 82 83 orig = tmp = RREG32(VCE_UENC_CLOCK_GATING); 84 tmp &= ~0x1fe000; 85 tmp &= ~0xff000000; 86 if (tmp != orig) 87 WREG32(VCE_UENC_CLOCK_GATING, tmp); 88 89 orig = tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); 90 tmp &= ~0x3fc; 91 if (tmp != orig) 92 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); 93 94 if (gated) 95 WREG32(VCE_CGTT_CLK_OVERRIDE, 0); 96 } 97 98 static void vce_v2_0_disable_cg(struct radeon_device *rdev) 99 { 100 WREG32(VCE_CGTT_CLK_OVERRIDE, 7); 101 } 102 103 void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable) 104 { 105 bool sw_cg = false; 106 107 if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) { 108 if (sw_cg) 109 vce_v2_0_set_sw_cg(rdev, true); 110 else 111 vce_v2_0_set_dyn_cg(rdev, true); 112 } else { 113 vce_v2_0_disable_cg(rdev); 114 115 if (sw_cg) 116 vce_v2_0_set_sw_cg(rdev, false); 117 else 118 vce_v2_0_set_dyn_cg(rdev, false); 119 } 120 } 121 122 static void vce_v2_0_init_cg(struct radeon_device *rdev) 123 { 124 u32 tmp; 125 126 tmp = RREG32(VCE_CLOCK_GATING_A); 127 tmp &= ~(CGC_CLK_GATE_DLY_TIMER_MASK | CGC_CLK_GATER_OFF_DLY_TIMER_MASK); 128 tmp |= (CGC_CLK_GATE_DLY_TIMER(0) | CGC_CLK_GATER_OFF_DLY_TIMER(4)); 129 tmp |= CGC_UENC_WAIT_AWAKE; 130 WREG32(VCE_CLOCK_GATING_A, tmp); 131 132 tmp = RREG32(VCE_UENC_CLOCK_GATING); 133 tmp &= ~(CLOCK_ON_DELAY_MASK | CLOCK_OFF_DELAY_MASK); 134 tmp |= (CLOCK_ON_DELAY(0) | CLOCK_OFF_DELAY(4)); 135 WREG32(VCE_UENC_CLOCK_GATING, tmp); 136 137 tmp = RREG32(VCE_CLOCK_GATING_B); 138 tmp |= 0x10; 139 tmp &= ~0x100000; 140 WREG32(VCE_CLOCK_GATING_B, tmp); 141 } 142 143 int vce_v2_0_resume(struct radeon_device *rdev) 144 { 145 uint64_t addr = rdev->vce.gpu_addr; 146 uint32_t size; 147 148 WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16)); 149 WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); 150 WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); 151 WREG32(VCE_CLOCK_GATING_B, 0xf7); 152 153 WREG32(VCE_LMI_CTRL, 0x00398000); 154 WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1); 155 WREG32(VCE_LMI_SWAP_CNTL, 0); 156 WREG32(VCE_LMI_SWAP_CNTL1, 0); 157 WREG32(VCE_LMI_VM_CTRL, 0); 158 159 WREG32(VCE_LMI_VCPU_CACHE_40BIT_BAR, addr >> 8); 160 161 addr &= 0xff; 162 size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size); 163 WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff); 164 WREG32(VCE_VCPU_CACHE_SIZE0, size); 165 166 addr += size; 167 size = RADEON_VCE_STACK_SIZE; 168 WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff); 169 WREG32(VCE_VCPU_CACHE_SIZE1, size); 170 171 addr += size; 172 size = RADEON_VCE_HEAP_SIZE; 173 WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff); 174 WREG32(VCE_VCPU_CACHE_SIZE2, size); 175 176 WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100); 177 178 WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 179 ~VCE_SYS_INT_TRAP_INTERRUPT_EN); 180 181 vce_v2_0_init_cg(rdev); 182 183 return 0; 184 } 185