2 * Copyright 2012 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
28 #include "trinity_dpm.h"
30 #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
31 #define TRINITY_MINIMUM_ENGINE_CLOCK 800
32 #define SCLK_MIN_DIV_INTV_SHIFT 12
33 #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
35 #ifndef TRINITY_MGCG_SEQUENCE
36 #define TRINITY_MGCG_SEQUENCE 100
38 static const u32 trinity_mgcg_shls_default[] =
40 /* Register, Value, Mask */
41 0x0000802c, 0xc0000000, 0xffffffff,
42 0x00003fc4, 0xc0000000, 0xffffffff,
43 0x00005448, 0x00000100, 0xffffffff,
44 0x000055e4, 0x00000100, 0xffffffff,
45 0x0000160c, 0x00000100, 0xffffffff,
46 0x00008984, 0x06000100, 0xffffffff,
47 0x0000c164, 0x00000100, 0xffffffff,
48 0x00008a18, 0x00000100, 0xffffffff,
49 0x0000897c, 0x06000100, 0xffffffff,
50 0x00008b28, 0x00000100, 0xffffffff,
51 0x00009144, 0x00800200, 0xffffffff,
52 0x00009a60, 0x00000100, 0xffffffff,
53 0x00009868, 0x00000100, 0xffffffff,
54 0x00008d58, 0x00000100, 0xffffffff,
55 0x00009510, 0x00000100, 0xffffffff,
56 0x0000949c, 0x00000100, 0xffffffff,
57 0x00009654, 0x00000100, 0xffffffff,
58 0x00009030, 0x00000100, 0xffffffff,
59 0x00009034, 0x00000100, 0xffffffff,
60 0x00009038, 0x00000100, 0xffffffff,
61 0x0000903c, 0x00000100, 0xffffffff,
62 0x00009040, 0x00000100, 0xffffffff,
63 0x0000a200, 0x00000100, 0xffffffff,
64 0x0000a204, 0x00000100, 0xffffffff,
65 0x0000a208, 0x00000100, 0xffffffff,
66 0x0000a20c, 0x00000100, 0xffffffff,
67 0x00009744, 0x00000100, 0xffffffff,
68 0x00003f80, 0x00000100, 0xffffffff,
69 0x0000a210, 0x00000100, 0xffffffff,
70 0x0000a214, 0x00000100, 0xffffffff,
71 0x000004d8, 0x00000100, 0xffffffff,
72 0x00009664, 0x00000100, 0xffffffff,
73 0x00009698, 0x00000100, 0xffffffff,
74 0x000004d4, 0x00000200, 0xffffffff,
75 0x000004d0, 0x00000000, 0xffffffff,
76 0x000030cc, 0x00000104, 0xffffffff,
77 0x0000d0c0, 0x00000100, 0xffffffff,
78 0x0000d8c0, 0x00000100, 0xffffffff,
79 0x0000951c, 0x00010000, 0xffffffff,
80 0x00009160, 0x00030002, 0xffffffff,
81 0x00009164, 0x00050004, 0xffffffff,
82 0x00009168, 0x00070006, 0xffffffff,
83 0x00009178, 0x00070000, 0xffffffff,
84 0x0000917c, 0x00030002, 0xffffffff,
85 0x00009180, 0x00050004, 0xffffffff,
86 0x0000918c, 0x00010006, 0xffffffff,
87 0x00009190, 0x00090008, 0xffffffff,
88 0x00009194, 0x00070000, 0xffffffff,
89 0x00009198, 0x00030002, 0xffffffff,
90 0x0000919c, 0x00050004, 0xffffffff,
91 0x000091a8, 0x00010006, 0xffffffff,
92 0x000091ac, 0x00090008, 0xffffffff,
93 0x000091b0, 0x00070000, 0xffffffff,
94 0x000091b4, 0x00030002, 0xffffffff,
95 0x000091b8, 0x00050004, 0xffffffff,
96 0x000091c4, 0x00010006, 0xffffffff,
97 0x000091c8, 0x00090008, 0xffffffff,
98 0x000091cc, 0x00070000, 0xffffffff,
99 0x000091d0, 0x00030002, 0xffffffff,
100 0x000091d4, 0x00050004, 0xffffffff,
101 0x000091e0, 0x00010006, 0xffffffff,
102 0x000091e4, 0x00090008, 0xffffffff,
103 0x000091e8, 0x00000000, 0xffffffff,
104 0x000091ec, 0x00070000, 0xffffffff,
105 0x000091f0, 0x00030002, 0xffffffff,
106 0x000091f4, 0x00050004, 0xffffffff,
107 0x00009200, 0x00010006, 0xffffffff,
108 0x00009204, 0x00090008, 0xffffffff,
109 0x00009208, 0x00070000, 0xffffffff,
110 0x0000920c, 0x00030002, 0xffffffff,
111 0x00009210, 0x00050004, 0xffffffff,
112 0x0000921c, 0x00010006, 0xffffffff,
113 0x00009220, 0x00090008, 0xffffffff,
114 0x00009294, 0x00000000, 0xffffffff
117 static const u32 trinity_mgcg_shls_enable[] =
119 /* Register, Value, Mask */
120 0x0000802c, 0xc0000000, 0xffffffff,
121 0x000008f8, 0x00000000, 0xffffffff,
122 0x000008fc, 0x00000000, 0x000133FF,
123 0x000008f8, 0x00000001, 0xffffffff,
124 0x000008fc, 0x00000000, 0xE00B03FC,
125 0x00009150, 0x96944200, 0xffffffff
128 static const u32 trinity_mgcg_shls_disable[] =
130 /* Register, Value, Mask */
131 0x0000802c, 0xc0000000, 0xffffffff,
132 0x00009150, 0x00600000, 0xffffffff,
133 0x000008f8, 0x00000000, 0xffffffff,
134 0x000008fc, 0xffffffff, 0x000133FF,
135 0x000008f8, 0x00000001, 0xffffffff,
136 0x000008fc, 0xffffffff, 0xE00B03FC
140 #ifndef TRINITY_SYSLS_SEQUENCE
141 #define TRINITY_SYSLS_SEQUENCE 100
143 static const u32 trinity_sysls_default[] =
145 /* Register, Value, Mask */
146 0x000055e8, 0x00000000, 0xffffffff,
147 0x0000d0bc, 0x00000000, 0xffffffff,
148 0x0000d8bc, 0x00000000, 0xffffffff,
149 0x000015c0, 0x000c1401, 0xffffffff,
150 0x0000264c, 0x000c0400, 0xffffffff,
151 0x00002648, 0x000c0400, 0xffffffff,
152 0x00002650, 0x000c0400, 0xffffffff,
153 0x000020b8, 0x000c0400, 0xffffffff,
154 0x000020bc, 0x000c0400, 0xffffffff,
155 0x000020c0, 0x000c0c80, 0xffffffff,
156 0x0000f4a0, 0x000000c0, 0xffffffff,
157 0x0000f4a4, 0x00680fff, 0xffffffff,
158 0x00002f50, 0x00000404, 0xffffffff,
159 0x000004c8, 0x00000001, 0xffffffff,
160 0x0000641c, 0x00000000, 0xffffffff,
161 0x00000c7c, 0x00000000, 0xffffffff,
162 0x00006dfc, 0x00000000, 0xffffffff
165 static const u32 trinity_sysls_disable[] =
167 /* Register, Value, Mask */
168 0x0000d0c0, 0x00000000, 0xffffffff,
169 0x0000d8c0, 0x00000000, 0xffffffff,
170 0x000055e8, 0x00000000, 0xffffffff,
171 0x0000d0bc, 0x00000000, 0xffffffff,
172 0x0000d8bc, 0x00000000, 0xffffffff,
173 0x000015c0, 0x00041401, 0xffffffff,
174 0x0000264c, 0x00040400, 0xffffffff,
175 0x00002648, 0x00040400, 0xffffffff,
176 0x00002650, 0x00040400, 0xffffffff,
177 0x000020b8, 0x00040400, 0xffffffff,
178 0x000020bc, 0x00040400, 0xffffffff,
179 0x000020c0, 0x00040c80, 0xffffffff,
180 0x0000f4a0, 0x000000c0, 0xffffffff,
181 0x0000f4a4, 0x00680000, 0xffffffff,
182 0x00002f50, 0x00000404, 0xffffffff,
183 0x000004c8, 0x00000001, 0xffffffff,
184 0x0000641c, 0x00007ffd, 0xffffffff,
185 0x00000c7c, 0x0000ff00, 0xffffffff,
186 0x00006dfc, 0x0000007f, 0xffffffff
189 static const u32 trinity_sysls_enable[] =
191 /* Register, Value, Mask */
192 0x000055e8, 0x00000001, 0xffffffff,
193 0x0000d0bc, 0x00000100, 0xffffffff,
194 0x0000d8bc, 0x00000100, 0xffffffff,
195 0x000015c0, 0x000c1401, 0xffffffff,
196 0x0000264c, 0x000c0400, 0xffffffff,
197 0x00002648, 0x000c0400, 0xffffffff,
198 0x00002650, 0x000c0400, 0xffffffff,
199 0x000020b8, 0x000c0400, 0xffffffff,
200 0x000020bc, 0x000c0400, 0xffffffff,
201 0x000020c0, 0x000c0c80, 0xffffffff,
202 0x0000f4a0, 0x000000c0, 0xffffffff,
203 0x0000f4a4, 0x00680fff, 0xffffffff,
204 0x00002f50, 0x00000903, 0xffffffff,
205 0x000004c8, 0x00000000, 0xffffffff,
206 0x0000641c, 0x00000000, 0xffffffff,
207 0x00000c7c, 0x00000000, 0xffffffff,
208 0x00006dfc, 0x00000000, 0xffffffff
212 static const u32 trinity_override_mgpg_sequences[] =
214 /* Register, Value */
215 0x00000200, 0xE030032C,
216 0x00000204, 0x00000FFF,
217 0x00000200, 0xE0300058,
218 0x00000204, 0x00030301,
219 0x00000200, 0xE0300054,
220 0x00000204, 0x500010FF,
221 0x00000200, 0xE0300074,
222 0x00000204, 0x00030301,
223 0x00000200, 0xE0300070,
224 0x00000204, 0x500010FF,
225 0x00000200, 0xE0300090,
226 0x00000204, 0x00030301,
227 0x00000200, 0xE030008C,
228 0x00000204, 0x500010FF,
229 0x00000200, 0xE03000AC,
230 0x00000204, 0x00030301,
231 0x00000200, 0xE03000A8,
232 0x00000204, 0x500010FF,
233 0x00000200, 0xE03000C8,
234 0x00000204, 0x00030301,
235 0x00000200, 0xE03000C4,
236 0x00000204, 0x500010FF,
237 0x00000200, 0xE03000E4,
238 0x00000204, 0x00030301,
239 0x00000200, 0xE03000E0,
240 0x00000204, 0x500010FF,
241 0x00000200, 0xE0300100,
242 0x00000204, 0x00030301,
243 0x00000200, 0xE03000FC,
244 0x00000204, 0x500010FF,
245 0x00000200, 0xE0300058,
246 0x00000204, 0x00030303,
247 0x00000200, 0xE0300054,
248 0x00000204, 0x600010FF,
249 0x00000200, 0xE0300074,
250 0x00000204, 0x00030303,
251 0x00000200, 0xE0300070,
252 0x00000204, 0x600010FF,
253 0x00000200, 0xE0300090,
254 0x00000204, 0x00030303,
255 0x00000200, 0xE030008C,
256 0x00000204, 0x600010FF,
257 0x00000200, 0xE03000AC,
258 0x00000204, 0x00030303,
259 0x00000200, 0xE03000A8,
260 0x00000204, 0x600010FF,
261 0x00000200, 0xE03000C8,
262 0x00000204, 0x00030303,
263 0x00000200, 0xE03000C4,
264 0x00000204, 0x600010FF,
265 0x00000200, 0xE03000E4,
266 0x00000204, 0x00030303,
267 0x00000200, 0xE03000E0,
268 0x00000204, 0x600010FF,
269 0x00000200, 0xE0300100,
270 0x00000204, 0x00030303,
271 0x00000200, 0xE03000FC,
272 0x00000204, 0x600010FF,
273 0x00000200, 0xE0300058,
274 0x00000204, 0x00030303,
275 0x00000200, 0xE0300054,
276 0x00000204, 0x700010FF,
277 0x00000200, 0xE0300074,
278 0x00000204, 0x00030303,
279 0x00000200, 0xE0300070,
280 0x00000204, 0x700010FF,
281 0x00000200, 0xE0300090,
282 0x00000204, 0x00030303,
283 0x00000200, 0xE030008C,
284 0x00000204, 0x700010FF,
285 0x00000200, 0xE03000AC,
286 0x00000204, 0x00030303,
287 0x00000200, 0xE03000A8,
288 0x00000204, 0x700010FF,
289 0x00000200, 0xE03000C8,
290 0x00000204, 0x00030303,
291 0x00000200, 0xE03000C4,
292 0x00000204, 0x700010FF,
293 0x00000200, 0xE03000E4,
294 0x00000204, 0x00030303,
295 0x00000200, 0xE03000E0,
296 0x00000204, 0x700010FF,
297 0x00000200, 0xE0300100,
298 0x00000204, 0x00030303,
299 0x00000200, 0xE03000FC,
300 0x00000204, 0x700010FF,
301 0x00000200, 0xE0300058,
302 0x00000204, 0x00010303,
303 0x00000200, 0xE0300054,
304 0x00000204, 0x800010FF,
305 0x00000200, 0xE0300074,
306 0x00000204, 0x00010303,
307 0x00000200, 0xE0300070,
308 0x00000204, 0x800010FF,
309 0x00000200, 0xE0300090,
310 0x00000204, 0x00010303,
311 0x00000200, 0xE030008C,
312 0x00000204, 0x800010FF,
313 0x00000200, 0xE03000AC,
314 0x00000204, 0x00010303,
315 0x00000200, 0xE03000A8,
316 0x00000204, 0x800010FF,
317 0x00000200, 0xE03000C4,
318 0x00000204, 0x800010FF,
319 0x00000200, 0xE03000C8,
320 0x00000204, 0x00010303,
321 0x00000200, 0xE03000E4,
322 0x00000204, 0x00010303,
323 0x00000200, 0xE03000E0,
324 0x00000204, 0x800010FF,
325 0x00000200, 0xE0300100,
326 0x00000204, 0x00010303,
327 0x00000200, 0xE03000FC,
328 0x00000204, 0x800010FF,
329 0x00000200, 0x0001f198,
330 0x00000204, 0x0003ffff,
331 0x00000200, 0x0001f19C,
332 0x00000204, 0x3fffffff,
333 0x00000200, 0xE030032C,
334 0x00000204, 0x00000000,
337 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
338 const u32 *seq, u32 count);
339 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
340 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
341 struct radeon_ps *new_rps,
342 struct radeon_ps *old_rps);
344 struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
346 struct trinity_ps *ps = rps->ps_priv;
351 struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
353 struct trinity_power_info *pi = rdev->pm.dpm.priv;
358 static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
360 struct trinity_power_info *pi = trinity_get_pi(rdev);
363 struct atom_clock_dividers dividers;
364 u32 xclk = radeon_get_xclk(rdev);
367 u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
369 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
370 25000, false, ÷rs);
374 value = RREG32_SMC(GFX_POWER_GATING_CNTL);
375 value &= ~(SSSD_MASK | PDS_DIV_MASK);
378 value |= PDS_DIV(dividers.post_div);
379 WREG32_SMC(GFX_POWER_GATING_CNTL, value);
381 r600_calculate_u_and_p(500, xclk, 16, &p, &u);
383 WREG32(CG_PG_CTRL, SP(p) | SU(u));
385 WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
387 /* XXX double check hw_rev */
388 if (pi->override_dynamic_mgpg && (hw_rev == 0))
389 trinity_override_dynamic_mg_powergating(rdev);
393 #define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF
394 #define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE
395 #define CGTS_SM_CTRL_REG_DISABLE 0x00600000
396 #define CGTS_SM_CTRL_REG_ENABLE 0x96944200
398 static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
405 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
406 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
408 WREG32_CG(CG_CGTT_LOCAL_0,
409 (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
410 WREG32_CG(CG_CGTT_LOCAL_1,
411 (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
413 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
415 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
417 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
418 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
420 WREG32_CG(CG_CGTT_LOCAL_0,
421 CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
422 WREG32_CG(CG_CGTT_LOCAL_1,
423 CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
427 static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
430 const u32 *seq = NULL;
432 seq = &trinity_mgcg_shls_default[0];
433 count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
435 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
438 static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
442 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
444 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
445 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
446 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
447 RREG32(GB_ADDR_CONFIG);
451 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
452 const u32 *seq, u32 count)
454 u32 i, length = count * 3;
456 for (i = 0; i < length; i += 3)
457 WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
460 static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
461 const u32 *seq, u32 count)
463 u32 i, length = count * 2;
465 for (i = 0; i < length; i += 2)
466 WREG32(seq[i], seq[i+1]);
470 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
473 const u32 *seq = NULL;
475 seq = &trinity_override_mgpg_sequences[0];
476 count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
478 trinity_program_override_mgpg_sequences(rdev, seq, count);
481 static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
485 const u32 *seq = NULL;
488 seq = &trinity_sysls_enable[0];
489 count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
491 seq = &trinity_sysls_disable[0];
492 count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
495 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
498 static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
502 if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
503 WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
505 WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
507 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
508 RREG32(GB_ADDR_CONFIG);
512 static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
518 value = RREG32_SMC(PM_I_CNTL_1);
519 value &= ~DS_PG_CNTL_MASK;
520 value |= DS_PG_CNTL(1);
521 WREG32_SMC(PM_I_CNTL_1, value);
523 value = RREG32_SMC(SMU_S_PG_CNTL);
524 value &= ~DS_PG_EN_MASK;
525 value |= DS_PG_EN(1);
526 WREG32_SMC(SMU_S_PG_CNTL, value);
528 value = RREG32_SMC(SMU_S_PG_CNTL);
529 value &= ~DS_PG_EN_MASK;
530 WREG32_SMC(SMU_S_PG_CNTL, value);
532 value = RREG32_SMC(PM_I_CNTL_1);
533 value &= ~DS_PG_CNTL_MASK;
534 WREG32_SMC(PM_I_CNTL_1, value);
537 trinity_gfx_dynamic_mgpg_config(rdev);
541 static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
543 struct trinity_power_info *pi = trinity_get_pi(rdev);
545 if (pi->enable_gfx_clock_gating)
546 sumo_gfx_clockgating_initialize(rdev);
547 if (pi->enable_mg_clock_gating)
548 trinity_mg_clockgating_initialize(rdev);
549 if (pi->enable_gfx_power_gating)
550 trinity_gfx_powergating_initialize(rdev);
551 if (pi->enable_mg_clock_gating) {
552 trinity_ls_clockgating_enable(rdev, true);
553 trinity_mg_clockgating_enable(rdev, true);
555 if (pi->enable_gfx_clock_gating)
556 trinity_gfx_clockgating_enable(rdev, true);
557 if (pi->enable_gfx_dynamic_mgpg)
558 trinity_gfx_dynamic_mgpg_enable(rdev, true);
559 if (pi->enable_gfx_power_gating)
560 trinity_gfx_powergating_enable(rdev, true);
563 static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
565 struct trinity_power_info *pi = trinity_get_pi(rdev);
567 if (pi->enable_gfx_power_gating)
568 trinity_gfx_powergating_enable(rdev, false);
569 if (pi->enable_gfx_dynamic_mgpg)
570 trinity_gfx_dynamic_mgpg_enable(rdev, false);
571 if (pi->enable_gfx_clock_gating)
572 trinity_gfx_clockgating_enable(rdev, false);
573 if (pi->enable_mg_clock_gating) {
574 trinity_mg_clockgating_enable(rdev, false);
575 trinity_ls_clockgating_enable(rdev, false);
579 static void trinity_set_divider_value(struct radeon_device *rdev,
582 struct atom_clock_dividers dividers;
585 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
587 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
588 sclk, false, ÷rs);
592 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
593 value &= ~CLK_DIVIDER_MASK;
594 value |= CLK_DIVIDER(dividers.post_div);
595 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
597 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
598 sclk/2, false, ÷rs);
602 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
603 value &= ~PD_SCLK_DIVIDER_MASK;
604 value |= PD_SCLK_DIVIDER(dividers.post_div);
605 WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
608 static void trinity_set_ds_dividers(struct radeon_device *rdev,
609 u32 index, u32 divider)
612 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
614 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
615 value &= ~DS_DIV_MASK;
616 value |= DS_DIV(divider);
617 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
620 static void trinity_set_ss_dividers(struct radeon_device *rdev,
621 u32 index, u32 divider)
624 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
626 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
627 value &= ~DS_SH_DIV_MASK;
628 value |= DS_SH_DIV(divider);
629 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
632 static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
634 struct trinity_power_info *pi = trinity_get_pi(rdev);
635 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
637 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
639 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
641 value |= VID(vid_7bit);
642 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
644 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
647 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
650 static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
651 u32 index, u32 gnb_slow)
654 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
656 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
657 value &= ~GNB_SLOW_MASK;
658 value |= GNB_SLOW(gnb_slow);
659 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
662 static void trinity_set_force_nbp_state(struct radeon_device *rdev,
663 u32 index, u32 force_nbp_state)
666 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
668 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
669 value &= ~FORCE_NBPS1_MASK;
670 value |= FORCE_NBPS1(force_nbp_state);
671 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
674 static void trinity_set_display_wm(struct radeon_device *rdev,
678 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
680 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
681 value &= ~DISPLAY_WM_MASK;
682 value |= DISPLAY_WM(wm);
683 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
686 static void trinity_set_vce_wm(struct radeon_device *rdev,
690 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
692 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
693 value &= ~VCE_WM_MASK;
695 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
698 static void trinity_set_at(struct radeon_device *rdev,
702 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
704 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
707 WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
710 static void trinity_program_power_level(struct radeon_device *rdev,
711 struct trinity_pl *pl, u32 index)
713 struct trinity_power_info *pi = trinity_get_pi(rdev);
715 if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
718 trinity_set_divider_value(rdev, index, pl->sclk);
719 trinity_set_vid(rdev, index, pl->vddc_index);
720 trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
721 trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
722 trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
723 trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
724 trinity_set_display_wm(rdev, index, pl->display_wm);
725 trinity_set_vce_wm(rdev, index, pl->vce_wm);
726 trinity_set_at(rdev, index, pi->at[index]);
729 static void trinity_power_level_enable_disable(struct radeon_device *rdev,
730 u32 index, bool enable)
733 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
735 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
736 value &= ~STATE_VALID_MASK;
738 value |= STATE_VALID(1);
739 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
742 static bool trinity_dpm_enabled(struct radeon_device *rdev)
744 if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
750 static void trinity_start_dpm(struct radeon_device *rdev)
752 u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
754 value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
755 value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
756 WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
758 WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
759 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
761 trinity_dpm_config(rdev, true);
764 static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
768 for (i = 0; i < rdev->usec_timeout; i++) {
769 if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
773 for (i = 0; i < rdev->usec_timeout; i++) {
774 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
778 for (i = 0; i < rdev->usec_timeout; i++) {
779 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
785 static void trinity_stop_dpm(struct radeon_device *rdev)
789 WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
791 sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
792 sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
793 WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
795 trinity_dpm_config(rdev, false);
798 static void trinity_start_am(struct radeon_device *rdev)
800 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
803 static void trinity_reset_am(struct radeon_device *rdev)
805 WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
806 ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
809 static void trinity_wait_for_level_0(struct radeon_device *rdev)
813 for (i = 0; i < rdev->usec_timeout; i++) {
814 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
820 static void trinity_enable_power_level_0(struct radeon_device *rdev)
822 trinity_power_level_enable_disable(rdev, 0, true);
825 static void trinity_force_level_0(struct radeon_device *rdev)
827 trinity_dpm_force_state(rdev, 0);
830 static void trinity_unforce_levels(struct radeon_device *rdev)
832 trinity_dpm_no_forced_level(rdev);
835 static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev,
836 struct radeon_ps *new_rps,
837 struct radeon_ps *old_rps)
839 struct trinity_ps *new_ps = trinity_get_ps(new_rps);
840 struct trinity_ps *old_ps = trinity_get_ps(old_rps);
842 u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
844 for (i = 0; i < new_ps->num_levels; i++) {
845 trinity_program_power_level(rdev, &new_ps->levels[i], i);
846 trinity_power_level_enable_disable(rdev, i, true);
849 for (i = new_ps->num_levels; i < n_current_state_levels; i++)
850 trinity_power_level_enable_disable(rdev, i, false);
853 static void trinity_program_bootup_state(struct radeon_device *rdev)
855 struct trinity_power_info *pi = trinity_get_pi(rdev);
858 trinity_program_power_level(rdev, &pi->boot_pl, 0);
859 trinity_power_level_enable_disable(rdev, 0, true);
861 for (i = 1; i < 8; i++)
862 trinity_power_level_enable_disable(rdev, i, false);
865 static void trinity_setup_uvd_clock_table(struct radeon_device *rdev,
866 struct radeon_ps *rps)
868 struct trinity_ps *ps = trinity_get_ps(rps);
869 u32 uvdstates = (ps->vclk_low_divider |
870 ps->vclk_high_divider << 8 |
871 ps->dclk_low_divider << 16 |
872 ps->dclk_high_divider << 24);
874 WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates);
877 static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev,
881 u32 tp = RREG32_SMC(PM_TP);
883 u32 xclk = radeon_get_xclk(rdev);
885 r600_calculate_u_and_p(interval, xclk, 16, &p, &u);
887 val = (p + tp - 1) / tp;
889 WREG32_SMC(SMU_UVD_DPM_CNTL, val);
892 static bool trinity_uvd_clocks_zero(struct radeon_ps *rps)
894 if ((rps->vclk == 0) && (rps->dclk == 0))
900 static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1,
901 struct radeon_ps *rps2)
903 struct trinity_ps *ps1 = trinity_get_ps(rps1);
904 struct trinity_ps *ps2 = trinity_get_ps(rps2);
906 if ((rps1->vclk == rps2->vclk) &&
907 (rps1->dclk == rps2->dclk) &&
908 (ps1->vclk_low_divider == ps2->vclk_low_divider) &&
909 (ps1->vclk_high_divider == ps2->vclk_high_divider) &&
910 (ps1->dclk_low_divider == ps2->dclk_low_divider) &&
911 (ps1->dclk_high_divider == ps2->dclk_high_divider))
917 static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
918 struct radeon_ps *new_rps,
919 struct radeon_ps *old_rps)
921 struct trinity_power_info *pi = trinity_get_pi(rdev);
924 if (trinity_uvd_clocks_zero(new_rps) &&
925 !trinity_uvd_clocks_zero(old_rps)) {
926 trinity_setup_uvd_dpm_interval(rdev, 0);
927 } else if (!trinity_uvd_clocks_zero(new_rps)) {
928 trinity_setup_uvd_clock_table(rdev, new_rps);
930 if (trinity_uvd_clocks_zero(old_rps)) {
931 u32 tmp = RREG32(CG_MISC_REG);
933 WREG32(CG_MISC_REG, tmp);
935 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
937 trinity_setup_uvd_dpm_interval(rdev, 3000);
940 trinity_uvd_dpm_config(rdev);
942 if (trinity_uvd_clocks_zero(new_rps) ||
943 trinity_uvd_clocks_equal(new_rps, old_rps))
946 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
950 static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
951 struct radeon_ps *new_rps,
952 struct radeon_ps *old_rps)
954 struct trinity_ps *new_ps = trinity_get_ps(new_rps);
955 struct trinity_ps *current_ps = trinity_get_ps(new_rps);
957 if (new_ps->levels[new_ps->num_levels - 1].sclk >=
958 current_ps->levels[current_ps->num_levels - 1].sclk)
961 trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
964 static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
965 struct radeon_ps *new_rps,
966 struct radeon_ps *old_rps)
968 struct trinity_ps *new_ps = trinity_get_ps(new_rps);
969 struct trinity_ps *current_ps = trinity_get_ps(old_rps);
971 if (new_ps->levels[new_ps->num_levels - 1].sclk <
972 current_ps->levels[current_ps->num_levels - 1].sclk)
975 trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
978 static void trinity_program_ttt(struct radeon_device *rdev)
980 struct trinity_power_info *pi = trinity_get_pi(rdev);
981 u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
983 value &= ~(HT_MASK | LT_MASK);
984 value |= HT((pi->thermal_auto_throttling + 49) * 8);
985 value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
986 WREG32_SMC(SMU_SCLK_DPM_TTT, value);
989 static void trinity_enable_att(struct radeon_device *rdev)
991 u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
993 value &= ~SCLK_TT_EN_MASK;
994 value |= SCLK_TT_EN(1);
995 WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
998 static void trinity_program_sclk_dpm(struct radeon_device *rdev)
1001 u32 tp = RREG32_SMC(PM_TP);
1003 u32 xclk = radeon_get_xclk(rdev);
1006 r600_calculate_u_and_p(400, xclk, 16, &p, &u);
1008 ni = (p + tp - 1) / tp;
1010 value = RREG32_SMC(PM_I_CNTL_1);
1011 value &= ~SCLK_DPM_MASK;
1012 value |= SCLK_DPM(ni);
1013 WREG32_SMC(PM_I_CNTL_1, value);
1016 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
1017 int min_temp, int max_temp)
1019 int low_temp = 0 * 1000;
1020 int high_temp = 255 * 1000;
1022 if (low_temp < min_temp)
1023 low_temp = min_temp;
1024 if (high_temp > max_temp)
1025 high_temp = max_temp;
1026 if (high_temp < low_temp) {
1027 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
1031 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
1032 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
1034 rdev->pm.dpm.thermal.min_temp = low_temp;
1035 rdev->pm.dpm.thermal.max_temp = high_temp;
1040 static void trinity_update_current_ps(struct radeon_device *rdev,
1041 struct radeon_ps *rps)
1043 struct trinity_ps *new_ps = trinity_get_ps(rps);
1044 struct trinity_power_info *pi = trinity_get_pi(rdev);
1046 pi->current_rps = *rps;
1047 pi->current_ps = *new_ps;
1048 pi->current_rps.ps_priv = &pi->current_ps;
1051 static void trinity_update_requested_ps(struct radeon_device *rdev,
1052 struct radeon_ps *rps)
1054 struct trinity_ps *new_ps = trinity_get_ps(rps);
1055 struct trinity_power_info *pi = trinity_get_pi(rdev);
1057 pi->requested_rps = *rps;
1058 pi->requested_ps = *new_ps;
1059 pi->requested_rps.ps_priv = &pi->requested_ps;
1062 int trinity_dpm_enable(struct radeon_device *rdev)
1064 struct trinity_power_info *pi = trinity_get_pi(rdev);
1067 trinity_acquire_mutex(rdev);
1069 if (trinity_dpm_enabled(rdev)) {
1070 trinity_release_mutex(rdev);
1074 trinity_enable_clock_power_gating(rdev);
1075 trinity_program_bootup_state(rdev);
1076 sumo_program_vc(rdev, 0x00C00033);
1077 trinity_start_am(rdev);
1078 if (pi->enable_auto_thermal_throttling) {
1079 trinity_program_ttt(rdev);
1080 trinity_enable_att(rdev);
1082 trinity_program_sclk_dpm(rdev);
1083 trinity_start_dpm(rdev);
1084 trinity_wait_for_dpm_enabled(rdev);
1085 trinity_release_mutex(rdev);
1087 if (rdev->irq.installed &&
1088 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1089 ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
1091 trinity_release_mutex(rdev);
1094 rdev->irq.dpm_thermal = true;
1095 radeon_irq_set(rdev);
1098 trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1103 void trinity_dpm_disable(struct radeon_device *rdev)
1105 trinity_acquire_mutex(rdev);
1106 if (!trinity_dpm_enabled(rdev)) {
1107 trinity_release_mutex(rdev);
1110 trinity_disable_clock_power_gating(rdev);
1111 sumo_clear_vc(rdev);
1112 trinity_wait_for_level_0(rdev);
1113 trinity_stop_dpm(rdev);
1114 trinity_reset_am(rdev);
1115 trinity_release_mutex(rdev);
1117 if (rdev->irq.installed &&
1118 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1119 rdev->irq.dpm_thermal = false;
1120 radeon_irq_set(rdev);
1123 trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1126 static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
1128 struct trinity_power_info *pi = trinity_get_pi(rdev);
1131 (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
1134 static void trinity_setup_nbp_sim(struct radeon_device *rdev,
1135 struct radeon_ps *rps)
1137 struct trinity_power_info *pi = trinity_get_pi(rdev);
1138 struct trinity_ps *new_ps = trinity_get_ps(rps);
1141 if (pi->sys_info.nb_dpm_enable) {
1142 nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
1143 nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
1144 nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
1145 Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
1146 DpmXNbPsLo(new_ps->DpmXNbPsLo) |
1147 DpmXNbPsHi(new_ps->DpmXNbPsHi));
1148 WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
1152 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev)
1154 struct trinity_power_info *pi = trinity_get_pi(rdev);
1155 struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
1156 struct radeon_ps *new_ps = &requested_ps;
1158 trinity_update_requested_ps(rdev, new_ps);
1160 trinity_apply_state_adjust_rules(rdev,
1167 int trinity_dpm_set_power_state(struct radeon_device *rdev)
1169 struct trinity_power_info *pi = trinity_get_pi(rdev);
1170 struct radeon_ps *new_ps = &pi->requested_rps;
1171 struct radeon_ps *old_ps = &pi->current_rps;
1173 trinity_acquire_mutex(rdev);
1174 if (pi->enable_dpm) {
1175 trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
1176 trinity_enable_power_level_0(rdev);
1177 trinity_force_level_0(rdev);
1178 trinity_wait_for_level_0(rdev);
1179 trinity_setup_nbp_sim(rdev, new_ps);
1180 trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
1181 trinity_force_level_0(rdev);
1182 trinity_unforce_levels(rdev);
1183 trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1185 trinity_release_mutex(rdev);
1190 void trinity_dpm_post_set_power_state(struct radeon_device *rdev)
1192 struct trinity_power_info *pi = trinity_get_pi(rdev);
1193 struct radeon_ps *new_ps = &pi->requested_rps;
1195 trinity_update_current_ps(rdev, new_ps);
1198 void trinity_dpm_setup_asic(struct radeon_device *rdev)
1200 trinity_acquire_mutex(rdev);
1201 sumo_program_sstp(rdev);
1202 sumo_take_smu_control(rdev, true);
1203 trinity_get_min_sclk_divider(rdev);
1204 trinity_release_mutex(rdev);
1207 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1209 struct trinity_power_info *pi = trinity_get_pi(rdev);
1211 trinity_acquire_mutex(rdev);
1212 if (pi->enable_dpm) {
1213 trinity_enable_power_level_0(rdev);
1214 trinity_force_level_0(rdev);
1215 trinity_wait_for_level_0(rdev);
1216 trinity_program_bootup_state(rdev);
1217 trinity_force_level_0(rdev);
1218 trinity_unforce_levels(rdev);
1220 trinity_release_mutex(rdev);
1223 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1226 struct trinity_power_info *pi = trinity_get_pi(rdev);
1227 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1228 u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1229 u32 step = (svi_mode == 0) ? 1250 : 625;
1230 u32 delta = vid_7bit * step + 50;
1235 return (155000 - delta) / 100;
1238 static void trinity_patch_boot_state(struct radeon_device *rdev,
1239 struct trinity_ps *ps)
1241 struct trinity_power_info *pi = trinity_get_pi(rdev);
1246 ps->levels[0] = pi->boot_pl;
1249 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1256 static void trinity_construct_boot_state(struct radeon_device *rdev)
1258 struct trinity_power_info *pi = trinity_get_pi(rdev);
1260 pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1261 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1262 pi->boot_pl.ds_divider_index = 0;
1263 pi->boot_pl.ss_divider_index = 0;
1264 pi->boot_pl.allow_gnb_slow = 1;
1265 pi->boot_pl.force_nbp_state = 0;
1266 pi->boot_pl.display_wm = 0;
1267 pi->boot_pl.vce_wm = 0;
1268 pi->current_ps.num_levels = 1;
1269 pi->current_ps.levels[0] = pi->boot_pl;
1272 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1273 u32 sclk, u32 min_sclk_in_sr)
1275 struct trinity_power_info *pi = trinity_get_pi(rdev);
1278 u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1279 min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1284 if (!pi->enable_sclk_ds)
1287 for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
1288 temp = sclk / sumo_get_sleep_divider_from_id(i);
1289 if (temp >= min || i == 0)
1296 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1299 struct trinity_power_info *pi = trinity_get_pi(rdev);
1302 for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1303 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1304 return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1307 if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1308 DRM_ERROR("engine clock out of range!");
1313 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1314 struct trinity_ps *ps,
1315 struct trinity_ps *current_ps)
1317 struct trinity_power_info *pi = trinity_get_pi(rdev);
1318 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1321 u32 current_index = 0;
1324 current_vddc = current_ps->levels[current_index].vddc_index;
1325 current_sclk = current_ps->levels[current_index].sclk;
1327 current_vddc = pi->boot_pl.vddc_index;
1328 current_sclk = pi->boot_pl.sclk;
1331 ps->levels[0].vddc_index = current_vddc;
1333 if (ps->levels[0].sclk > current_sclk)
1334 ps->levels[0].sclk = current_sclk;
1336 ps->levels[0].ds_divider_index =
1337 trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1338 ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1339 ps->levels[0].allow_gnb_slow = 1;
1340 ps->levels[0].force_nbp_state = 0;
1341 ps->levels[0].display_wm = 0;
1342 ps->levels[0].vce_wm =
1343 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1346 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1347 struct trinity_ps *ps, u32 index)
1349 if (ps == NULL || ps->num_levels <= 1)
1351 else if (ps->num_levels == 2) {
1359 else if (ps->levels[index].sclk < 30000)
1366 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
1367 struct radeon_ps *rps)
1369 struct trinity_power_info *pi = trinity_get_pi(rdev);
1372 for (i = 0; i < 4; i++) {
1373 if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
1374 (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
1379 DRM_ERROR("UVD clock index not found!\n");
1385 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1386 struct radeon_ps *rps)
1388 struct trinity_ps *ps = trinity_get_ps(rps);
1389 struct trinity_power_info *pi = trinity_get_pi(rdev);
1393 if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
1394 high_index = trinity_get_uvd_clock_index(rdev, rps);
1396 switch(high_index) {
1408 ps->vclk_low_divider =
1409 pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
1410 ps->dclk_low_divider =
1411 pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
1412 ps->vclk_high_divider =
1413 pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
1414 ps->dclk_high_divider =
1415 pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
1421 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1422 struct radeon_ps *new_rps,
1423 struct radeon_ps *old_rps)
1425 struct trinity_ps *ps = trinity_get_ps(new_rps);
1426 struct trinity_ps *current_ps = trinity_get_ps(old_rps);
1427 struct trinity_power_info *pi = trinity_get_pi(rdev);
1428 u32 min_voltage = 0; /* ??? */
1429 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1430 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1433 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1435 if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1436 return trinity_patch_thermal_state(rdev, ps, current_ps);
1438 trinity_adjust_uvd_state(rdev, new_rps);
1440 for (i = 0; i < ps->num_levels; i++) {
1441 if (ps->levels[i].vddc_index < min_voltage)
1442 ps->levels[i].vddc_index = min_voltage;
1444 if (ps->levels[i].sclk < min_sclk)
1445 ps->levels[i].sclk =
1446 trinity_get_valid_engine_clock(rdev, min_sclk);
1448 ps->levels[i].ds_divider_index =
1449 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1451 ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1453 ps->levels[i].allow_gnb_slow = 1;
1454 ps->levels[i].force_nbp_state = 0;
1455 ps->levels[i].display_wm =
1456 trinity_calculate_display_wm(rdev, ps, i);
1457 ps->levels[i].vce_wm =
1458 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1461 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1462 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1463 ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1465 if (pi->sys_info.nb_dpm_enable) {
1466 ps->Dpm0PgNbPsLo = 0x1;
1467 ps->Dpm0PgNbPsHi = 0x0;
1468 ps->DpmXNbPsLo = 0x2;
1469 ps->DpmXNbPsHi = 0x1;
1471 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1472 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1473 force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1474 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1475 (pi->sys_info.uma_channel_number == 1)));
1476 force_high = (num_active_displays >= 3) || force_high;
1477 ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1478 ps->Dpm0PgNbPsHi = 0x1;
1479 ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1480 ps->DpmXNbPsHi = 0x2;
1481 ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1486 static void trinity_cleanup_asic(struct radeon_device *rdev)
1488 sumo_take_smu_control(rdev, false);
1492 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1494 struct trinity_power_info *pi = trinity_get_pi(rdev);
1496 if (pi->voltage_drop_in_dce)
1497 trinity_dce_enable_voltage_adjustment(rdev, false);
1501 static void trinity_add_dccac_value(struct radeon_device *rdev)
1503 u32 gpu_cac_avrg_cntl_window_size;
1504 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1505 u64 disp_clk = rdev->clock.default_dispclk / 100;
1508 gpu_cac_avrg_cntl_window_size =
1509 (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1511 dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1512 (32 - gpu_cac_avrg_cntl_window_size));
1514 WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1517 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1519 struct trinity_power_info *pi = trinity_get_pi(rdev);
1521 if (pi->voltage_drop_in_dce)
1522 trinity_dce_enable_voltage_adjustment(rdev, true);
1523 trinity_add_dccac_value(rdev);
1527 struct _ATOM_POWERPLAY_INFO info;
1528 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1529 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1530 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1531 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1532 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1535 union pplib_clock_info {
1536 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1537 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1538 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1539 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1542 union pplib_power_state {
1543 struct _ATOM_PPLIB_STATE v1;
1544 struct _ATOM_PPLIB_STATE_V2 v2;
1547 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1548 struct radeon_ps *rps,
1549 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1552 struct trinity_ps *ps = trinity_get_ps(rps);
1554 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1555 rps->class = le16_to_cpu(non_clock_info->usClassification);
1556 rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1558 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1559 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1560 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1566 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1567 rdev->pm.dpm.boot_ps = rps;
1568 trinity_patch_boot_state(rdev, ps);
1570 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1571 rdev->pm.dpm.uvd_ps = rps;
1574 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1575 struct radeon_ps *rps, int index,
1576 union pplib_clock_info *clock_info)
1578 struct trinity_power_info *pi = trinity_get_pi(rdev);
1579 struct trinity_ps *ps = trinity_get_ps(rps);
1580 struct trinity_pl *pl = &ps->levels[index];
1583 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1584 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1586 pl->vddc_index = clock_info->sumo.vddcIndex;
1588 ps->num_levels = index + 1;
1590 if (pi->enable_sclk_ds) {
1591 pl->ds_divider_index = 5;
1592 pl->ss_divider_index = 5;
1596 static int trinity_parse_power_table(struct radeon_device *rdev)
1598 struct radeon_mode_info *mode_info = &rdev->mode_info;
1599 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1600 union pplib_power_state *power_state;
1601 int i, j, k, non_clock_array_index, clock_array_index;
1602 union pplib_clock_info *clock_info;
1603 struct _StateArray *state_array;
1604 struct _ClockInfoArray *clock_info_array;
1605 struct _NonClockInfoArray *non_clock_info_array;
1606 union power_info *power_info;
1607 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1610 u8 *power_state_offset;
1613 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1614 &frev, &crev, &data_offset))
1616 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1618 state_array = (struct _StateArray *)
1619 (mode_info->atom_context->bios + data_offset +
1620 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1621 clock_info_array = (struct _ClockInfoArray *)
1622 (mode_info->atom_context->bios + data_offset +
1623 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1624 non_clock_info_array = (struct _NonClockInfoArray *)
1625 (mode_info->atom_context->bios + data_offset +
1626 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1628 rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
1629 state_array->ucNumEntries, GFP_KERNEL);
1630 if (!rdev->pm.dpm.ps)
1632 power_state_offset = (u8 *)state_array->states;
1633 rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
1634 rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
1635 rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
1636 for (i = 0; i < state_array->ucNumEntries; i++) {
1637 power_state = (union pplib_power_state *)power_state_offset;
1638 non_clock_array_index = power_state->v2.nonClockInfoIndex;
1639 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1640 &non_clock_info_array->nonClockInfo[non_clock_array_index];
1641 if (!rdev->pm.power_state[i].clock_info)
1643 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1645 kfree(rdev->pm.dpm.ps);
1648 rdev->pm.dpm.ps[i].ps_priv = ps;
1650 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1651 clock_array_index = power_state->v2.clockInfoIndex[j];
1652 if (clock_array_index >= clock_info_array->ucNumEntries)
1654 if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1656 clock_info = (union pplib_clock_info *)
1657 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
1658 trinity_parse_pplib_clock_info(rdev,
1659 &rdev->pm.dpm.ps[i], k,
1663 trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1665 non_clock_info_array->ucEntrySize);
1666 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1668 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1673 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1674 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1675 struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1676 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1677 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1680 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
1682 struct trinity_power_info *pi = trinity_get_pi(rdev);
1685 if (did >= 8 && did <= 0x3f)
1687 else if (did > 0x3f && did <= 0x5f)
1688 divider = (did - 64) * 50 + 1600;
1689 else if (did > 0x5f && did <= 0x7e)
1690 divider = (did - 96) * 100 + 3200;
1691 else if (did == 0x7f)
1692 divider = 128 * 100;
1696 return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
1699 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1701 struct trinity_power_info *pi = trinity_get_pi(rdev);
1702 struct radeon_mode_info *mode_info = &rdev->mode_info;
1703 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1704 union igp_info *igp_info;
1709 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1710 &frev, &crev, &data_offset)) {
1711 igp_info = (union igp_info *)(mode_info->atom_context->bios +
1715 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1718 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1719 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1720 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1721 pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
1722 pi->sys_info.bootup_nb_voltage_index =
1723 le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1724 if (igp_info->info_7.ucHtcTmpLmt == 0)
1725 pi->sys_info.htc_tmp_lmt = 203;
1727 pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1728 if (igp_info->info_7.ucHtcHystLmt == 0)
1729 pi->sys_info.htc_hyst_lmt = 5;
1731 pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1732 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1733 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1736 if (pi->enable_nbps_policy)
1737 pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1739 pi->sys_info.nb_dpm_enable = 0;
1741 for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1742 pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1743 pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1746 pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1747 pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1748 pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1749 pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1751 if (!pi->sys_info.nb_dpm_enable) {
1752 for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1753 pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1754 pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1755 pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1759 pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1761 sumo_construct_sclk_voltage_mapping_table(rdev,
1762 &pi->sys_info.sclk_voltage_mapping_table,
1763 igp_info->info_7.sAvail_SCLK);
1764 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1765 igp_info->info_7.sAvail_SCLK);
1767 pi->sys_info.uvd_clock_table_entries[0].vclk_did =
1768 igp_info->info_7.ucDPMState0VclkFid;
1769 pi->sys_info.uvd_clock_table_entries[1].vclk_did =
1770 igp_info->info_7.ucDPMState1VclkFid;
1771 pi->sys_info.uvd_clock_table_entries[2].vclk_did =
1772 igp_info->info_7.ucDPMState2VclkFid;
1773 pi->sys_info.uvd_clock_table_entries[3].vclk_did =
1774 igp_info->info_7.ucDPMState3VclkFid;
1776 pi->sys_info.uvd_clock_table_entries[0].dclk_did =
1777 igp_info->info_7.ucDPMState0DclkFid;
1778 pi->sys_info.uvd_clock_table_entries[1].dclk_did =
1779 igp_info->info_7.ucDPMState1DclkFid;
1780 pi->sys_info.uvd_clock_table_entries[2].dclk_did =
1781 igp_info->info_7.ucDPMState2DclkFid;
1782 pi->sys_info.uvd_clock_table_entries[3].dclk_did =
1783 igp_info->info_7.ucDPMState3DclkFid;
1785 for (i = 0; i < 4; i++) {
1786 pi->sys_info.uvd_clock_table_entries[i].vclk =
1787 trinity_convert_did_to_freq(rdev,
1788 pi->sys_info.uvd_clock_table_entries[i].vclk_did);
1789 pi->sys_info.uvd_clock_table_entries[i].dclk =
1790 trinity_convert_did_to_freq(rdev,
1791 pi->sys_info.uvd_clock_table_entries[i].dclk_did);
1800 int trinity_dpm_init(struct radeon_device *rdev)
1802 struct trinity_power_info *pi;
1805 pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1808 rdev->pm.dpm.priv = pi;
1810 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1811 pi->at[i] = TRINITY_AT_DFLT;
1813 pi->enable_nbps_policy = true;
1814 pi->enable_sclk_ds = true;
1815 pi->enable_gfx_power_gating = true;
1816 pi->enable_gfx_clock_gating = true;
1817 pi->enable_mg_clock_gating = true;
1818 pi->enable_gfx_dynamic_mgpg = true; /* ??? */
1819 pi->override_dynamic_mgpg = true;
1820 pi->enable_auto_thermal_throttling = true;
1821 pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1822 pi->uvd_dpm = true; /* ??? */
1824 ret = trinity_parse_sys_info_table(rdev);
1828 trinity_construct_boot_state(rdev);
1830 ret = trinity_parse_power_table(rdev);
1834 pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1835 pi->enable_dpm = true;
1840 void trinity_dpm_print_power_state(struct radeon_device *rdev,
1841 struct radeon_ps *rps)
1844 struct trinity_ps *ps = trinity_get_ps(rps);
1846 r600_dpm_print_class_info(rps->class, rps->class2);
1847 r600_dpm_print_cap_info(rps->caps);
1848 printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1849 for (i = 0; i < ps->num_levels; i++) {
1850 struct trinity_pl *pl = &ps->levels[i];
1851 printk("\t\tpower level %d sclk: %u vddc: %u\n",
1853 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1855 r600_dpm_print_ps_status(rdev, rps);
1858 void trinity_dpm_fini(struct radeon_device *rdev)
1862 trinity_cleanup_asic(rdev); /* ??? */
1864 for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1865 kfree(rdev->pm.dpm.ps[i].ps_priv);
1867 kfree(rdev->pm.dpm.ps);
1868 kfree(rdev->pm.dpm.priv);
1871 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
1873 struct trinity_power_info *pi = trinity_get_pi(rdev);
1874 struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
1877 return requested_state->levels[0].sclk;
1879 return requested_state->levels[requested_state->num_levels - 1].sclk;
1882 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
1884 struct trinity_power_info *pi = trinity_get_pi(rdev);
1886 return pi->sys_info.bootup_uma_clk;