File: | dev/pci/drm/radeon/sumo_dpm.c |
Warning: | line 423, column 9 The right operand of '*' is a garbage value due to array index out of bounds |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright 2012 Advanced Micro Devices, Inc. | |||
3 | * | |||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
5 | * copy of this software and associated documentation files (the "Software"), | |||
6 | * to deal in the Software without restriction, including without limitation | |||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
8 | * and/or sell copies of the Software, and to permit persons to whom the | |||
9 | * Software is furnished to do so, subject to the following conditions: | |||
10 | * | |||
11 | * The above copyright notice and this permission notice shall be included in | |||
12 | * all copies or substantial portions of the Software. | |||
13 | * | |||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
20 | * OTHER DEALINGS IN THE SOFTWARE. | |||
21 | * | |||
22 | */ | |||
23 | ||||
24 | #include "radeon.h" | |||
25 | #include "radeon_asic.h" | |||
26 | #include "sumod.h" | |||
27 | #include "r600_dpm.h" | |||
28 | #include "cypress_dpm.h" | |||
29 | #include "sumo_dpm.h" | |||
30 | #include <linux/seq_file.h> | |||
31 | ||||
32 | #define SUMO_MAX_DEEPSLEEP_DIVIDER_ID5 5 | |||
33 | #define SUMO_MINIMUM_ENGINE_CLOCK800 800 | |||
34 | #define BOOST_DPM_LEVEL7 7 | |||
35 | ||||
36 | static const u32 sumo_utc[SUMO_PM_NUMBER_OF_TC15] = | |||
37 | { | |||
38 | SUMO_UTC_DFLT_000x48, | |||
39 | SUMO_UTC_DFLT_010x44, | |||
40 | SUMO_UTC_DFLT_020x44, | |||
41 | SUMO_UTC_DFLT_030x44, | |||
42 | SUMO_UTC_DFLT_040x44, | |||
43 | SUMO_UTC_DFLT_050x44, | |||
44 | SUMO_UTC_DFLT_060x44, | |||
45 | SUMO_UTC_DFLT_070x44, | |||
46 | SUMO_UTC_DFLT_080x44, | |||
47 | SUMO_UTC_DFLT_090x44, | |||
48 | SUMO_UTC_DFLT_100x44, | |||
49 | SUMO_UTC_DFLT_110x44, | |||
50 | SUMO_UTC_DFLT_120x44, | |||
51 | SUMO_UTC_DFLT_130x44, | |||
52 | SUMO_UTC_DFLT_140x44, | |||
53 | }; | |||
54 | ||||
55 | static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC15] = | |||
56 | { | |||
57 | SUMO_DTC_DFLT_000x48, | |||
58 | SUMO_DTC_DFLT_010x44, | |||
59 | SUMO_DTC_DFLT_020x44, | |||
60 | SUMO_DTC_DFLT_030x44, | |||
61 | SUMO_DTC_DFLT_040x44, | |||
62 | SUMO_DTC_DFLT_050x44, | |||
63 | SUMO_DTC_DFLT_060x44, | |||
64 | SUMO_DTC_DFLT_070x44, | |||
65 | SUMO_DTC_DFLT_080x44, | |||
66 | SUMO_DTC_DFLT_090x44, | |||
67 | SUMO_DTC_DFLT_100x44, | |||
68 | SUMO_DTC_DFLT_110x44, | |||
69 | SUMO_DTC_DFLT_120x44, | |||
70 | SUMO_DTC_DFLT_130x44, | |||
71 | SUMO_DTC_DFLT_140x44, | |||
72 | }; | |||
73 | ||||
74 | static struct sumo_ps *sumo_get_ps(struct radeon_ps *rps) | |||
75 | { | |||
76 | struct sumo_ps *ps = rps->ps_priv; | |||
77 | ||||
78 | return ps; | |||
79 | } | |||
80 | ||||
81 | struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev) | |||
82 | { | |||
83 | struct sumo_power_info *pi = rdev->pm.dpm.priv; | |||
84 | ||||
85 | return pi; | |||
86 | } | |||
87 | ||||
88 | static void sumo_gfx_clockgating_enable(struct radeon_device *rdev, bool_Bool enable) | |||
89 | { | |||
90 | if (enable) | |||
91 | WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 7)); tmp_ |= (((1 << 7)) & ~(~(1 << 7))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0); | |||
92 | else { | |||
93 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 7)); tmp_ |= ((0) & ~(~(1 << 7))); r100_mm_wreg (rdev, (0x644), (tmp_), 0); } while (0); | |||
94 | WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 8)); tmp_ |= (((1 << 8)) & ~(~(1 << 8))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0); | |||
95 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 8)); tmp_ |= ((0) & ~(~(1 << 8))); r100_mm_wreg (rdev, (0x644), (tmp_), 0); } while (0); | |||
96 | RREG32(GB_ADDR_CONFIG)r100_mm_rreg(rdev, (0x98f8), 0); | |||
97 | } | |||
98 | } | |||
99 | ||||
100 | #define CGCG_CGTT_LOCAL0_MASK0xE5BFFFFF 0xE5BFFFFF | |||
101 | #define CGCG_CGTT_LOCAL1_MASK0xEFFF07FF 0xEFFF07FF | |||
102 | ||||
103 | static void sumo_mg_clockgating_enable(struct radeon_device *rdev, bool_Bool enable) | |||
104 | { | |||
105 | u32 local0; | |||
106 | u32 local1; | |||
107 | ||||
108 | local0 = RREG32(CG_CGTT_LOCAL_0)r100_mm_rreg(rdev, (0x7d0), 0); | |||
109 | local1 = RREG32(CG_CGTT_LOCAL_1)r100_mm_rreg(rdev, (0x7d4), 0); | |||
110 | ||||
111 | if (enable) { | |||
112 | WREG32(CG_CGTT_LOCAL_0, (0 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) )r100_mm_wreg(rdev, (0x7d0), ((0 & 0xE5BFFFFF) | (local0 & ~0xE5BFFFFF)), 0); | |||
113 | WREG32(CG_CGTT_LOCAL_1, (0 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) )r100_mm_wreg(rdev, (0x7d4), ((0 & 0xEFFF07FF) | (local1 & ~0xEFFF07FF)), 0); | |||
114 | } else { | |||
115 | WREG32(CG_CGTT_LOCAL_0, (0xFFFFFFFF & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) )r100_mm_wreg(rdev, (0x7d0), ((0xFFFFFFFF & 0xE5BFFFFF) | ( local0 & ~0xE5BFFFFF)), 0); | |||
116 | WREG32(CG_CGTT_LOCAL_1, (0xFFFFCFFF & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) )r100_mm_wreg(rdev, (0x7d4), ((0xFFFFCFFF & 0xEFFF07FF) | ( local1 & ~0xEFFF07FF)), 0); | |||
117 | } | |||
118 | } | |||
119 | ||||
120 | static void sumo_program_git(struct radeon_device *rdev) | |||
121 | { | |||
122 | u32 p, u; | |||
123 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
124 | ||||
125 | r600_calculate_u_and_p(SUMO_GICST_DFLT19, | |||
126 | xclk, 16, &p, &u); | |||
127 | ||||
128 | WREG32_P(CG_GIT, CG_GICST(p), ~CG_GICST_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6d8), 0); tmp_ &= (~(0xffff << 0)); tmp_ |= ((((p) << 0)) & ~( ~(0xffff << 0))); r100_mm_wreg(rdev, (0x6d8), (tmp_), 0 ); } while (0); | |||
129 | } | |||
130 | ||||
131 | static void sumo_program_grsd(struct radeon_device *rdev) | |||
132 | { | |||
133 | u32 p, u; | |||
134 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
135 | u32 grs = 256 * 25 / 100; | |||
136 | ||||
137 | r600_calculate_u_and_p(1, xclk, 14, &p, &u); | |||
138 | ||||
139 | WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u))r100_mm_wreg(rdev, (0x68c), (((grs) << 0) | ((p) << 9) | ((u) << 23)), 0); | |||
140 | } | |||
141 | ||||
142 | void sumo_gfx_clockgating_initialize(struct radeon_device *rdev) | |||
143 | { | |||
144 | sumo_program_git(rdev); | |||
145 | sumo_program_grsd(rdev); | |||
146 | } | |||
147 | ||||
148 | static void sumo_gfx_powergating_initialize(struct radeon_device *rdev) | |||
149 | { | |||
150 | u32 rcu_pwr_gating_cntl; | |||
151 | u32 p, u; | |||
152 | u32 p_c, p_p, d_p; | |||
153 | u32 r_t, i_t; | |||
154 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
155 | ||||
156 | if (rdev->family == CHIP_PALM) { | |||
157 | p_c = 4; | |||
158 | d_p = 10; | |||
159 | r_t = 10; | |||
160 | i_t = 4; | |||
161 | p_p = 50 + 1000/200 + 6 * 32; | |||
162 | } else { | |||
163 | p_c = 16; | |||
164 | d_p = 50; | |||
165 | r_t = 50; | |||
166 | i_t = 50; | |||
167 | p_p = 113; | |||
168 | } | |||
169 | ||||
170 | WREG32(CG_SCRATCH2, 0x01B60A17)r100_mm_wreg(rdev, (0x824), (0x01B60A17), 0); | |||
171 | ||||
172 | r600_calculate_u_and_p(SUMO_GFXPOWERGATINGT_DFLT100, | |||
173 | xclk, 16, &p, &u); | |||
174 | ||||
175 | WREG32_P(CG_PWR_GATING_CNTL, PGP(p) | PGU(u),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &= (~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p) << 8) | ((u) << 24)) & ~(~((0xffff << 8 ) | (0xf << 24)))); r100_mm_wreg(rdev, (0x7ac), (tmp_), 0); } while (0) | |||
176 | ~(PGP_MASK | PGU_MASK))do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &= (~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p) << 8) | ((u) << 24)) & ~(~((0xffff << 8 ) | (0xf << 24)))); r100_mm_wreg(rdev, (0x7ac), (tmp_), 0); } while (0); | |||
177 | ||||
178 | r600_calculate_u_and_p(SUMO_VOLTAGEDROPT_DFLT1, | |||
179 | xclk, 16, &p, &u); | |||
180 | ||||
181 | WREG32_P(CG_CG_VOLTAGE_CNTL, PGP(p) | PGU(u),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &= (~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p) << 8) | ((u) << 24)) & ~(~((0xffff << 8 ) | (0xf << 24)))); r100_mm_wreg(rdev, (0x770), (tmp_), 0); } while (0) | |||
182 | ~(PGP_MASK | PGU_MASK))do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &= (~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p) << 8) | ((u) << 24)) & ~(~((0xffff << 8 ) | (0xf << 24)))); r100_mm_wreg(rdev, (0x770), (tmp_), 0); } while (0); | |||
183 | ||||
184 | if (rdev->family == CHIP_PALM) { | |||
185 | WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x10103210)r600_rcu_wreg(rdev, (0x408), (0x10103210)); | |||
186 | WREG32_RCU(RCU_PWR_GATING_SEQ1, 0x10101010)r600_rcu_wreg(rdev, (0x40c), (0x10101010)); | |||
187 | } else { | |||
188 | WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x76543210)r600_rcu_wreg(rdev, (0x408), (0x76543210)); | |||
189 | WREG32_RCU(RCU_PWR_GATING_SEQ1, 0xFEDCBA98)r600_rcu_wreg(rdev, (0x40c), (0xFEDCBA98)); | |||
190 | } | |||
191 | ||||
192 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL)r600_rcu_rreg(rdev, (0x410)); | |||
193 | rcu_pwr_gating_cntl &= | |||
194 | ~(RSVD_MASK(0x3 << 1) | PCV_MASK(0x1f << 3) | PGS_MASK(0xf << 28)); | |||
195 | rcu_pwr_gating_cntl |= PCV(p_c)((p_c) << 3) | PGS(1)((1) << 28) | PWR_GATING_EN(1 << 0); | |||
196 | if (rdev->family == CHIP_PALM) { | |||
197 | rcu_pwr_gating_cntl &= ~PCP_MASK(0xf << 8); | |||
198 | rcu_pwr_gating_cntl |= PCP(0x77)((0x77) << 8); | |||
199 | } | |||
200 | WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x410), (rcu_pwr_gating_cntl)); | |||
201 | ||||
202 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2)r600_rcu_rreg(rdev, (0x4a0)); | |||
203 | rcu_pwr_gating_cntl &= ~(MPPU_MASK(0xffff << 0) | MPPD_MASK(0xffff << 16)); | |||
204 | rcu_pwr_gating_cntl |= MPPU(p_p)((p_p) << 0) | MPPD(50)((50) << 16); | |||
205 | WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a0), (rcu_pwr_gating_cntl)); | |||
206 | ||||
207 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3)r600_rcu_rreg(rdev, (0x4a4)); | |||
208 | rcu_pwr_gating_cntl &= ~(DPPU_MASK(0xffff << 0) | DPPD_MASK(0xffff << 16)); | |||
209 | rcu_pwr_gating_cntl |= DPPU(d_p)((d_p) << 0) | DPPD(50)((50) << 16); | |||
210 | WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a4), (rcu_pwr_gating_cntl)); | |||
211 | ||||
212 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_4)r600_rcu_rreg(rdev, (0x4a8)); | |||
213 | rcu_pwr_gating_cntl &= ~(RT_MASK(0xffff << 0) | IT_MASK(0xffff << 16)); | |||
214 | rcu_pwr_gating_cntl |= RT(r_t)((r_t) << 0) | IT(i_t)((i_t) << 16); | |||
215 | WREG32_RCU(RCU_PWR_GATING_CNTL_4, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a8), (rcu_pwr_gating_cntl)); | |||
216 | ||||
217 | if (rdev->family == CHIP_PALM) | |||
218 | WREG32_RCU(RCU_PWR_GATING_CNTL_5, 0xA02)r600_rcu_wreg(rdev, (0x504), (0xA02)); | |||
219 | ||||
220 | sumo_smu_pg_init(rdev); | |||
221 | ||||
222 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL)r600_rcu_rreg(rdev, (0x410)); | |||
223 | rcu_pwr_gating_cntl &= | |||
224 | ~(RSVD_MASK(0x3 << 1) | PCV_MASK(0x1f << 3) | PGS_MASK(0xf << 28)); | |||
225 | rcu_pwr_gating_cntl |= PCV(p_c)((p_c) << 3) | PGS(4)((4) << 28) | PWR_GATING_EN(1 << 0); | |||
226 | if (rdev->family == CHIP_PALM) { | |||
227 | rcu_pwr_gating_cntl &= ~PCP_MASK(0xf << 8); | |||
228 | rcu_pwr_gating_cntl |= PCP(0x77)((0x77) << 8); | |||
229 | } | |||
230 | WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x410), (rcu_pwr_gating_cntl)); | |||
231 | ||||
232 | if (rdev->family == CHIP_PALM) { | |||
233 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2)r600_rcu_rreg(rdev, (0x4a0)); | |||
234 | rcu_pwr_gating_cntl &= ~(MPPU_MASK(0xffff << 0) | MPPD_MASK(0xffff << 16)); | |||
235 | rcu_pwr_gating_cntl |= MPPU(113)((113) << 0) | MPPD(50)((50) << 16); | |||
236 | WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a0), (rcu_pwr_gating_cntl)); | |||
237 | ||||
238 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3)r600_rcu_rreg(rdev, (0x4a4)); | |||
239 | rcu_pwr_gating_cntl &= ~(DPPU_MASK(0xffff << 0) | DPPD_MASK(0xffff << 16)); | |||
240 | rcu_pwr_gating_cntl |= DPPU(16)((16) << 0) | DPPD(50)((50) << 16); | |||
241 | WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a4), (rcu_pwr_gating_cntl)); | |||
242 | } | |||
243 | ||||
244 | sumo_smu_pg_init(rdev); | |||
245 | ||||
246 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL)r600_rcu_rreg(rdev, (0x410)); | |||
247 | rcu_pwr_gating_cntl &= | |||
248 | ~(RSVD_MASK(0x3 << 1) | PCV_MASK(0x1f << 3) | PGS_MASK(0xf << 28)); | |||
249 | rcu_pwr_gating_cntl |= PGS(5)((5) << 28) | PWR_GATING_EN(1 << 0); | |||
250 | ||||
251 | if (rdev->family == CHIP_PALM) { | |||
252 | rcu_pwr_gating_cntl |= PCV(4)((4) << 3); | |||
253 | rcu_pwr_gating_cntl &= ~PCP_MASK(0xf << 8); | |||
254 | rcu_pwr_gating_cntl |= PCP(0x77)((0x77) << 8); | |||
255 | } else | |||
256 | rcu_pwr_gating_cntl |= PCV(11)((11) << 3); | |||
257 | WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x410), (rcu_pwr_gating_cntl)); | |||
258 | ||||
259 | if (rdev->family == CHIP_PALM) { | |||
260 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2)r600_rcu_rreg(rdev, (0x4a0)); | |||
261 | rcu_pwr_gating_cntl &= ~(MPPU_MASK(0xffff << 0) | MPPD_MASK(0xffff << 16)); | |||
262 | rcu_pwr_gating_cntl |= MPPU(113)((113) << 0) | MPPD(50)((50) << 16); | |||
263 | WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a0), (rcu_pwr_gating_cntl)); | |||
264 | ||||
265 | rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3)r600_rcu_rreg(rdev, (0x4a4)); | |||
266 | rcu_pwr_gating_cntl &= ~(DPPU_MASK(0xffff << 0) | DPPD_MASK(0xffff << 16)); | |||
267 | rcu_pwr_gating_cntl |= DPPU(22)((22) << 0) | DPPD(50)((50) << 16); | |||
268 | WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a4), (rcu_pwr_gating_cntl)); | |||
269 | } | |||
270 | ||||
271 | sumo_smu_pg_init(rdev); | |||
272 | } | |||
273 | ||||
274 | static void sumo_gfx_powergating_enable(struct radeon_device *rdev, bool_Bool enable) | |||
275 | { | |||
276 | if (enable) | |||
277 | WREG32_P(CG_PWR_GATING_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &= (~(1 << 0)); tmp_ |= (((1 << 0)) & ~(~(1 << 0))); r100_mm_wreg(rdev, (0x7ac), (tmp_), 0); } while (0); | |||
278 | else { | |||
279 | WREG32_P(CG_PWR_GATING_CNTL, 0, ~DYN_PWR_DOWN_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &= (~(1 << 0)); tmp_ |= ((0) & ~(~(1 << 0))); r100_mm_wreg (rdev, (0x7ac), (tmp_), 0); } while (0); | |||
280 | RREG32(GB_ADDR_CONFIG)r100_mm_rreg(rdev, (0x98f8), 0); | |||
281 | } | |||
282 | } | |||
283 | ||||
284 | static int sumo_enable_clock_power_gating(struct radeon_device *rdev) | |||
285 | { | |||
286 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
287 | ||||
288 | if (pi->enable_gfx_clock_gating) | |||
289 | sumo_gfx_clockgating_initialize(rdev); | |||
290 | if (pi->enable_gfx_power_gating) | |||
291 | sumo_gfx_powergating_initialize(rdev); | |||
292 | if (pi->enable_mg_clock_gating) | |||
293 | sumo_mg_clockgating_enable(rdev, true1); | |||
294 | if (pi->enable_gfx_clock_gating) | |||
295 | sumo_gfx_clockgating_enable(rdev, true1); | |||
296 | if (pi->enable_gfx_power_gating) | |||
297 | sumo_gfx_powergating_enable(rdev, true1); | |||
298 | ||||
299 | return 0; | |||
300 | } | |||
301 | ||||
302 | static void sumo_disable_clock_power_gating(struct radeon_device *rdev) | |||
303 | { | |||
304 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
305 | ||||
306 | if (pi->enable_gfx_clock_gating) | |||
307 | sumo_gfx_clockgating_enable(rdev, false0); | |||
308 | if (pi->enable_gfx_power_gating) | |||
309 | sumo_gfx_powergating_enable(rdev, false0); | |||
310 | if (pi->enable_mg_clock_gating) | |||
311 | sumo_mg_clockgating_enable(rdev, false0); | |||
312 | } | |||
313 | ||||
314 | static void sumo_calculate_bsp(struct radeon_device *rdev, | |||
315 | u32 high_clk) | |||
316 | { | |||
317 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
318 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
319 | ||||
320 | pi->pasi = 65535 * 100 / high_clk; | |||
321 | pi->asi = 65535 * 100 / high_clk; | |||
322 | ||||
323 | r600_calculate_u_and_p(pi->asi, | |||
324 | xclk, 16, &pi->bsp, &pi->bsu); | |||
325 | ||||
326 | r600_calculate_u_and_p(pi->pasi, | |||
327 | xclk, 16, &pi->pbsp, &pi->pbsu); | |||
328 | ||||
329 | pi->dsp = BSP(pi->bsp)((pi->bsp) << 0) | BSU(pi->bsu)((pi->bsu) << 16); | |||
330 | pi->psp = BSP(pi->pbsp)((pi->pbsp) << 0) | BSU(pi->pbsu)((pi->pbsu) << 16); | |||
331 | } | |||
332 | ||||
333 | static void sumo_init_bsp(struct radeon_device *rdev) | |||
334 | { | |||
335 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
336 | ||||
337 | WREG32(CG_BSP_0, pi->psp)r100_mm_wreg(rdev, (0x750), (pi->psp), 0); | |||
338 | } | |||
339 | ||||
340 | ||||
341 | static void sumo_program_bsp(struct radeon_device *rdev, | |||
342 | struct radeon_ps *rps) | |||
343 | { | |||
344 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
345 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
346 | u32 i; | |||
347 | u32 highest_engine_clock = ps->levels[ps->num_levels - 1].sclk; | |||
348 | ||||
349 | if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) | |||
350 | highest_engine_clock = pi->boost_pl.sclk; | |||
351 | ||||
352 | sumo_calculate_bsp(rdev, highest_engine_clock); | |||
353 | ||||
354 | for (i = 0; i < ps->num_levels - 1; i++) | |||
355 | WREG32(CG_BSP_0 + (i * 4), pi->dsp)r100_mm_wreg(rdev, (0x750 + (i * 4)), (pi->dsp), 0); | |||
356 | ||||
357 | WREG32(CG_BSP_0 + (i * 4), pi->psp)r100_mm_wreg(rdev, (0x750 + (i * 4)), (pi->psp), 0); | |||
358 | ||||
359 | if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) | |||
360 | WREG32(CG_BSP_0 + (BOOST_DPM_LEVEL * 4), pi->psp)r100_mm_wreg(rdev, (0x750 + (7 * 4)), (pi->psp), 0); | |||
361 | } | |||
362 | ||||
363 | static void sumo_write_at(struct radeon_device *rdev, | |||
364 | u32 index, u32 value) | |||
365 | { | |||
366 | if (index == 0) | |||
367 | WREG32(CG_AT_0, value)r100_mm_wreg(rdev, (0x728), (value), 0); | |||
368 | else if (index == 1) | |||
369 | WREG32(CG_AT_1, value)r100_mm_wreg(rdev, (0x72c), (value), 0); | |||
370 | else if (index == 2) | |||
371 | WREG32(CG_AT_2, value)r100_mm_wreg(rdev, (0x730), (value), 0); | |||
372 | else if (index == 3) | |||
373 | WREG32(CG_AT_3, value)r100_mm_wreg(rdev, (0x738), (value), 0); | |||
374 | else if (index == 4) | |||
375 | WREG32(CG_AT_4, value)r100_mm_wreg(rdev, (0x73c), (value), 0); | |||
376 | else if (index == 5) | |||
377 | WREG32(CG_AT_5, value)r100_mm_wreg(rdev, (0x740), (value), 0); | |||
378 | else if (index == 6) | |||
379 | WREG32(CG_AT_6, value)r100_mm_wreg(rdev, (0x744), (value), 0); | |||
380 | else if (index == 7) | |||
381 | WREG32(CG_AT_7, value)r100_mm_wreg(rdev, (0x748), (value), 0); | |||
382 | } | |||
383 | ||||
384 | static void sumo_program_at(struct radeon_device *rdev, | |||
385 | struct radeon_ps *rps) | |||
386 | { | |||
387 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
388 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
389 | u32 asi; | |||
390 | u32 i; | |||
391 | u32 m_a; | |||
392 | u32 a_t; | |||
393 | u32 r[SUMO_MAX_HARDWARE_POWERLEVELS5]; | |||
394 | u32 l[SUMO_MAX_HARDWARE_POWERLEVELS5]; | |||
395 | ||||
396 | r[0] = SUMO_R_DFLT070; | |||
397 | r[1] = SUMO_R_DFLT170; | |||
398 | r[2] = SUMO_R_DFLT270; | |||
399 | r[3] = SUMO_R_DFLT370; | |||
400 | r[4] = SUMO_R_DFLT4100; | |||
401 | ||||
402 | l[0] = SUMO_L_DFLT00; | |||
403 | l[1] = SUMO_L_DFLT120; | |||
404 | l[2] = SUMO_L_DFLT220; | |||
405 | l[3] = SUMO_L_DFLT320; | |||
406 | l[4] = SUMO_L_DFLT420; | |||
407 | ||||
408 | for (i = 0; i < ps->num_levels; i++) { | |||
409 | asi = (i == ps->num_levels - 1) ? pi->pasi : pi->asi; | |||
410 | ||||
411 | m_a = asi * ps->levels[i].sclk / 100; | |||
412 | ||||
413 | a_t = CG_R(m_a * r[i] / 100)((m_a * r[i] / 100) << 0) | CG_L(m_a * l[i] / 100)((m_a * l[i] / 100) << 16); | |||
414 | ||||
415 | sumo_write_at(rdev, i, a_t); | |||
416 | } | |||
417 | ||||
418 | if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) { | |||
419 | asi = pi->pasi; | |||
420 | ||||
421 | m_a = asi * pi->boost_pl.sclk / 100; | |||
422 | ||||
423 | a_t = CG_R(m_a * r[ps->num_levels - 1] / 100)((m_a * r[ps->num_levels - 1] / 100) << 0) | | |||
| ||||
424 | CG_L(m_a * l[ps->num_levels - 1] / 100)((m_a * l[ps->num_levels - 1] / 100) << 16); | |||
425 | ||||
426 | sumo_write_at(rdev, BOOST_DPM_LEVEL7, a_t); | |||
427 | } | |||
428 | } | |||
429 | ||||
430 | static void sumo_program_tp(struct radeon_device *rdev) | |||
431 | { | |||
432 | int i; | |||
433 | enum r600_td td = R600_TD_DFLT0; | |||
434 | ||||
435 | for (i = 0; i < SUMO_PM_NUMBER_OF_TC15; i++) { | |||
436 | WREG32_P(CG_FFCT_0 + (i * 4), UTC_0(sumo_utc[i]), ~UTC_0_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x694 + (i * 4)), 0) ; tmp_ &= (~(0x3ff << 0)); tmp_ |= ((((sumo_utc[i]) << 0)) & ~(~(0x3ff << 0))); r100_mm_wreg(rdev , (0x694 + (i * 4)), (tmp_), 0); } while (0); | |||
437 | WREG32_P(CG_FFCT_0 + (i * 4), DTC_0(sumo_dtc[i]), ~DTC_0_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x694 + (i * 4)), 0) ; tmp_ &= (~(0x3ff << 10)); tmp_ |= ((((sumo_dtc[i] ) << 10)) & ~(~(0x3ff << 10))); r100_mm_wreg( rdev, (0x694 + (i * 4)), (tmp_), 0); } while (0); | |||
438 | } | |||
439 | ||||
440 | if (td == R600_TD_AUTO) | |||
441 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 5)); tmp_ |= ((0) & ~(~(1 << 5))); r100_mm_wreg (rdev, (0x644), (tmp_), 0); } while (0); | |||
442 | else | |||
443 | WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 5)); tmp_ |= (((1 << 5)) & ~(~(1 << 5))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0); | |||
444 | ||||
445 | if (td == R600_TD_UP) | |||
446 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 6)); tmp_ |= ((0) & ~(~(1 << 6))); r100_mm_wreg (rdev, (0x644), (tmp_), 0); } while (0); | |||
447 | ||||
448 | if (td == R600_TD_DOWN) | |||
449 | WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 6)); tmp_ |= (((1 << 6)) & ~(~(1 << 6))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0); | |||
450 | } | |||
451 | ||||
452 | void sumo_program_vc(struct radeon_device *rdev, u32 vrc) | |||
453 | { | |||
454 | WREG32(CG_FTV, vrc)r100_mm_wreg(rdev, (0x690), (vrc), 0); | |||
455 | } | |||
456 | ||||
457 | void sumo_clear_vc(struct radeon_device *rdev) | |||
458 | { | |||
459 | WREG32(CG_FTV, 0)r100_mm_wreg(rdev, (0x690), (0), 0); | |||
460 | } | |||
461 | ||||
462 | void sumo_program_sstp(struct radeon_device *rdev) | |||
463 | { | |||
464 | u32 p, u; | |||
465 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
466 | ||||
467 | r600_calculate_u_and_p(SUMO_SST_DFLT8, | |||
468 | xclk, 16, &p, &u); | |||
469 | ||||
470 | WREG32(CG_SSP, SSTU(u) | SST(p))r100_mm_wreg(rdev, (0x6e8), (((u) << 16) | ((p) << 0)), 0); | |||
471 | } | |||
472 | ||||
473 | static void sumo_set_divider_value(struct radeon_device *rdev, | |||
474 | u32 index, u32 divider) | |||
475 | { | |||
476 | u32 reg_index = index / 4; | |||
477 | u32 field_index = index % 4; | |||
478 | ||||
479 | if (field_index == 0) | |||
480 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 0)); tmp_ |= ((((divider ) << 0)) & ~(~(0x7f << 0))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
481 | SCLK_FSTATE_0_DIV(divider), ~SCLK_FSTATE_0_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 0)); tmp_ |= ((((divider ) << 0)) & ~(~(0x7f << 0))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
482 | else if (field_index == 1) | |||
483 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 8)); tmp_ |= ((((divider ) << 8)) & ~(~(0x7f << 8))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
484 | SCLK_FSTATE_1_DIV(divider), ~SCLK_FSTATE_1_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 8)); tmp_ |= ((((divider ) << 8)) & ~(~(0x7f << 8))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
485 | else if (field_index == 2) | |||
486 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 16)); tmp_ |= ((((divider ) << 16)) & ~(~(0x7f << 16))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
487 | SCLK_FSTATE_2_DIV(divider), ~SCLK_FSTATE_2_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 16)); tmp_ |= ((((divider ) << 16)) & ~(~(0x7f << 16))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
488 | else if (field_index == 3) | |||
489 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 24)); tmp_ |= ((((divider ) << 24)) & ~(~(0x7f << 24))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
490 | SCLK_FSTATE_3_DIV(divider), ~SCLK_FSTATE_3_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(0x7f << 24)); tmp_ |= ((((divider ) << 24)) & ~(~(0x7f << 24))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
491 | } | |||
492 | ||||
493 | static void sumo_set_ds_dividers(struct radeon_device *rdev, | |||
494 | u32 index, u32 divider) | |||
495 | { | |||
496 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
497 | ||||
498 | if (pi->enable_sclk_ds) { | |||
499 | u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_6)r100_mm_rreg(rdev, (0x724), 0); | |||
500 | ||||
501 | dpm_ctrl &= ~(0x7 << (index * 3)); | |||
502 | dpm_ctrl |= (divider << (index * 3)); | |||
503 | WREG32(CG_SCLK_DPM_CTRL_6, dpm_ctrl)r100_mm_wreg(rdev, (0x724), (dpm_ctrl), 0); | |||
504 | } | |||
505 | } | |||
506 | ||||
507 | static void sumo_set_ss_dividers(struct radeon_device *rdev, | |||
508 | u32 index, u32 divider) | |||
509 | { | |||
510 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
511 | ||||
512 | if (pi->enable_sclk_ds) { | |||
513 | u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_11)r100_mm_rreg(rdev, (0x830), 0); | |||
514 | ||||
515 | dpm_ctrl &= ~(0x7 << (index * 3)); | |||
516 | dpm_ctrl |= (divider << (index * 3)); | |||
517 | WREG32(CG_SCLK_DPM_CTRL_11, dpm_ctrl)r100_mm_wreg(rdev, (0x830), (dpm_ctrl), 0); | |||
518 | } | |||
519 | } | |||
520 | ||||
521 | static void sumo_set_vid(struct radeon_device *rdev, u32 index, u32 vid) | |||
522 | { | |||
523 | u32 voltage_cntl = RREG32(CG_DPM_VOLTAGE_CNTL)r100_mm_rreg(rdev, (0x788), 0); | |||
524 | ||||
525 | voltage_cntl &= ~(DPM_STATE0_LEVEL_MASK(0x3 << 0) << (index * 2)); | |||
526 | voltage_cntl |= (vid << (DPM_STATE0_LEVEL_SHIFT0 + index * 2)); | |||
527 | WREG32(CG_DPM_VOLTAGE_CNTL, voltage_cntl)r100_mm_wreg(rdev, (0x788), (voltage_cntl), 0); | |||
528 | } | |||
529 | ||||
530 | static void sumo_set_allos_gnb_slow(struct radeon_device *rdev, u32 index, u32 gnb_slow) | |||
531 | { | |||
532 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
533 | u32 temp = gnb_slow; | |||
534 | u32 cg_sclk_dpm_ctrl_3; | |||
535 | ||||
536 | if (pi->driver_nbps_policy_disable) | |||
537 | temp = 1; | |||
538 | ||||
539 | cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3)r100_mm_rreg(rdev, (0x6e0), 0); | |||
540 | cg_sclk_dpm_ctrl_3 &= ~(GNB_SLOW_FSTATE_0_MASK(1 << 23) << index); | |||
541 | cg_sclk_dpm_ctrl_3 |= (temp << (GNB_SLOW_FSTATE_0_SHIFT23 + index)); | |||
542 | ||||
543 | WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3)r100_mm_wreg(rdev, (0x6e0), (cg_sclk_dpm_ctrl_3), 0); | |||
544 | } | |||
545 | ||||
546 | static void sumo_program_power_level(struct radeon_device *rdev, | |||
547 | struct sumo_pl *pl, u32 index) | |||
548 | { | |||
549 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
550 | int ret; | |||
551 | struct atom_clock_dividers dividers; | |||
552 | u32 ds_en = RREG32(DEEP_SLEEP_CNTL)r100_mm_rreg(rdev, (0x818), 0) & ENABLE_DS(1 << 31); | |||
553 | ||||
554 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM2, | |||
555 | pl->sclk, false0, ÷rs); | |||
556 | if (ret) | |||
557 | return; | |||
558 | ||||
559 | sumo_set_divider_value(rdev, index, dividers.post_div); | |||
560 | ||||
561 | sumo_set_vid(rdev, index, pl->vddc_index); | |||
562 | ||||
563 | if (pl->ss_divider_index == 0 || pl->ds_divider_index == 0) { | |||
564 | if (ds_en) | |||
565 | WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x818), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((0) & ~(~(1 << 31))); r100_mm_wreg(rdev, (0x818), (tmp_), 0); } while (0); | |||
566 | } else { | |||
567 | sumo_set_ss_dividers(rdev, index, pl->ss_divider_index); | |||
568 | sumo_set_ds_dividers(rdev, index, pl->ds_divider_index); | |||
569 | ||||
570 | if (!ds_en) | |||
571 | WREG32_P(DEEP_SLEEP_CNTL, ENABLE_DS, ~ENABLE_DS)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x818), 0); tmp_ &= (~(1 << 31)); tmp_ |= (((1 << 31)) & ~(~(1 << 31))); r100_mm_wreg(rdev, (0x818), (tmp_), 0); } while (0); | |||
572 | } | |||
573 | ||||
574 | sumo_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow); | |||
575 | ||||
576 | if (pi->enable_boost) | |||
577 | sumo_set_tdp_limit(rdev, index, pl->sclk_dpm_tdp_limit); | |||
578 | } | |||
579 | ||||
580 | static void sumo_power_level_enable(struct radeon_device *rdev, u32 index, bool_Bool enable) | |||
581 | { | |||
582 | u32 reg_index = index / 4; | |||
583 | u32 field_index = index % 4; | |||
584 | ||||
585 | if (field_index == 0) | |||
586 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 7)); tmp_ |= ((enable ? ( 1 << 7) : 0) & ~(~(1 << 7))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
587 | enable ? SCLK_FSTATE_0_VLD : 0, ~SCLK_FSTATE_0_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 7)); tmp_ |= ((enable ? ( 1 << 7) : 0) & ~(~(1 << 7))); r100_mm_wreg(rdev , (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
588 | else if (field_index == 1) | |||
589 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 15)); tmp_ |= ((enable ? ( 1 << 15) : 0) & ~(~(1 << 15))); r100_mm_wreg( rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
590 | enable ? SCLK_FSTATE_1_VLD : 0, ~SCLK_FSTATE_1_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 15)); tmp_ |= ((enable ? ( 1 << 15) : 0) & ~(~(1 << 15))); r100_mm_wreg( rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
591 | else if (field_index == 2) | |||
592 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 23)); tmp_ |= ((enable ? ( 1 << 23) : 0) & ~(~(1 << 23))); r100_mm_wreg( rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
593 | enable ? SCLK_FSTATE_2_VLD : 0, ~SCLK_FSTATE_2_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 23)); tmp_ |= ((enable ? ( 1 << 23) : 0) & ~(~(1 << 23))); r100_mm_wreg( rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
594 | else if (field_index == 3) | |||
595 | WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((enable ? ( 1 << 31) : 0) & ~(~(1 << 31))); r100_mm_wreg( rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0) | |||
596 | enable ? SCLK_FSTATE_3_VLD : 0, ~SCLK_FSTATE_3_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index * 4)), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((enable ? ( 1 << 31) : 0) & ~(~(1 << 31))); r100_mm_wreg( rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0); | |||
597 | } | |||
598 | ||||
599 | static bool_Bool sumo_dpm_enabled(struct radeon_device *rdev) | |||
600 | { | |||
601 | if (RREG32(CG_SCLK_DPM_CTRL_3)r100_mm_rreg(rdev, (0x6e0), 0) & DPM_SCLK_ENABLE(1 << 18)) | |||
602 | return true1; | |||
603 | else | |||
604 | return false0; | |||
605 | } | |||
606 | ||||
607 | static void sumo_start_dpm(struct radeon_device *rdev) | |||
608 | { | |||
609 | WREG32_P(CG_SCLK_DPM_CTRL_3, DPM_SCLK_ENABLE, ~DPM_SCLK_ENABLE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 18)); tmp_ |= (((1 << 18)) & ~(~(1 << 18))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
610 | } | |||
611 | ||||
612 | static void sumo_stop_dpm(struct radeon_device *rdev) | |||
613 | { | |||
614 | WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~DPM_SCLK_ENABLE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 18)); tmp_ |= ((0) & ~(~(1 << 18))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
615 | } | |||
616 | ||||
617 | static void sumo_set_forced_mode(struct radeon_device *rdev, bool_Bool enable) | |||
618 | { | |||
619 | if (enable) | |||
620 | WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE_EN, ~FORCE_SCLK_STATE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 3)); tmp_ |= (((1 << 3)) & ~(~(1 << 3))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
621 | else | |||
622 | WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_SCLK_STATE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 3)); tmp_ |= ((0) & ~(~(1 << 3))); r100_mm_wreg (rdev, (0x6e0), (tmp_), 0); } while (0); | |||
623 | } | |||
624 | ||||
625 | static void sumo_set_forced_mode_enabled(struct radeon_device *rdev) | |||
626 | { | |||
627 | int i; | |||
628 | ||||
629 | sumo_set_forced_mode(rdev, true1); | |||
630 | for (i = 0; i < rdev->usec_timeout; i++) { | |||
631 | if (RREG32(CG_SCLK_STATUS)r100_mm_rreg(rdev, (0x604), 0) & SCLK_OVERCLK_DETECT(1 << 2)) | |||
632 | break; | |||
633 | udelay(1); | |||
634 | } | |||
635 | } | |||
636 | ||||
637 | static void sumo_wait_for_level_0(struct radeon_device *rdev) | |||
638 | { | |||
639 | int i; | |||
640 | ||||
641 | for (i = 0; i < rdev->usec_timeout; i++) { | |||
642 | if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_SCLK_INDEX_MASK(0x7 << 9)) == 0) | |||
643 | break; | |||
644 | udelay(1); | |||
645 | } | |||
646 | for (i = 0; i < rdev->usec_timeout; i++) { | |||
647 | if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_INDEX_MASK(0x7 << 15)) == 0) | |||
648 | break; | |||
649 | udelay(1); | |||
650 | } | |||
651 | } | |||
652 | ||||
653 | static void sumo_set_forced_mode_disabled(struct radeon_device *rdev) | |||
654 | { | |||
655 | sumo_set_forced_mode(rdev, false0); | |||
656 | } | |||
657 | ||||
658 | static void sumo_enable_power_level_0(struct radeon_device *rdev) | |||
659 | { | |||
660 | sumo_power_level_enable(rdev, 0, true1); | |||
661 | } | |||
662 | ||||
663 | static void sumo_patch_boost_state(struct radeon_device *rdev, | |||
664 | struct radeon_ps *rps) | |||
665 | { | |||
666 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
667 | struct sumo_ps *new_ps = sumo_get_ps(rps); | |||
668 | ||||
669 | if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) { | |||
670 | pi->boost_pl = new_ps->levels[new_ps->num_levels - 1]; | |||
671 | pi->boost_pl.sclk = pi->sys_info.boost_sclk; | |||
672 | pi->boost_pl.vddc_index = pi->sys_info.boost_vid_2bit; | |||
673 | pi->boost_pl.sclk_dpm_tdp_limit = pi->sys_info.sclk_dpm_tdp_limit_boost; | |||
674 | } | |||
675 | } | |||
676 | ||||
677 | static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev, | |||
678 | struct radeon_ps *new_rps, | |||
679 | struct radeon_ps *old_rps) | |||
680 | { | |||
681 | struct sumo_ps *new_ps = sumo_get_ps(new_rps); | |||
682 | struct sumo_ps *old_ps = sumo_get_ps(old_rps); | |||
683 | u32 nbps1_old = 0; | |||
684 | u32 nbps1_new = 0; | |||
685 | ||||
686 | if (old_ps != NULL((void *)0)) | |||
687 | nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0)) ? 1 : 0; | |||
688 | ||||
689 | nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0)) ? 1 : 0; | |||
690 | ||||
691 | if (nbps1_old == 1 && nbps1_new == 0) | |||
692 | sumo_smu_notify_alt_vddnb_change(rdev, 0, 0); | |||
693 | } | |||
694 | ||||
695 | static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev, | |||
696 | struct radeon_ps *new_rps, | |||
697 | struct radeon_ps *old_rps) | |||
698 | { | |||
699 | struct sumo_ps *new_ps = sumo_get_ps(new_rps); | |||
700 | struct sumo_ps *old_ps = sumo_get_ps(old_rps); | |||
701 | u32 nbps1_old = 0; | |||
702 | u32 nbps1_new = 0; | |||
703 | ||||
704 | if (old_ps != NULL((void *)0)) | |||
705 | nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0))? 1 : 0; | |||
706 | ||||
707 | nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0))? 1 : 0; | |||
708 | ||||
709 | if (nbps1_old == 0 && nbps1_new == 1) | |||
710 | sumo_smu_notify_alt_vddnb_change(rdev, 1, 1); | |||
711 | } | |||
712 | ||||
713 | static void sumo_enable_boost(struct radeon_device *rdev, | |||
714 | struct radeon_ps *rps, | |||
715 | bool_Bool enable) | |||
716 | { | |||
717 | struct sumo_ps *new_ps = sumo_get_ps(rps); | |||
718 | ||||
719 | if (enable) { | |||
720 | if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) | |||
721 | sumo_boost_state_enable(rdev, true1); | |||
722 | } else | |||
723 | sumo_boost_state_enable(rdev, false0); | |||
724 | } | |||
725 | ||||
726 | static void sumo_set_forced_level(struct radeon_device *rdev, u32 index) | |||
727 | { | |||
728 | WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE(index), ~FORCE_SCLK_STATE_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(0x7 << 0)); tmp_ |= ((((index) << 0)) & ~ (~(0x7 << 0))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
729 | } | |||
730 | ||||
731 | static void sumo_set_forced_level_0(struct radeon_device *rdev) | |||
732 | { | |||
733 | sumo_set_forced_level(rdev, 0); | |||
734 | } | |||
735 | ||||
736 | static void sumo_program_wl(struct radeon_device *rdev, | |||
737 | struct radeon_ps *rps) | |||
738 | { | |||
739 | struct sumo_ps *new_ps = sumo_get_ps(rps); | |||
740 | u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4)r100_mm_rreg(rdev, (0x71c), 0); | |||
741 | ||||
742 | dpm_ctrl4 &= 0xFFFFFF00; | |||
743 | dpm_ctrl4 |= (1 << (new_ps->num_levels - 1)); | |||
744 | ||||
745 | if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) | |||
746 | dpm_ctrl4 |= (1 << BOOST_DPM_LEVEL7); | |||
747 | ||||
748 | WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4)r100_mm_wreg(rdev, (0x71c), (dpm_ctrl4), 0); | |||
749 | } | |||
750 | ||||
751 | static void sumo_program_power_levels_0_to_n(struct radeon_device *rdev, | |||
752 | struct radeon_ps *new_rps, | |||
753 | struct radeon_ps *old_rps) | |||
754 | { | |||
755 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
756 | struct sumo_ps *new_ps = sumo_get_ps(new_rps); | |||
757 | struct sumo_ps *old_ps = sumo_get_ps(old_rps); | |||
758 | u32 i; | |||
759 | u32 n_current_state_levels = (old_ps == NULL((void *)0)) ? 1 : old_ps->num_levels; | |||
760 | ||||
761 | for (i = 0; i < new_ps->num_levels; i++) { | |||
762 | sumo_program_power_level(rdev, &new_ps->levels[i], i); | |||
763 | sumo_power_level_enable(rdev, i, true1); | |||
764 | } | |||
765 | ||||
766 | for (i = new_ps->num_levels; i < n_current_state_levels; i++) | |||
767 | sumo_power_level_enable(rdev, i, false0); | |||
768 | ||||
769 | if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) | |||
770 | sumo_program_power_level(rdev, &pi->boost_pl, BOOST_DPM_LEVEL7); | |||
771 | } | |||
772 | ||||
773 | static void sumo_enable_acpi_pm(struct radeon_device *rdev) | |||
774 | { | |||
775 | WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x63c), 0); tmp_ &= (~(1 << 1)); tmp_ |= (((1 << 1)) & ~(~(1 << 1))); r100_mm_wreg(rdev, (0x63c), (tmp_), 0); } while (0); | |||
776 | } | |||
777 | ||||
778 | static void sumo_program_power_level_enter_state(struct radeon_device *rdev) | |||
779 | { | |||
780 | WREG32_P(CG_SCLK_DPM_CTRL_5, SCLK_FSTATE_BOOTUP(0), ~SCLK_FSTATE_BOOTUP_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x720), 0); tmp_ &= (~(0x7 << 0)); tmp_ |= ((((0) << 0)) & ~(~(0x7 << 0))); r100_mm_wreg(rdev, (0x720), (tmp_), 0); } while (0); | |||
781 | } | |||
782 | ||||
783 | static void sumo_program_acpi_power_level(struct radeon_device *rdev) | |||
784 | { | |||
785 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
786 | struct atom_clock_dividers dividers; | |||
787 | int ret; | |||
788 | ||||
789 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM2, | |||
790 | pi->acpi_pl.sclk, | |||
791 | false0, ÷rs); | |||
792 | if (ret) | |||
793 | return; | |||
794 | ||||
795 | WREG32_P(CG_ACPI_CNTL, SCLK_ACPI_DIV(dividers.post_div), ~SCLK_ACPI_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x70c), 0); tmp_ &= (~(0x7f << 0)); tmp_ |= ((((dividers.post_div) << 0)) & ~(~(0x7f << 0))); r100_mm_wreg(rdev, (0x70c) , (tmp_), 0); } while (0); | |||
796 | WREG32_P(CG_ACPI_VOLTAGE_CNTL, 0, ~ACPI_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x780), 0); tmp_ &= (~(1 << 8)); tmp_ |= ((0) & ~(~(1 << 8))); r100_mm_wreg (rdev, (0x780), (tmp_), 0); } while (0); | |||
797 | } | |||
798 | ||||
799 | static void sumo_program_bootup_state(struct radeon_device *rdev) | |||
800 | { | |||
801 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
802 | u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4)r100_mm_rreg(rdev, (0x71c), 0); | |||
803 | u32 i; | |||
804 | ||||
805 | sumo_program_power_level(rdev, &pi->boot_pl, 0); | |||
806 | ||||
807 | dpm_ctrl4 &= 0xFFFFFF00; | |||
808 | WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4)r100_mm_wreg(rdev, (0x71c), (dpm_ctrl4), 0); | |||
809 | ||||
810 | for (i = 1; i < 8; i++) | |||
811 | sumo_power_level_enable(rdev, i, false0); | |||
812 | } | |||
813 | ||||
814 | static void sumo_setup_uvd_clocks(struct radeon_device *rdev, | |||
815 | struct radeon_ps *new_rps, | |||
816 | struct radeon_ps *old_rps) | |||
817 | { | |||
818 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
819 | ||||
820 | if (pi->enable_gfx_power_gating) { | |||
821 | sumo_gfx_powergating_enable(rdev, false0); | |||
822 | } | |||
823 | ||||
824 | radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk)(rdev)->asic->pm.set_uvd_clocks((rdev), (new_rps->vclk ), (new_rps->dclk)); | |||
825 | ||||
826 | if (pi->enable_gfx_power_gating) { | |||
827 | if (!pi->disable_gfx_power_gating_in_uvd || | |||
828 | !r600_is_uvd_state(new_rps->class, new_rps->class2)) | |||
829 | sumo_gfx_powergating_enable(rdev, true1); | |||
830 | } | |||
831 | } | |||
832 | ||||
833 | static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev, | |||
834 | struct radeon_ps *new_rps, | |||
835 | struct radeon_ps *old_rps) | |||
836 | { | |||
837 | struct sumo_ps *new_ps = sumo_get_ps(new_rps); | |||
838 | struct sumo_ps *current_ps = sumo_get_ps(old_rps); | |||
839 | ||||
840 | if ((new_rps->vclk == old_rps->vclk) && | |||
841 | (new_rps->dclk == old_rps->dclk)) | |||
842 | return; | |||
843 | ||||
844 | if (new_ps->levels[new_ps->num_levels - 1].sclk >= | |||
845 | current_ps->levels[current_ps->num_levels - 1].sclk) | |||
846 | return; | |||
847 | ||||
848 | sumo_setup_uvd_clocks(rdev, new_rps, old_rps); | |||
849 | } | |||
850 | ||||
851 | static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, | |||
852 | struct radeon_ps *new_rps, | |||
853 | struct radeon_ps *old_rps) | |||
854 | { | |||
855 | struct sumo_ps *new_ps = sumo_get_ps(new_rps); | |||
856 | struct sumo_ps *current_ps = sumo_get_ps(old_rps); | |||
857 | ||||
858 | if ((new_rps->vclk == old_rps->vclk) && | |||
859 | (new_rps->dclk == old_rps->dclk)) | |||
860 | return; | |||
861 | ||||
862 | if (new_ps->levels[new_ps->num_levels - 1].sclk < | |||
863 | current_ps->levels[current_ps->num_levels - 1].sclk) | |||
864 | return; | |||
865 | ||||
866 | sumo_setup_uvd_clocks(rdev, new_rps, old_rps); | |||
867 | } | |||
868 | ||||
869 | void sumo_take_smu_control(struct radeon_device *rdev, bool_Bool enable) | |||
870 | { | |||
871 | /* This bit selects who handles display phy powergating. | |||
872 | * Clear the bit to let atom handle it. | |||
873 | * Set it to let the driver handle it. | |||
874 | * For now we just let atom handle it. | |||
875 | */ | |||
876 | #if 0 | |||
877 | u32 v = RREG32(DOUT_SCRATCH3)r100_mm_rreg(rdev, (0x611c), 0); | |||
878 | ||||
879 | if (enable) | |||
880 | v |= 0x4; | |||
881 | else | |||
882 | v &= 0xFFFFFFFB; | |||
883 | ||||
884 | WREG32(DOUT_SCRATCH3, v)r100_mm_wreg(rdev, (0x611c), (v), 0); | |||
885 | #endif | |||
886 | } | |||
887 | ||||
888 | static void sumo_enable_sclk_ds(struct radeon_device *rdev, bool_Bool enable) | |||
889 | { | |||
890 | if (enable) { | |||
891 | u32 deep_sleep_cntl = RREG32(DEEP_SLEEP_CNTL)r100_mm_rreg(rdev, (0x818), 0); | |||
892 | u32 deep_sleep_cntl2 = RREG32(DEEP_SLEEP_CNTL2)r100_mm_rreg(rdev, (0x81c), 0); | |||
893 | u32 t = 1; | |||
894 | ||||
895 | deep_sleep_cntl &= ~R_DIS(1 << 3); | |||
896 | deep_sleep_cntl &= ~HS_MASK(0xfff << 4); | |||
897 | deep_sleep_cntl |= HS(t > 4095 ? 4095 : t)((t > 4095 ? 4095 : t) << 4); | |||
898 | ||||
899 | deep_sleep_cntl2 |= LB_UFP_EN(1 << 0); | |||
900 | deep_sleep_cntl2 &= INOUT_C_MASK(0xff << 4); | |||
901 | deep_sleep_cntl2 |= INOUT_C(0xf)((0xf) << 4); | |||
902 | ||||
903 | WREG32(DEEP_SLEEP_CNTL2, deep_sleep_cntl2)r100_mm_wreg(rdev, (0x81c), (deep_sleep_cntl2), 0); | |||
904 | WREG32(DEEP_SLEEP_CNTL, deep_sleep_cntl)r100_mm_wreg(rdev, (0x818), (deep_sleep_cntl), 0); | |||
905 | } else | |||
906 | WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x818), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((0) & ~(~(1 << 31))); r100_mm_wreg(rdev, (0x818), (tmp_), 0); } while (0); | |||
907 | } | |||
908 | ||||
909 | static void sumo_program_bootup_at(struct radeon_device *rdev) | |||
910 | { | |||
911 | WREG32_P(CG_AT_0, CG_R(0xffff), ~CG_R_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x728), 0); tmp_ &= (~(0xffff << 0)); tmp_ |= ((((0xffff) << 0)) & ~(~(0xffff << 0))); r100_mm_wreg(rdev, (0x728), (tmp_) , 0); } while (0); | |||
912 | WREG32_P(CG_AT_0, CG_L(0), ~CG_L_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x728), 0); tmp_ &= (~(0xffff << 16)); tmp_ |= ((((0) << 16)) & ~ (~(0xffff << 16))); r100_mm_wreg(rdev, (0x728), (tmp_), 0); } while (0); | |||
913 | } | |||
914 | ||||
915 | static void sumo_reset_am(struct radeon_device *rdev) | |||
916 | { | |||
917 | WREG32_P(SCLK_PWRMGT_CNTL, FIR_RESET, ~FIR_RESET)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 4)); tmp_ |= (((1 << 4)) & ~(~(1 << 4))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0); | |||
918 | } | |||
919 | ||||
920 | static void sumo_start_am(struct radeon_device *rdev) | |||
921 | { | |||
922 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_RESET)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &= (~(1 << 4)); tmp_ |= ((0) & ~(~(1 << 4))); r100_mm_wreg (rdev, (0x644), (tmp_), 0); } while (0); | |||
923 | } | |||
924 | ||||
925 | static void sumo_program_ttp(struct radeon_device *rdev) | |||
926 | { | |||
927 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
928 | u32 p, u; | |||
929 | u32 cg_sclk_dpm_ctrl_5 = RREG32(CG_SCLK_DPM_CTRL_5)r100_mm_rreg(rdev, (0x720), 0); | |||
930 | ||||
931 | r600_calculate_u_and_p(1000, | |||
932 | xclk, 16, &p, &u); | |||
933 | ||||
934 | cg_sclk_dpm_ctrl_5 &= ~(TT_TP_MASK(0xffff << 3) | TT_TU_MASK(0xff << 19)); | |||
935 | cg_sclk_dpm_ctrl_5 |= TT_TP(p)((p) << 3) | TT_TU(u)((u) << 19); | |||
936 | ||||
937 | WREG32(CG_SCLK_DPM_CTRL_5, cg_sclk_dpm_ctrl_5)r100_mm_wreg(rdev, (0x720), (cg_sclk_dpm_ctrl_5), 0); | |||
938 | } | |||
939 | ||||
940 | static void sumo_program_ttt(struct radeon_device *rdev) | |||
941 | { | |||
942 | u32 cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3)r100_mm_rreg(rdev, (0x6e0), 0); | |||
943 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
944 | ||||
945 | cg_sclk_dpm_ctrl_3 &= ~(GNB_TT_MASK(0xff << 8) | GNB_THERMTHRO_MASK(1 << 16)); | |||
946 | cg_sclk_dpm_ctrl_3 |= GNB_TT(pi->thermal_auto_throttling + 49)((pi->thermal_auto_throttling + 49) << 8); | |||
947 | ||||
948 | WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3)r100_mm_wreg(rdev, (0x6e0), (cg_sclk_dpm_ctrl_3), 0); | |||
949 | } | |||
950 | ||||
951 | ||||
952 | static void sumo_enable_voltage_scaling(struct radeon_device *rdev, bool_Bool enable) | |||
953 | { | |||
954 | if (enable) { | |||
955 | WREG32_P(CG_DPM_VOLTAGE_CNTL, DPM_VOLTAGE_EN, ~DPM_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x788), 0); tmp_ &= (~(1 << 16)); tmp_ |= (((1 << 16)) & ~(~(1 << 16))); r100_mm_wreg(rdev, (0x788), (tmp_), 0); } while (0); | |||
956 | WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~CG_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &= (~(1 << 3)); tmp_ |= ((0) & ~(~(1 << 3))); r100_mm_wreg (rdev, (0x770), (tmp_), 0); } while (0); | |||
957 | } else { | |||
958 | WREG32_P(CG_CG_VOLTAGE_CNTL, CG_VOLTAGE_EN, ~CG_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &= (~(1 << 3)); tmp_ |= (((1 << 3)) & ~(~(1 << 3))); r100_mm_wreg(rdev, (0x770), (tmp_), 0); } while (0); | |||
959 | WREG32_P(CG_DPM_VOLTAGE_CNTL, 0, ~DPM_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x788), 0); tmp_ &= (~(1 << 16)); tmp_ |= ((0) & ~(~(1 << 16))); r100_mm_wreg(rdev, (0x788), (tmp_), 0); } while (0); | |||
960 | } | |||
961 | } | |||
962 | ||||
963 | static void sumo_override_cnb_thermal_events(struct radeon_device *rdev) | |||
964 | { | |||
965 | WREG32_P(CG_SCLK_DPM_CTRL_3, CNB_THERMTHRO_MASK_SCLK,do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 17)); tmp_ |= (((1 << 17)) & ~(~(1 << 17))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0) | |||
966 | ~CNB_THERMTHRO_MASK_SCLK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 17)); tmp_ |= (((1 << 17)) & ~(~(1 << 17))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
967 | } | |||
968 | ||||
969 | static void sumo_program_dc_hto(struct radeon_device *rdev) | |||
970 | { | |||
971 | u32 cg_sclk_dpm_ctrl_4 = RREG32(CG_SCLK_DPM_CTRL_4)r100_mm_rreg(rdev, (0x71c), 0); | |||
972 | u32 p, u; | |||
973 | u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev)); | |||
974 | ||||
975 | r600_calculate_u_and_p(100000, | |||
976 | xclk, 14, &p, &u); | |||
977 | ||||
978 | cg_sclk_dpm_ctrl_4 &= ~(DC_HDC_MASK(0x3fff << 14) | DC_HU_MASK(0xf << 28)); | |||
979 | cg_sclk_dpm_ctrl_4 |= DC_HDC(p)((p) << 14) | DC_HU(u)((u) << 28); | |||
980 | ||||
981 | WREG32(CG_SCLK_DPM_CTRL_4, cg_sclk_dpm_ctrl_4)r100_mm_wreg(rdev, (0x71c), (cg_sclk_dpm_ctrl_4), 0); | |||
982 | } | |||
983 | ||||
984 | static void sumo_force_nbp_state(struct radeon_device *rdev, | |||
985 | struct radeon_ps *rps) | |||
986 | { | |||
987 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
988 | struct sumo_ps *new_ps = sumo_get_ps(rps); | |||
989 | ||||
990 | if (!pi->driver_nbps_policy_disable) { | |||
991 | if (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0)) | |||
992 | WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_NB_PSTATE_1, ~FORCE_NB_PSTATE_1)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 31)); tmp_ |= (((1 << 31)) & ~(~(1 << 31))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
993 | else | |||
994 | WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_NB_PSTATE_1)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((0) & ~(~(1 << 31))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0); | |||
995 | } | |||
996 | } | |||
997 | ||||
998 | u32 sumo_get_sleep_divider_from_id(u32 id) | |||
999 | { | |||
1000 | return 1 << id; | |||
1001 | } | |||
1002 | ||||
1003 | u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, | |||
1004 | u32 sclk, | |||
1005 | u32 min_sclk_in_sr) | |||
1006 | { | |||
1007 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1008 | u32 i; | |||
1009 | u32 temp; | |||
1010 | u32 min = (min_sclk_in_sr > SUMO_MINIMUM_ENGINE_CLOCK800) ? | |||
1011 | min_sclk_in_sr : SUMO_MINIMUM_ENGINE_CLOCK800; | |||
1012 | ||||
1013 | if (sclk < min) | |||
1014 | return 0; | |||
1015 | ||||
1016 | if (!pi->enable_sclk_ds) | |||
1017 | return 0; | |||
1018 | ||||
1019 | for (i = SUMO_MAX_DEEPSLEEP_DIVIDER_ID5; ; i--) { | |||
1020 | temp = sclk / sumo_get_sleep_divider_from_id(i); | |||
1021 | ||||
1022 | if (temp >= min || i == 0) | |||
1023 | break; | |||
1024 | } | |||
1025 | return i; | |||
1026 | } | |||
1027 | ||||
1028 | static u32 sumo_get_valid_engine_clock(struct radeon_device *rdev, | |||
1029 | u32 lower_limit) | |||
1030 | { | |||
1031 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1032 | u32 i; | |||
1033 | ||||
1034 | for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) { | |||
1035 | if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit) | |||
1036 | return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency; | |||
1037 | } | |||
1038 | ||||
1039 | return pi->sys_info.sclk_voltage_mapping_table.entries[pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1].sclk_frequency; | |||
1040 | } | |||
1041 | ||||
1042 | static void sumo_patch_thermal_state(struct radeon_device *rdev, | |||
1043 | struct sumo_ps *ps, | |||
1044 | struct sumo_ps *current_ps) | |||
1045 | { | |||
1046 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1047 | u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ | |||
1048 | u32 current_vddc; | |||
1049 | u32 current_sclk; | |||
1050 | u32 current_index = 0; | |||
1051 | ||||
1052 | if (current_ps) { | |||
1053 | current_vddc = current_ps->levels[current_index].vddc_index; | |||
1054 | current_sclk = current_ps->levels[current_index].sclk; | |||
1055 | } else { | |||
1056 | current_vddc = pi->boot_pl.vddc_index; | |||
1057 | current_sclk = pi->boot_pl.sclk; | |||
1058 | } | |||
1059 | ||||
1060 | ps->levels[0].vddc_index = current_vddc; | |||
1061 | ||||
1062 | if (ps->levels[0].sclk > current_sclk) | |||
1063 | ps->levels[0].sclk = current_sclk; | |||
1064 | ||||
1065 | ps->levels[0].ss_divider_index = | |||
1066 | sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr); | |||
1067 | ||||
1068 | ps->levels[0].ds_divider_index = | |||
1069 | sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, SUMO_MINIMUM_ENGINE_CLOCK800); | |||
1070 | ||||
1071 | if (ps->levels[0].ds_divider_index > ps->levels[0].ss_divider_index + 1) | |||
1072 | ps->levels[0].ds_divider_index = ps->levels[0].ss_divider_index + 1; | |||
1073 | ||||
1074 | if (ps->levels[0].ss_divider_index == ps->levels[0].ds_divider_index) { | |||
1075 | if (ps->levels[0].ss_divider_index > 1) | |||
1076 | ps->levels[0].ss_divider_index = ps->levels[0].ss_divider_index - 1; | |||
1077 | } | |||
1078 | ||||
1079 | if (ps->levels[0].ss_divider_index == 0) | |||
1080 | ps->levels[0].ds_divider_index = 0; | |||
1081 | ||||
1082 | if (ps->levels[0].ds_divider_index == 0) | |||
1083 | ps->levels[0].ss_divider_index = 0; | |||
1084 | } | |||
1085 | ||||
1086 | static void sumo_apply_state_adjust_rules(struct radeon_device *rdev, | |||
1087 | struct radeon_ps *new_rps, | |||
1088 | struct radeon_ps *old_rps) | |||
1089 | { | |||
1090 | struct sumo_ps *ps = sumo_get_ps(new_rps); | |||
1091 | struct sumo_ps *current_ps = sumo_get_ps(old_rps); | |||
1092 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1093 | u32 min_voltage = 0; /* ??? */ | |||
1094 | u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */ | |||
1095 | u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ | |||
1096 | u32 i; | |||
1097 | ||||
1098 | if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL0x0010) | |||
1099 | return sumo_patch_thermal_state(rdev, ps, current_ps); | |||
1100 | ||||
1101 | if (pi->enable_boost) { | |||
1102 | if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE5) | |||
1103 | ps->flags |= SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1); | |||
1104 | } | |||
1105 | ||||
1106 | if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY1) || | |||
1107 | (new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE0x8000) || | |||
1108 | (new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE0x4000)) | |||
1109 | ps->flags |= SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0); | |||
1110 | ||||
1111 | for (i = 0; i < ps->num_levels; i++) { | |||
1112 | if (ps->levels[i].vddc_index < min_voltage) | |||
1113 | ps->levels[i].vddc_index = min_voltage; | |||
1114 | ||||
1115 | if (ps->levels[i].sclk < min_sclk) | |||
1116 | ps->levels[i].sclk = | |||
1117 | sumo_get_valid_engine_clock(rdev, min_sclk); | |||
1118 | ||||
1119 | ps->levels[i].ss_divider_index = | |||
1120 | sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); | |||
1121 | ||||
1122 | ps->levels[i].ds_divider_index = | |||
1123 | sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, SUMO_MINIMUM_ENGINE_CLOCK800); | |||
1124 | ||||
1125 | if (ps->levels[i].ds_divider_index > ps->levels[i].ss_divider_index + 1) | |||
1126 | ps->levels[i].ds_divider_index = ps->levels[i].ss_divider_index + 1; | |||
1127 | ||||
1128 | if (ps->levels[i].ss_divider_index == ps->levels[i].ds_divider_index) { | |||
1129 | if (ps->levels[i].ss_divider_index > 1) | |||
1130 | ps->levels[i].ss_divider_index = ps->levels[i].ss_divider_index - 1; | |||
1131 | } | |||
1132 | ||||
1133 | if (ps->levels[i].ss_divider_index == 0) | |||
1134 | ps->levels[i].ds_divider_index = 0; | |||
1135 | ||||
1136 | if (ps->levels[i].ds_divider_index == 0) | |||
1137 | ps->levels[i].ss_divider_index = 0; | |||
1138 | ||||
1139 | if (ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0)) | |||
1140 | ps->levels[i].allow_gnb_slow = 1; | |||
1141 | else if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE0x0400) || | |||
1142 | (new_rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC0x0004)) | |||
1143 | ps->levels[i].allow_gnb_slow = 0; | |||
1144 | else if (i == ps->num_levels - 1) | |||
1145 | ps->levels[i].allow_gnb_slow = 0; | |||
1146 | else | |||
1147 | ps->levels[i].allow_gnb_slow = 1; | |||
1148 | } | |||
1149 | } | |||
1150 | ||||
1151 | static void sumo_cleanup_asic(struct radeon_device *rdev) | |||
1152 | { | |||
1153 | sumo_take_smu_control(rdev, false0); | |||
1154 | } | |||
1155 | ||||
1156 | static int sumo_set_thermal_temperature_range(struct radeon_device *rdev, | |||
1157 | int min_temp, int max_temp) | |||
1158 | { | |||
1159 | int low_temp = 0 * 1000; | |||
1160 | int high_temp = 255 * 1000; | |||
1161 | ||||
1162 | if (low_temp < min_temp) | |||
1163 | low_temp = min_temp; | |||
1164 | if (high_temp > max_temp) | |||
1165 | high_temp = max_temp; | |||
1166 | if (high_temp < low_temp) { | |||
1167 | DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp)__drm_err("invalid thermal range: %d - %d\n", low_temp, high_temp ); | |||
1168 | return -EINVAL22; | |||
1169 | } | |||
1170 | ||||
1171 | WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x734), 0); tmp_ &= (~0x0000FF00); tmp_ |= ((((49 + (high_temp / 1000)) << 8)) & ~(~0x0000FF00)); r100_mm_wreg(rdev, (0x734), (tmp_ ), 0); } while (0); | |||
1172 | WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x734), 0); tmp_ &= (~0x00FF0000); tmp_ |= ((((49 + (low_temp / 1000)) << 16 )) & ~(~0x00FF0000)); r100_mm_wreg(rdev, (0x734), (tmp_), 0); } while (0); | |||
1173 | ||||
1174 | rdev->pm.dpm.thermal.min_temp = low_temp; | |||
1175 | rdev->pm.dpm.thermal.max_temp = high_temp; | |||
1176 | ||||
1177 | return 0; | |||
1178 | } | |||
1179 | ||||
1180 | static void sumo_update_current_ps(struct radeon_device *rdev, | |||
1181 | struct radeon_ps *rps) | |||
1182 | { | |||
1183 | struct sumo_ps *new_ps = sumo_get_ps(rps); | |||
1184 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1185 | ||||
1186 | pi->current_rps = *rps; | |||
1187 | pi->current_ps = *new_ps; | |||
1188 | pi->current_rps.ps_priv = &pi->current_ps; | |||
1189 | } | |||
1190 | ||||
1191 | static void sumo_update_requested_ps(struct radeon_device *rdev, | |||
1192 | struct radeon_ps *rps) | |||
1193 | { | |||
1194 | struct sumo_ps *new_ps = sumo_get_ps(rps); | |||
1195 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1196 | ||||
1197 | pi->requested_rps = *rps; | |||
1198 | pi->requested_ps = *new_ps; | |||
1199 | pi->requested_rps.ps_priv = &pi->requested_ps; | |||
1200 | } | |||
1201 | ||||
1202 | int sumo_dpm_enable(struct radeon_device *rdev) | |||
1203 | { | |||
1204 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1205 | ||||
1206 | if (sumo_dpm_enabled(rdev)) | |||
1207 | return -EINVAL22; | |||
1208 | ||||
1209 | sumo_program_bootup_state(rdev); | |||
1210 | sumo_init_bsp(rdev); | |||
1211 | sumo_reset_am(rdev); | |||
1212 | sumo_program_tp(rdev); | |||
1213 | sumo_program_bootup_at(rdev); | |||
1214 | sumo_start_am(rdev); | |||
1215 | if (pi->enable_auto_thermal_throttling) { | |||
1216 | sumo_program_ttp(rdev); | |||
1217 | sumo_program_ttt(rdev); | |||
1218 | } | |||
1219 | sumo_program_dc_hto(rdev); | |||
1220 | sumo_program_power_level_enter_state(rdev); | |||
1221 | sumo_enable_voltage_scaling(rdev, true1); | |||
1222 | sumo_program_sstp(rdev); | |||
1223 | sumo_program_vc(rdev, SUMO_VRC_DFLT0x30033); | |||
1224 | sumo_override_cnb_thermal_events(rdev); | |||
1225 | sumo_start_dpm(rdev); | |||
1226 | sumo_wait_for_level_0(rdev); | |||
1227 | if (pi->enable_sclk_ds) | |||
1228 | sumo_enable_sclk_ds(rdev, true1); | |||
1229 | if (pi->enable_boost) | |||
1230 | sumo_enable_boost_timer(rdev); | |||
1231 | ||||
1232 | sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps); | |||
1233 | ||||
1234 | return 0; | |||
1235 | } | |||
1236 | ||||
1237 | int sumo_dpm_late_enable(struct radeon_device *rdev) | |||
1238 | { | |||
1239 | int ret; | |||
1240 | ||||
1241 | ret = sumo_enable_clock_power_gating(rdev); | |||
1242 | if (ret) | |||
1243 | return ret; | |||
1244 | ||||
1245 | if (rdev->irq.installed && | |||
1246 | r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { | |||
1247 | ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN(90 * 1000), R600_TEMP_RANGE_MAX(120 * 1000)); | |||
1248 | if (ret) | |||
1249 | return ret; | |||
1250 | rdev->irq.dpm_thermal = true1; | |||
1251 | radeon_irq_set(rdev)(rdev)->asic->irq.set((rdev)); | |||
1252 | } | |||
1253 | ||||
1254 | return 0; | |||
1255 | } | |||
1256 | ||||
1257 | void sumo_dpm_disable(struct radeon_device *rdev) | |||
1258 | { | |||
1259 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1260 | ||||
1261 | if (!sumo_dpm_enabled(rdev)) | |||
1262 | return; | |||
1263 | sumo_disable_clock_power_gating(rdev); | |||
1264 | if (pi->enable_sclk_ds) | |||
1265 | sumo_enable_sclk_ds(rdev, false0); | |||
1266 | sumo_clear_vc(rdev); | |||
1267 | sumo_wait_for_level_0(rdev); | |||
1268 | sumo_stop_dpm(rdev); | |||
1269 | sumo_enable_voltage_scaling(rdev, false0); | |||
1270 | ||||
1271 | if (rdev->irq.installed && | |||
1272 | r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { | |||
1273 | rdev->irq.dpm_thermal = false0; | |||
1274 | radeon_irq_set(rdev)(rdev)->asic->irq.set((rdev)); | |||
1275 | } | |||
1276 | ||||
1277 | sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps); | |||
1278 | } | |||
1279 | ||||
1280 | int sumo_dpm_pre_set_power_state(struct radeon_device *rdev) | |||
1281 | { | |||
1282 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1283 | struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; | |||
1284 | struct radeon_ps *new_ps = &requested_ps; | |||
1285 | ||||
1286 | sumo_update_requested_ps(rdev, new_ps); | |||
1287 | ||||
1288 | if (pi->enable_dynamic_patch_ps) | |||
1289 | sumo_apply_state_adjust_rules(rdev, | |||
1290 | &pi->requested_rps, | |||
1291 | &pi->current_rps); | |||
1292 | ||||
1293 | return 0; | |||
1294 | } | |||
1295 | ||||
1296 | int sumo_dpm_set_power_state(struct radeon_device *rdev) | |||
1297 | { | |||
1298 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1299 | struct radeon_ps *new_ps = &pi->requested_rps; | |||
1300 | struct radeon_ps *old_ps = &pi->current_rps; | |||
1301 | ||||
1302 | if (pi->enable_dpm) | |||
| ||||
1303 | sumo_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); | |||
1304 | if (pi->enable_boost) { | |||
1305 | sumo_enable_boost(rdev, new_ps, false0); | |||
1306 | sumo_patch_boost_state(rdev, new_ps); | |||
1307 | } | |||
1308 | if (pi->enable_dpm
| |||
1309 | sumo_pre_notify_alt_vddnb_change(rdev, new_ps, old_ps); | |||
1310 | sumo_enable_power_level_0(rdev); | |||
1311 | sumo_set_forced_level_0(rdev); | |||
1312 | sumo_set_forced_mode_enabled(rdev); | |||
1313 | sumo_wait_for_level_0(rdev); | |||
1314 | sumo_program_power_levels_0_to_n(rdev, new_ps, old_ps); | |||
1315 | sumo_program_wl(rdev, new_ps); | |||
1316 | sumo_program_bsp(rdev, new_ps); | |||
1317 | sumo_program_at(rdev, new_ps); | |||
1318 | sumo_force_nbp_state(rdev, new_ps); | |||
1319 | sumo_set_forced_mode_disabled(rdev); | |||
1320 | sumo_set_forced_mode_enabled(rdev); | |||
1321 | sumo_set_forced_mode_disabled(rdev); | |||
1322 | sumo_post_notify_alt_vddnb_change(rdev, new_ps, old_ps); | |||
1323 | } | |||
1324 | if (pi->enable_boost) | |||
1325 | sumo_enable_boost(rdev, new_ps, true1); | |||
1326 | if (pi->enable_dpm) | |||
1327 | sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); | |||
1328 | ||||
1329 | return 0; | |||
1330 | } | |||
1331 | ||||
1332 | void sumo_dpm_post_set_power_state(struct radeon_device *rdev) | |||
1333 | { | |||
1334 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1335 | struct radeon_ps *new_ps = &pi->requested_rps; | |||
1336 | ||||
1337 | sumo_update_current_ps(rdev, new_ps); | |||
1338 | } | |||
1339 | ||||
1340 | #if 0 | |||
1341 | void sumo_dpm_reset_asic(struct radeon_device *rdev) | |||
1342 | { | |||
1343 | sumo_program_bootup_state(rdev); | |||
1344 | sumo_enable_power_level_0(rdev); | |||
1345 | sumo_set_forced_level_0(rdev); | |||
1346 | sumo_set_forced_mode_enabled(rdev); | |||
1347 | sumo_wait_for_level_0(rdev); | |||
1348 | sumo_set_forced_mode_disabled(rdev); | |||
1349 | sumo_set_forced_mode_enabled(rdev); | |||
1350 | sumo_set_forced_mode_disabled(rdev); | |||
1351 | } | |||
1352 | #endif | |||
1353 | ||||
1354 | void sumo_dpm_setup_asic(struct radeon_device *rdev) | |||
1355 | { | |||
1356 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1357 | ||||
1358 | sumo_initialize_m3_arb(rdev); | |||
1359 | pi->fw_version = sumo_get_running_fw_version(rdev); | |||
1360 | DRM_INFO("Found smc ucode version: 0x%08x\n", pi->fw_version)printk("\0016" "[" "drm" "] " "Found smc ucode version: 0x%08x\n" , pi->fw_version); | |||
1361 | sumo_program_acpi_power_level(rdev); | |||
1362 | sumo_enable_acpi_pm(rdev); | |||
1363 | sumo_take_smu_control(rdev, true1); | |||
1364 | } | |||
1365 | ||||
1366 | void sumo_dpm_display_configuration_changed(struct radeon_device *rdev) | |||
1367 | { | |||
1368 | ||||
1369 | } | |||
1370 | ||||
1371 | union power_info { | |||
1372 | struct _ATOM_POWERPLAY_INFO info; | |||
1373 | struct _ATOM_POWERPLAY_INFO_V2 info_2; | |||
1374 | struct _ATOM_POWERPLAY_INFO_V3 info_3; | |||
1375 | struct _ATOM_PPLIB_POWERPLAYTABLE pplib; | |||
1376 | struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; | |||
1377 | struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; | |||
1378 | }; | |||
1379 | ||||
1380 | union pplib_clock_info { | |||
1381 | struct _ATOM_PPLIB_R600_CLOCK_INFO r600; | |||
1382 | struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; | |||
1383 | struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; | |||
1384 | struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; | |||
1385 | }; | |||
1386 | ||||
1387 | union pplib_power_state { | |||
1388 | struct _ATOM_PPLIB_STATE v1; | |||
1389 | struct _ATOM_PPLIB_STATE_V2 v2; | |||
1390 | }; | |||
1391 | ||||
1392 | static void sumo_patch_boot_state(struct radeon_device *rdev, | |||
1393 | struct sumo_ps *ps) | |||
1394 | { | |||
1395 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1396 | ||||
1397 | ps->num_levels = 1; | |||
1398 | ps->flags = 0; | |||
1399 | ps->levels[0] = pi->boot_pl; | |||
1400 | } | |||
1401 | ||||
1402 | static void sumo_parse_pplib_non_clock_info(struct radeon_device *rdev, | |||
1403 | struct radeon_ps *rps, | |||
1404 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, | |||
1405 | u8 table_rev) | |||
1406 | { | |||
1407 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
1408 | ||||
1409 | rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings)((__uint32_t)(non_clock_info->ulCapsAndSettings)); | |||
1410 | rps->class = le16_to_cpu(non_clock_info->usClassification)((__uint16_t)(non_clock_info->usClassification)); | |||
1411 | rps->class2 = le16_to_cpu(non_clock_info->usClassification2)((__uint16_t)(non_clock_info->usClassification2)); | |||
1412 | ||||
1413 | if (ATOM_PPLIB_NONCLOCKINFO_VER112 < table_rev) { | |||
1414 | rps->vclk = le32_to_cpu(non_clock_info->ulVCLK)((__uint32_t)(non_clock_info->ulVCLK)); | |||
1415 | rps->dclk = le32_to_cpu(non_clock_info->ulDCLK)((__uint32_t)(non_clock_info->ulDCLK)); | |||
1416 | } else { | |||
1417 | rps->vclk = 0; | |||
1418 | rps->dclk = 0; | |||
1419 | } | |||
1420 | ||||
1421 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT0x0008) { | |||
1422 | rdev->pm.dpm.boot_ps = rps; | |||
1423 | sumo_patch_boot_state(rdev, ps); | |||
1424 | } | |||
1425 | if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE0x0400) | |||
1426 | rdev->pm.dpm.uvd_ps = rps; | |||
1427 | } | |||
1428 | ||||
1429 | static void sumo_parse_pplib_clock_info(struct radeon_device *rdev, | |||
1430 | struct radeon_ps *rps, int index, | |||
1431 | union pplib_clock_info *clock_info) | |||
1432 | { | |||
1433 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1434 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
1435 | struct sumo_pl *pl = &ps->levels[index]; | |||
1436 | u32 sclk; | |||
1437 | ||||
1438 | sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow)((__uint16_t)(clock_info->sumo.usEngineClockLow)); | |||
1439 | sclk |= clock_info->sumo.ucEngineClockHigh << 16; | |||
1440 | pl->sclk = sclk; | |||
1441 | pl->vddc_index = clock_info->sumo.vddcIndex; | |||
1442 | pl->sclk_dpm_tdp_limit = clock_info->sumo.tdpLimit; | |||
1443 | ||||
1444 | ps->num_levels = index + 1; | |||
1445 | ||||
1446 | if (pi->enable_sclk_ds) { | |||
1447 | pl->ds_divider_index = 5; | |||
1448 | pl->ss_divider_index = 4; | |||
1449 | } | |||
1450 | } | |||
1451 | ||||
1452 | static int sumo_parse_power_table(struct radeon_device *rdev) | |||
1453 | { | |||
1454 | struct radeon_mode_info *mode_info = &rdev->mode_info; | |||
1455 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; | |||
1456 | union pplib_power_state *power_state; | |||
1457 | int i, j, k, non_clock_array_index, clock_array_index; | |||
1458 | union pplib_clock_info *clock_info; | |||
1459 | struct _StateArray *state_array; | |||
1460 | struct _ClockInfoArray *clock_info_array; | |||
1461 | struct _NonClockInfoArray *non_clock_info_array; | |||
1462 | union power_info *power_info; | |||
1463 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo)(((char*)(&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->PowerPlayInfo )-(char*)0)/sizeof(USHORT)); | |||
1464 | u16 data_offset; | |||
1465 | u8 frev, crev; | |||
1466 | u8 *power_state_offset; | |||
1467 | struct sumo_ps *ps; | |||
1468 | ||||
1469 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL((void *)0), | |||
1470 | &frev, &crev, &data_offset)) | |||
1471 | return -EINVAL22; | |||
1472 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | |||
1473 | ||||
1474 | state_array = (struct _StateArray *) | |||
1475 | (mode_info->atom_context->bios + data_offset + | |||
1476 | le16_to_cpu(power_info->pplib.usStateArrayOffset)((__uint16_t)(power_info->pplib.usStateArrayOffset))); | |||
1477 | clock_info_array = (struct _ClockInfoArray *) | |||
1478 | (mode_info->atom_context->bios + data_offset + | |||
1479 | le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)((__uint16_t)(power_info->pplib.usClockInfoArrayOffset))); | |||
1480 | non_clock_info_array = (struct _NonClockInfoArray *) | |||
1481 | (mode_info->atom_context->bios + data_offset + | |||
1482 | le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)((__uint16_t)(power_info->pplib.usNonClockInfoArrayOffset) )); | |||
1483 | ||||
1484 | rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, | |||
1485 | sizeof(struct radeon_ps), | |||
1486 | GFP_KERNEL(0x0001 | 0x0004)); | |||
1487 | if (!rdev->pm.dpm.ps) | |||
1488 | return -ENOMEM12; | |||
1489 | power_state_offset = (u8 *)state_array->states; | |||
1490 | for (i = 0; i < state_array->ucNumEntries; i++) { | |||
1491 | u8 *idx; | |||
1492 | power_state = (union pplib_power_state *)power_state_offset; | |||
1493 | non_clock_array_index = power_state->v2.nonClockInfoIndex; | |||
1494 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | |||
1495 | &non_clock_info_array->nonClockInfo[non_clock_array_index]; | |||
1496 | if (!rdev->pm.power_state[i].clock_info) | |||
1497 | return -EINVAL22; | |||
1498 | ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL(0x0001 | 0x0004)); | |||
1499 | if (ps == NULL((void *)0)) { | |||
1500 | kfree(rdev->pm.dpm.ps); | |||
1501 | return -ENOMEM12; | |||
1502 | } | |||
1503 | rdev->pm.dpm.ps[i].ps_priv = ps; | |||
1504 | k = 0; | |||
1505 | idx = (u8 *)&power_state->v2.clockInfoIndex[0]; | |||
1506 | for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { | |||
1507 | clock_array_index = idx[j]; | |||
1508 | if (k >= SUMO_MAX_HARDWARE_POWERLEVELS5) | |||
1509 | break; | |||
1510 | ||||
1511 | clock_info = (union pplib_clock_info *) | |||
1512 | ((u8 *)&clock_info_array->clockInfo[0] + | |||
1513 | (clock_array_index * clock_info_array->ucEntrySize)); | |||
1514 | sumo_parse_pplib_clock_info(rdev, | |||
1515 | &rdev->pm.dpm.ps[i], k, | |||
1516 | clock_info); | |||
1517 | k++; | |||
1518 | } | |||
1519 | sumo_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], | |||
1520 | non_clock_info, | |||
1521 | non_clock_info_array->ucEntrySize); | |||
1522 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; | |||
1523 | } | |||
1524 | rdev->pm.dpm.num_ps = state_array->ucNumEntries; | |||
1525 | return 0; | |||
1526 | } | |||
1527 | ||||
1528 | u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, | |||
1529 | struct sumo_vid_mapping_table *vid_mapping_table, | |||
1530 | u32 vid_2bit) | |||
1531 | { | |||
1532 | u32 i; | |||
1533 | ||||
1534 | for (i = 0; i < vid_mapping_table->num_entries; i++) { | |||
1535 | if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) | |||
1536 | return vid_mapping_table->entries[i].vid_7bit; | |||
1537 | } | |||
1538 | ||||
1539 | return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; | |||
1540 | } | |||
1541 | ||||
1542 | #if 0 | |||
1543 | u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, | |||
1544 | struct sumo_vid_mapping_table *vid_mapping_table, | |||
1545 | u32 vid_7bit) | |||
1546 | { | |||
1547 | u32 i; | |||
1548 | ||||
1549 | for (i = 0; i < vid_mapping_table->num_entries; i++) { | |||
1550 | if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) | |||
1551 | return vid_mapping_table->entries[i].vid_2bit; | |||
1552 | } | |||
1553 | ||||
1554 | return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; | |||
1555 | } | |||
1556 | #endif | |||
1557 | ||||
1558 | static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, | |||
1559 | u32 vid_2bit) | |||
1560 | { | |||
1561 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1562 | u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit); | |||
1563 | ||||
1564 | if (vid_7bit > 0x7C) | |||
1565 | return 0; | |||
1566 | ||||
1567 | return (15500 - vid_7bit * 125 + 5) / 10; | |||
1568 | } | |||
1569 | ||||
1570 | static void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev, | |||
1571 | struct sumo_disp_clock_voltage_mapping_table *disp_clk_voltage_mapping_table, | |||
1572 | ATOM_CLK_VOLT_CAPABILITY *table) | |||
1573 | { | |||
1574 | u32 i; | |||
1575 | ||||
1576 | for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES4; i++) { | |||
1577 | if (table[i].ulMaximumSupportedCLK == 0) | |||
1578 | break; | |||
1579 | ||||
1580 | disp_clk_voltage_mapping_table->display_clock_frequency[i] = | |||
1581 | table[i].ulMaximumSupportedCLK; | |||
1582 | } | |||
1583 | ||||
1584 | disp_clk_voltage_mapping_table->num_max_voltage_levels = i; | |||
1585 | ||||
1586 | if (disp_clk_voltage_mapping_table->num_max_voltage_levels == 0) { | |||
1587 | disp_clk_voltage_mapping_table->display_clock_frequency[0] = 80000; | |||
1588 | disp_clk_voltage_mapping_table->num_max_voltage_levels = 1; | |||
1589 | } | |||
1590 | } | |||
1591 | ||||
1592 | void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev, | |||
1593 | struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table, | |||
1594 | ATOM_AVAILABLE_SCLK_LIST *table) | |||
1595 | { | |||
1596 | u32 i; | |||
1597 | u32 n = 0; | |||
1598 | u32 prev_sclk = 0; | |||
1599 | ||||
1600 | for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS5; i++) { | |||
1601 | if (table[i].ulSupportedSCLK > prev_sclk) { | |||
1602 | sclk_voltage_mapping_table->entries[n].sclk_frequency = | |||
1603 | table[i].ulSupportedSCLK; | |||
1604 | sclk_voltage_mapping_table->entries[n].vid_2bit = | |||
1605 | table[i].usVoltageIndex; | |||
1606 | prev_sclk = table[i].ulSupportedSCLK; | |||
1607 | n++; | |||
1608 | } | |||
1609 | } | |||
1610 | ||||
1611 | sclk_voltage_mapping_table->num_max_dpm_entries = n; | |||
1612 | } | |||
1613 | ||||
1614 | void sumo_construct_vid_mapping_table(struct radeon_device *rdev, | |||
1615 | struct sumo_vid_mapping_table *vid_mapping_table, | |||
1616 | ATOM_AVAILABLE_SCLK_LIST *table) | |||
1617 | { | |||
1618 | u32 i, j; | |||
1619 | ||||
1620 | for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS5; i++) { | |||
1621 | if (table[i].ulSupportedSCLK != 0) { | |||
1622 | vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit = | |||
1623 | table[i].usVoltageID; | |||
1624 | vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit = | |||
1625 | table[i].usVoltageIndex; | |||
1626 | } | |||
1627 | } | |||
1628 | ||||
1629 | for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES4; i++) { | |||
1630 | if (vid_mapping_table->entries[i].vid_7bit == 0) { | |||
1631 | for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES4; j++) { | |||
1632 | if (vid_mapping_table->entries[j].vid_7bit != 0) { | |||
1633 | vid_mapping_table->entries[i] = | |||
1634 | vid_mapping_table->entries[j]; | |||
1635 | vid_mapping_table->entries[j].vid_7bit = 0; | |||
1636 | break; | |||
1637 | } | |||
1638 | } | |||
1639 | ||||
1640 | if (j == SUMO_MAX_NUMBER_VOLTAGES4) | |||
1641 | break; | |||
1642 | } | |||
1643 | } | |||
1644 | ||||
1645 | vid_mapping_table->num_entries = i; | |||
1646 | } | |||
1647 | ||||
1648 | union igp_info { | |||
1649 | struct _ATOM_INTEGRATED_SYSTEM_INFO info; | |||
1650 | struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; | |||
1651 | struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; | |||
1652 | struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; | |||
1653 | }; | |||
1654 | ||||
1655 | static int sumo_parse_sys_info_table(struct radeon_device *rdev) | |||
1656 | { | |||
1657 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1658 | struct radeon_mode_info *mode_info = &rdev->mode_info; | |||
1659 | int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo)(((char*)(&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->IntegratedSystemInfo )-(char*)0)/sizeof(USHORT)); | |||
1660 | union igp_info *igp_info; | |||
1661 | u8 frev, crev; | |||
1662 | u16 data_offset; | |||
1663 | int i; | |||
1664 | ||||
1665 | if (atom_parse_data_header(mode_info->atom_context, index, NULL((void *)0), | |||
1666 | &frev, &crev, &data_offset)) { | |||
1667 | igp_info = (union igp_info *)(mode_info->atom_context->bios + | |||
1668 | data_offset); | |||
1669 | ||||
1670 | if (crev != 6) { | |||
1671 | DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev)__drm_err("Unsupported IGP table: %d %d\n", frev, crev); | |||
1672 | return -EINVAL22; | |||
1673 | } | |||
1674 | pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_6.ulBootUpEngineClock)((__uint32_t)(igp_info->info_6.ulBootUpEngineClock)); | |||
1675 | pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_6.ulMinEngineClock)((__uint32_t)(igp_info->info_6.ulMinEngineClock)); | |||
1676 | pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_6.ulBootUpUMAClock)((__uint32_t)(igp_info->info_6.ulBootUpUMAClock)); | |||
1677 | pi->sys_info.bootup_nb_voltage_index = | |||
1678 | le16_to_cpu(igp_info->info_6.usBootUpNBVoltage)((__uint16_t)(igp_info->info_6.usBootUpNBVoltage)); | |||
1679 | if (igp_info->info_6.ucHtcTmpLmt == 0) | |||
1680 | pi->sys_info.htc_tmp_lmt = 203; | |||
1681 | else | |||
1682 | pi->sys_info.htc_tmp_lmt = igp_info->info_6.ucHtcTmpLmt; | |||
1683 | if (igp_info->info_6.ucHtcHystLmt == 0) | |||
1684 | pi->sys_info.htc_hyst_lmt = 5; | |||
1685 | else | |||
1686 | pi->sys_info.htc_hyst_lmt = igp_info->info_6.ucHtcHystLmt; | |||
1687 | if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { | |||
1688 | DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n")__drm_err("The htcTmpLmt should be larger than htcHystLmt.\n" ); | |||
1689 | } | |||
1690 | for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS10; i++) { | |||
1691 | pi->sys_info.csr_m3_arb_cntl_default[i] = | |||
1692 | le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i])((__uint32_t)(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i ])); | |||
1693 | pi->sys_info.csr_m3_arb_cntl_uvd[i] = | |||
1694 | le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i])((__uint32_t)(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i])); | |||
1695 | pi->sys_info.csr_m3_arb_cntl_fs3d[i] = | |||
1696 | le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i])((__uint32_t)(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i])); | |||
1697 | } | |||
1698 | pi->sys_info.sclk_dpm_boost_margin = | |||
1699 | le32_to_cpu(igp_info->info_6.SclkDpmBoostMargin)((__uint32_t)(igp_info->info_6.SclkDpmBoostMargin)); | |||
1700 | pi->sys_info.sclk_dpm_throttle_margin = | |||
1701 | le32_to_cpu(igp_info->info_6.SclkDpmThrottleMargin)((__uint32_t)(igp_info->info_6.SclkDpmThrottleMargin)); | |||
1702 | pi->sys_info.sclk_dpm_tdp_limit_pg = | |||
1703 | le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitPG)((__uint16_t)(igp_info->info_6.SclkDpmTdpLimitPG)); | |||
1704 | pi->sys_info.gnb_tdp_limit = le16_to_cpu(igp_info->info_6.GnbTdpLimit)((__uint16_t)(igp_info->info_6.GnbTdpLimit)); | |||
1705 | pi->sys_info.sclk_dpm_tdp_limit_boost = | |||
1706 | le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitBoost)((__uint16_t)(igp_info->info_6.SclkDpmTdpLimitBoost)); | |||
1707 | pi->sys_info.boost_sclk = le32_to_cpu(igp_info->info_6.ulBoostEngineCLock)((__uint32_t)(igp_info->info_6.ulBoostEngineCLock)); | |||
1708 | pi->sys_info.boost_vid_2bit = igp_info->info_6.ulBoostVid_2bit; | |||
1709 | if (igp_info->info_6.EnableBoost) | |||
1710 | pi->sys_info.enable_boost = true1; | |||
1711 | else | |||
1712 | pi->sys_info.enable_boost = false0; | |||
1713 | sumo_construct_display_voltage_mapping_table(rdev, | |||
1714 | &pi->sys_info.disp_clk_voltage_mapping_table, | |||
1715 | igp_info->info_6.sDISPCLK_Voltage); | |||
1716 | sumo_construct_sclk_voltage_mapping_table(rdev, | |||
1717 | &pi->sys_info.sclk_voltage_mapping_table, | |||
1718 | igp_info->info_6.sAvail_SCLK); | |||
1719 | sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table, | |||
1720 | igp_info->info_6.sAvail_SCLK); | |||
1721 | ||||
1722 | } | |||
1723 | return 0; | |||
1724 | } | |||
1725 | ||||
1726 | static void sumo_construct_boot_and_acpi_state(struct radeon_device *rdev) | |||
1727 | { | |||
1728 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1729 | ||||
1730 | pi->boot_pl.sclk = pi->sys_info.bootup_sclk; | |||
1731 | pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; | |||
1732 | pi->boot_pl.ds_divider_index = 0; | |||
1733 | pi->boot_pl.ss_divider_index = 0; | |||
1734 | pi->boot_pl.allow_gnb_slow = 1; | |||
1735 | pi->acpi_pl = pi->boot_pl; | |||
1736 | pi->current_ps.num_levels = 1; | |||
1737 | pi->current_ps.levels[0] = pi->boot_pl; | |||
1738 | } | |||
1739 | ||||
1740 | int sumo_dpm_init(struct radeon_device *rdev) | |||
1741 | { | |||
1742 | struct sumo_power_info *pi; | |||
1743 | u32 hw_rev = (RREG32(HW_REV)r100_mm_rreg(rdev, (0x5564), 0) & ATI_REV_ID_MASK(0xf << 28)) >> ATI_REV_ID_SHIFT28; | |||
1744 | int ret; | |||
1745 | ||||
1746 | pi = kzalloc(sizeof(struct sumo_power_info), GFP_KERNEL(0x0001 | 0x0004)); | |||
1747 | if (pi == NULL((void *)0)) | |||
1748 | return -ENOMEM12; | |||
1749 | rdev->pm.dpm.priv = pi; | |||
1750 | ||||
1751 | pi->driver_nbps_policy_disable = false0; | |||
1752 | if ((rdev->family == CHIP_PALM) && (hw_rev < 3)) | |||
1753 | pi->disable_gfx_power_gating_in_uvd = true1; | |||
1754 | else | |||
1755 | pi->disable_gfx_power_gating_in_uvd = false0; | |||
1756 | pi->enable_alt_vddnb = true1; | |||
1757 | pi->enable_sclk_ds = true1; | |||
1758 | pi->enable_dynamic_m3_arbiter = false0; | |||
1759 | pi->enable_dynamic_patch_ps = true1; | |||
1760 | /* Some PALM chips don't seem to properly ungate gfx when UVD is in use; | |||
1761 | * for now just disable gfx PG. | |||
1762 | */ | |||
1763 | if (rdev->family == CHIP_PALM) | |||
1764 | pi->enable_gfx_power_gating = false0; | |||
1765 | else | |||
1766 | pi->enable_gfx_power_gating = true1; | |||
1767 | pi->enable_gfx_clock_gating = true1; | |||
1768 | pi->enable_mg_clock_gating = true1; | |||
1769 | pi->enable_auto_thermal_throttling = true1; | |||
1770 | ||||
1771 | ret = sumo_parse_sys_info_table(rdev); | |||
1772 | if (ret) | |||
1773 | return ret; | |||
1774 | ||||
1775 | sumo_construct_boot_and_acpi_state(rdev); | |||
1776 | ||||
1777 | ret = r600_get_platform_caps(rdev); | |||
1778 | if (ret) | |||
1779 | return ret; | |||
1780 | ||||
1781 | ret = sumo_parse_power_table(rdev); | |||
1782 | if (ret) | |||
1783 | return ret; | |||
1784 | ||||
1785 | pi->pasi = CYPRESS_HASI_DFLT400000; | |||
1786 | pi->asi = RV770_ASI_DFLT1000; | |||
1787 | pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt; | |||
1788 | pi->enable_boost = pi->sys_info.enable_boost; | |||
1789 | pi->enable_dpm = true1; | |||
1790 | ||||
1791 | return 0; | |||
1792 | } | |||
1793 | ||||
1794 | void sumo_dpm_print_power_state(struct radeon_device *rdev, | |||
1795 | struct radeon_ps *rps) | |||
1796 | { | |||
1797 | int i; | |||
1798 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
1799 | ||||
1800 | r600_dpm_print_class_info(rps->class, rps->class2); | |||
1801 | r600_dpm_print_cap_info(rps->caps); | |||
1802 | printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); | |||
1803 | for (i = 0; i < ps->num_levels; i++) { | |||
1804 | struct sumo_pl *pl = &ps->levels[i]; | |||
1805 | printk("\t\tpower level %d sclk: %u vddc: %u\n", | |||
1806 | i, pl->sclk, | |||
1807 | sumo_convert_voltage_index_to_value(rdev, pl->vddc_index)); | |||
1808 | } | |||
1809 | r600_dpm_print_ps_status(rdev, rps); | |||
1810 | } | |||
1811 | ||||
1812 | void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, | |||
1813 | struct seq_file *m) | |||
1814 | { | |||
1815 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1816 | struct radeon_ps *rps = &pi->current_rps; | |||
1817 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
1818 | struct sumo_pl *pl; | |||
1819 | u32 current_index = | |||
1820 | (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_INDEX_MASK(0x7 << 15)) >> | |||
1821 | CURR_INDEX_SHIFT15; | |||
1822 | ||||
1823 | if (current_index == BOOST_DPM_LEVEL7) { | |||
1824 | pl = &pi->boost_pl; | |||
1825 | seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); | |||
1826 | seq_printf(m, "power level %d sclk: %u vddc: %u\n", | |||
1827 | current_index, pl->sclk, | |||
1828 | sumo_convert_voltage_index_to_value(rdev, pl->vddc_index)); | |||
1829 | } else if (current_index >= ps->num_levels) { | |||
1830 | seq_printf(m, "invalid dpm profile %d\n", current_index); | |||
1831 | } else { | |||
1832 | pl = &ps->levels[current_index]; | |||
1833 | seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); | |||
1834 | seq_printf(m, "power level %d sclk: %u vddc: %u\n", | |||
1835 | current_index, pl->sclk, | |||
1836 | sumo_convert_voltage_index_to_value(rdev, pl->vddc_index)); | |||
1837 | } | |||
1838 | } | |||
1839 | ||||
1840 | u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev) | |||
1841 | { | |||
1842 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1843 | struct radeon_ps *rps = &pi->current_rps; | |||
1844 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
1845 | struct sumo_pl *pl; | |||
1846 | u32 current_index = | |||
1847 | (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_INDEX_MASK(0x7 << 15)) >> | |||
1848 | CURR_INDEX_SHIFT15; | |||
1849 | ||||
1850 | if (current_index == BOOST_DPM_LEVEL7) { | |||
1851 | pl = &pi->boost_pl; | |||
1852 | return pl->sclk; | |||
1853 | } else if (current_index >= ps->num_levels) { | |||
1854 | return 0; | |||
1855 | } else { | |||
1856 | pl = &ps->levels[current_index]; | |||
1857 | return pl->sclk; | |||
1858 | } | |||
1859 | } | |||
1860 | ||||
1861 | u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev) | |||
1862 | { | |||
1863 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1864 | ||||
1865 | return pi->sys_info.bootup_uma_clk; | |||
1866 | } | |||
1867 | ||||
1868 | void sumo_dpm_fini(struct radeon_device *rdev) | |||
1869 | { | |||
1870 | int i; | |||
1871 | ||||
1872 | sumo_cleanup_asic(rdev); /* ??? */ | |||
1873 | ||||
1874 | for (i = 0; i < rdev->pm.dpm.num_ps; i++) { | |||
1875 | kfree(rdev->pm.dpm.ps[i].ps_priv); | |||
1876 | } | |||
1877 | kfree(rdev->pm.dpm.ps); | |||
1878 | kfree(rdev->pm.dpm.priv); | |||
1879 | } | |||
1880 | ||||
1881 | u32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool_Bool low) | |||
1882 | { | |||
1883 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1884 | struct sumo_ps *requested_state = sumo_get_ps(&pi->requested_rps); | |||
1885 | ||||
1886 | if (low) | |||
1887 | return requested_state->levels[0].sclk; | |||
1888 | else | |||
1889 | return requested_state->levels[requested_state->num_levels - 1].sclk; | |||
1890 | } | |||
1891 | ||||
1892 | u32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool_Bool low) | |||
1893 | { | |||
1894 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1895 | ||||
1896 | return pi->sys_info.bootup_uma_clk; | |||
1897 | } | |||
1898 | ||||
1899 | int sumo_dpm_force_performance_level(struct radeon_device *rdev, | |||
1900 | enum radeon_dpm_forced_level level) | |||
1901 | { | |||
1902 | struct sumo_power_info *pi = sumo_get_pi(rdev); | |||
1903 | struct radeon_ps *rps = &pi->current_rps; | |||
1904 | struct sumo_ps *ps = sumo_get_ps(rps); | |||
1905 | int i; | |||
1906 | ||||
1907 | if (ps->num_levels <= 1) | |||
1908 | return 0; | |||
1909 | ||||
1910 | if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { | |||
1911 | if (pi->enable_boost) | |||
1912 | sumo_enable_boost(rdev, rps, false0); | |||
1913 | sumo_power_level_enable(rdev, ps->num_levels - 1, true1); | |||
1914 | sumo_set_forced_level(rdev, ps->num_levels - 1); | |||
1915 | sumo_set_forced_mode_enabled(rdev); | |||
1916 | for (i = 0; i < ps->num_levels - 1; i++) { | |||
1917 | sumo_power_level_enable(rdev, i, false0); | |||
1918 | } | |||
1919 | sumo_set_forced_mode(rdev, false0); | |||
1920 | sumo_set_forced_mode_enabled(rdev); | |||
1921 | sumo_set_forced_mode(rdev, false0); | |||
1922 | } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { | |||
1923 | if (pi->enable_boost) | |||
1924 | sumo_enable_boost(rdev, rps, false0); | |||
1925 | sumo_power_level_enable(rdev, 0, true1); | |||
1926 | sumo_set_forced_level(rdev, 0); | |||
1927 | sumo_set_forced_mode_enabled(rdev); | |||
1928 | for (i = 1; i < ps->num_levels; i++) { | |||
1929 | sumo_power_level_enable(rdev, i, false0); | |||
1930 | } | |||
1931 | sumo_set_forced_mode(rdev, false0); | |||
1932 | sumo_set_forced_mode_enabled(rdev); | |||
1933 | sumo_set_forced_mode(rdev, false0); | |||
1934 | } else { | |||
1935 | for (i = 0; i < ps->num_levels; i++) { | |||
1936 | sumo_power_level_enable(rdev, i, true1); | |||
1937 | } | |||
1938 | if (pi->enable_boost) | |||
1939 | sumo_enable_boost(rdev, rps, true1); | |||
1940 | } | |||
1941 | ||||
1942 | rdev->pm.dpm.forced_level = level; | |||
1943 | ||||
1944 | return 0; | |||
1945 | } |