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);
342 struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
344 struct trinity_ps *ps = rps->ps_priv;
349 struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
351 struct trinity_power_info *pi = rdev->pm.dpm.priv;
356 static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
358 struct trinity_power_info *pi = trinity_get_pi(rdev);
361 struct atom_clock_dividers dividers;
362 u32 xclk = sumo_get_xclk(rdev);
365 u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
367 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
368 25000, false, ÷rs);
372 value = RREG32_SMC(GFX_POWER_GATING_CNTL);
373 value &= ~(SSSD_MASK | PDS_DIV_MASK);
376 value |= PDS_DIV(dividers.post_div);
377 WREG32_SMC(GFX_POWER_GATING_CNTL, value);
379 r600_calculate_u_and_p(500, xclk, 16, &p, &u);
381 WREG32(CG_PG_CTRL, SP(p) | SU(u));
383 WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
385 /* XXX double check hw_rev */
386 if (pi->override_dynamic_mgpg && (hw_rev == 0))
387 trinity_override_dynamic_mg_powergating(rdev);
391 #define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF
392 #define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE
393 #define CGTS_SM_CTRL_REG_DISABLE 0x00600000
394 #define CGTS_SM_CTRL_REG_ENABLE 0x96944200
396 static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
403 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
404 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
406 WREG32_CG(CG_CGTT_LOCAL_0,
407 (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
408 WREG32_CG(CG_CGTT_LOCAL_1,
409 (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
411 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
413 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
415 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
416 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
418 WREG32_CG(CG_CGTT_LOCAL_0,
419 CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
420 WREG32_CG(CG_CGTT_LOCAL_1,
421 CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
425 static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
428 const u32 *seq = NULL;
430 seq = &trinity_mgcg_shls_default[0];
431 count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
433 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
436 static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
440 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
442 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
443 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
444 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
445 RREG32(GB_ADDR_CONFIG);
449 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
450 const u32 *seq, u32 count)
452 u32 i, length = count * 3;
454 for (i = 0; i < length; i += 3)
455 WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
458 static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
459 const u32 *seq, u32 count)
461 u32 i, length = count * 2;
463 for (i = 0; i < length; i += 2)
464 WREG32(seq[i], seq[i+1]);
468 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
471 const u32 *seq = NULL;
473 seq = &trinity_override_mgpg_sequences[0];
474 count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
476 trinity_program_override_mgpg_sequences(rdev, seq, count);
479 static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
483 const u32 *seq = NULL;
486 seq = &trinity_sysls_enable[0];
487 count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
489 seq = &trinity_sysls_disable[0];
490 count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
493 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
496 static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
500 if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
501 WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
503 WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
505 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
506 RREG32(GB_ADDR_CONFIG);
510 static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
516 value = RREG32_SMC(PM_I_CNTL_1);
517 value &= ~DS_PG_CNTL_MASK;
518 value |= DS_PG_CNTL(1);
519 WREG32_SMC(PM_I_CNTL_1, value);
521 value = RREG32_SMC(SMU_S_PG_CNTL);
522 value &= ~DS_PG_EN_MASK;
523 value |= DS_PG_EN(1);
524 WREG32_SMC(SMU_S_PG_CNTL, value);
526 value = RREG32_SMC(SMU_S_PG_CNTL);
527 value &= ~DS_PG_EN_MASK;
528 WREG32_SMC(SMU_S_PG_CNTL, value);
530 value = RREG32_SMC(PM_I_CNTL_1);
531 value &= ~DS_PG_CNTL_MASK;
532 WREG32_SMC(PM_I_CNTL_1, value);
535 trinity_gfx_dynamic_mgpg_config(rdev);
539 static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
541 struct trinity_power_info *pi = trinity_get_pi(rdev);
543 if (pi->enable_gfx_clock_gating)
544 sumo_gfx_clockgating_initialize(rdev);
545 if (pi->enable_mg_clock_gating)
546 trinity_mg_clockgating_initialize(rdev);
547 if (pi->enable_gfx_power_gating)
548 trinity_gfx_powergating_initialize(rdev);
549 if (pi->enable_mg_clock_gating) {
550 trinity_ls_clockgating_enable(rdev, true);
551 trinity_mg_clockgating_enable(rdev, true);
553 if (pi->enable_gfx_clock_gating)
554 trinity_gfx_clockgating_enable(rdev, true);
555 if (pi->enable_gfx_dynamic_mgpg)
556 trinity_gfx_dynamic_mgpg_enable(rdev, true);
557 if (pi->enable_gfx_power_gating)
558 trinity_gfx_powergating_enable(rdev, true);
561 static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
563 struct trinity_power_info *pi = trinity_get_pi(rdev);
565 if (pi->enable_gfx_power_gating)
566 trinity_gfx_powergating_enable(rdev, false);
567 if (pi->enable_gfx_dynamic_mgpg)
568 trinity_gfx_dynamic_mgpg_enable(rdev, false);
569 if (pi->enable_gfx_clock_gating)
570 trinity_gfx_clockgating_enable(rdev, false);
571 if (pi->enable_mg_clock_gating) {
572 trinity_mg_clockgating_enable(rdev, false);
573 trinity_ls_clockgating_enable(rdev, false);
577 static void trinity_set_divider_value(struct radeon_device *rdev,
580 struct atom_clock_dividers dividers;
583 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
585 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
586 sclk, false, ÷rs);
590 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
591 value &= ~CLK_DIVIDER_MASK;
592 value |= CLK_DIVIDER(dividers.post_div);
593 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
595 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
596 sclk/2, false, ÷rs);
600 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
601 value &= ~PD_SCLK_DIVIDER_MASK;
602 value |= PD_SCLK_DIVIDER(dividers.post_div);
603 WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
606 static void trinity_set_ds_dividers(struct radeon_device *rdev,
607 u32 index, u32 divider)
610 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
612 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
613 value &= ~DS_DIV_MASK;
614 value |= DS_DIV(divider);
615 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
618 static void trinity_set_ss_dividers(struct radeon_device *rdev,
619 u32 index, u32 divider)
622 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
624 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
625 value &= ~DS_SH_DIV_MASK;
626 value |= DS_SH_DIV(divider);
627 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
630 static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
632 struct trinity_power_info *pi = trinity_get_pi(rdev);
633 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
635 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
637 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
639 value |= VID(vid_7bit);
640 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
642 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
645 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
648 static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
649 u32 index, u32 gnb_slow)
652 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
654 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
655 value &= ~GNB_SLOW_MASK;
656 value |= GNB_SLOW(gnb_slow);
657 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
660 static void trinity_set_force_nbp_state(struct radeon_device *rdev,
661 u32 index, u32 force_nbp_state)
664 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
666 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
667 value &= ~FORCE_NBPS1_MASK;
668 value |= FORCE_NBPS1(force_nbp_state);
669 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
672 static void trinity_set_display_wm(struct radeon_device *rdev,
676 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
678 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
679 value &= ~DISPLAY_WM_MASK;
680 value |= DISPLAY_WM(wm);
681 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
684 static void trinity_set_vce_wm(struct radeon_device *rdev,
688 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
690 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
691 value &= ~VCE_WM_MASK;
693 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
696 static void trinity_set_at(struct radeon_device *rdev,
700 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
702 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
705 WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
708 static void trinity_program_power_level(struct radeon_device *rdev,
709 struct trinity_pl *pl, u32 index)
711 struct trinity_power_info *pi = trinity_get_pi(rdev);
713 if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
716 trinity_set_divider_value(rdev, index, pl->sclk);
717 trinity_set_vid(rdev, index, pl->vddc_index);
718 trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
719 trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
720 trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
721 trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
722 trinity_set_display_wm(rdev, index, pl->display_wm);
723 trinity_set_vce_wm(rdev, index, pl->vce_wm);
724 trinity_set_at(rdev, index, pi->at[index]);
727 static void trinity_power_level_enable_disable(struct radeon_device *rdev,
728 u32 index, bool enable)
731 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
733 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
734 value &= ~STATE_VALID_MASK;
736 value |= STATE_VALID(1);
737 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
740 static bool trinity_dpm_enabled(struct radeon_device *rdev)
742 if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
748 static void trinity_start_dpm(struct radeon_device *rdev)
750 u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
752 value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
753 value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
754 WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
756 WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
757 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
759 trinity_dpm_config(rdev, true);
762 static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
766 for (i = 0; i < rdev->usec_timeout; i++) {
767 if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
771 for (i = 0; i < rdev->usec_timeout; i++) {
772 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
776 for (i = 0; i < rdev->usec_timeout; i++) {
777 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
783 static void trinity_stop_dpm(struct radeon_device *rdev)
787 WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
789 sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
790 sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
791 WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
793 trinity_dpm_config(rdev, false);
796 static void trinity_start_am(struct radeon_device *rdev)
798 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
801 static void trinity_reset_am(struct radeon_device *rdev)
803 WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
804 ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
807 static void trinity_wait_for_level_0(struct radeon_device *rdev)
811 for (i = 0; i < rdev->usec_timeout; i++) {
812 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
818 static void trinity_enable_power_level_0(struct radeon_device *rdev)
820 trinity_power_level_enable_disable(rdev, 0, true);
823 static void trinity_force_level_0(struct radeon_device *rdev)
825 trinity_dpm_force_state(rdev, 0);
828 static void trinity_unforce_levels(struct radeon_device *rdev)
830 trinity_dpm_no_forced_level(rdev);
833 static void trinity_update_current_power_levels(struct radeon_device *rdev)
835 struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
836 struct trinity_power_info *pi = trinity_get_pi(rdev);
838 pi->current_ps = *new_ps;
841 static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev)
843 struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
844 struct trinity_ps *old_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
846 u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
848 for (i = 0; i < new_ps->num_levels; i++) {
849 trinity_program_power_level(rdev, &new_ps->levels[i], i);
850 trinity_power_level_enable_disable(rdev, i, true);
853 for (i = new_ps->num_levels; i < n_current_state_levels; i++)
854 trinity_power_level_enable_disable(rdev, i, false);
857 static void trinity_program_bootup_state(struct radeon_device *rdev)
859 struct trinity_power_info *pi = trinity_get_pi(rdev);
862 trinity_program_power_level(rdev, &pi->boot_pl, 0);
863 trinity_power_level_enable_disable(rdev, 0, true);
865 for (i = 1; i < 8; i++)
866 trinity_power_level_enable_disable(rdev, i, false);
869 static void trinity_program_ttt(struct radeon_device *rdev)
871 struct trinity_power_info *pi = trinity_get_pi(rdev);
872 u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
874 value &= ~(HT_MASK | LT_MASK);
875 value |= HT((pi->thermal_auto_throttling + 49) * 8);
876 value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
877 WREG32_SMC(SMU_SCLK_DPM_TTT, value);
880 static void trinity_enable_att(struct radeon_device *rdev)
882 u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
884 value &= ~SCLK_TT_EN_MASK;
885 value |= SCLK_TT_EN(1);
886 WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
889 static void trinity_program_sclk_dpm(struct radeon_device *rdev)
892 u32 tp = RREG32_SMC(PM_TP);
894 u32 xclk = sumo_get_xclk(rdev);
897 r600_calculate_u_and_p(400, xclk, 16, &p, &u);
899 ni = (p + tp - 1) / tp;
901 value = RREG32_SMC(PM_I_CNTL_1);
902 value &= ~SCLK_DPM_MASK;
903 value |= SCLK_DPM(ni);
904 WREG32_SMC(PM_I_CNTL_1, value);
907 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
908 int min_temp, int max_temp)
910 int low_temp = 0 * 1000;
911 int high_temp = 255 * 1000;
913 if (low_temp < min_temp)
915 if (high_temp > max_temp)
916 high_temp = max_temp;
917 if (high_temp < low_temp) {
918 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
922 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
923 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
925 rdev->pm.dpm.thermal.min_temp = low_temp;
926 rdev->pm.dpm.thermal.max_temp = high_temp;
931 int trinity_dpm_enable(struct radeon_device *rdev)
933 struct trinity_power_info *pi = trinity_get_pi(rdev);
935 trinity_acquire_mutex(rdev);
937 if (trinity_dpm_enabled(rdev)) {
938 trinity_release_mutex(rdev);
942 trinity_enable_clock_power_gating(rdev);
943 trinity_program_bootup_state(rdev);
944 sumo_program_vc(rdev, 0x00C00033);
945 trinity_start_am(rdev);
946 if (pi->enable_auto_thermal_throttling) {
947 trinity_program_ttt(rdev);
948 trinity_enable_att(rdev);
950 trinity_program_sclk_dpm(rdev);
951 trinity_start_dpm(rdev);
952 trinity_wait_for_dpm_enabled(rdev);
953 trinity_release_mutex(rdev);
955 if (rdev->irq.installed &&
956 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
957 trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
958 rdev->irq.dpm_thermal = true;
959 radeon_irq_set(rdev);
965 void trinity_dpm_disable(struct radeon_device *rdev)
967 trinity_acquire_mutex(rdev);
968 if (!trinity_dpm_enabled(rdev)) {
969 trinity_release_mutex(rdev);
972 trinity_disable_clock_power_gating(rdev);
974 trinity_wait_for_level_0(rdev);
975 trinity_stop_dpm(rdev);
976 trinity_reset_am(rdev);
977 trinity_release_mutex(rdev);
979 if (rdev->irq.installed &&
980 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
981 rdev->irq.dpm_thermal = false;
982 radeon_irq_set(rdev);
986 static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
988 struct trinity_power_info *pi = trinity_get_pi(rdev);
991 (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
994 static void trinity_setup_nbp_sim(struct radeon_device *rdev)
996 struct trinity_power_info *pi = trinity_get_pi(rdev);
997 struct trinity_ps *new_ps = trinity_get_ps(rdev->pm.dpm.requested_ps);
1000 if (pi->sys_info.nb_dpm_enable) {
1001 nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
1002 nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
1003 nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
1004 Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
1005 DpmXNbPsLo(new_ps->DpmXNbPsLo) |
1006 DpmXNbPsHi(new_ps->DpmXNbPsHi));
1007 WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
1011 int trinity_dpm_set_power_state(struct radeon_device *rdev)
1013 struct trinity_power_info *pi = trinity_get_pi(rdev);
1015 trinity_apply_state_adjust_rules(rdev);
1016 trinity_update_current_power_levels(rdev);
1018 trinity_acquire_mutex(rdev);
1019 if (pi->enable_dpm) {
1020 trinity_enable_power_level_0(rdev);
1021 trinity_force_level_0(rdev);
1022 trinity_wait_for_level_0(rdev);
1023 trinity_setup_nbp_sim(rdev);
1024 trinity_program_power_levels_0_to_n(rdev);
1025 trinity_force_level_0(rdev);
1026 trinity_unforce_levels(rdev);
1028 trinity_release_mutex(rdev);
1033 void trinity_dpm_setup_asic(struct radeon_device *rdev)
1035 trinity_acquire_mutex(rdev);
1036 sumo_program_sstp(rdev);
1037 sumo_take_smu_control(rdev, true);
1038 trinity_get_min_sclk_divider(rdev);
1039 trinity_release_mutex(rdev);
1042 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1044 struct trinity_power_info *pi = trinity_get_pi(rdev);
1046 trinity_acquire_mutex(rdev);
1047 if (pi->enable_dpm) {
1048 trinity_enable_power_level_0(rdev);
1049 trinity_force_level_0(rdev);
1050 trinity_wait_for_level_0(rdev);
1051 trinity_program_bootup_state(rdev);
1052 trinity_force_level_0(rdev);
1053 trinity_unforce_levels(rdev);
1055 trinity_release_mutex(rdev);
1058 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1061 struct trinity_power_info *pi = trinity_get_pi(rdev);
1062 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1063 u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1064 u32 step = (svi_mode == 0) ? 1250 : 625;
1065 u32 delta = vid_7bit * step + 50;
1070 return (155000 - delta) / 100;
1073 static void trinity_patch_boot_state(struct radeon_device *rdev,
1074 struct trinity_ps *ps)
1076 struct trinity_power_info *pi = trinity_get_pi(rdev);
1081 ps->levels[0] = pi->boot_pl;
1084 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1091 static void trinity_construct_boot_state(struct radeon_device *rdev)
1093 struct trinity_power_info *pi = trinity_get_pi(rdev);
1095 pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1096 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1097 pi->boot_pl.ds_divider_index = 0;
1098 pi->boot_pl.ss_divider_index = 0;
1099 pi->boot_pl.allow_gnb_slow = 1;
1100 pi->boot_pl.force_nbp_state = 0;
1101 pi->boot_pl.display_wm = 0;
1102 pi->boot_pl.vce_wm = 0;
1103 pi->current_ps.num_levels = 1;
1104 pi->current_ps.levels[0] = pi->boot_pl;
1107 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1108 u32 sclk, u32 min_sclk_in_sr)
1110 struct trinity_power_info *pi = trinity_get_pi(rdev);
1113 u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1114 min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1119 if (!pi->enable_sclk_ds)
1122 for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
1123 temp = sclk / sumo_get_sleep_divider_from_id(i);
1124 if (temp >= min || i == 0)
1131 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1134 struct trinity_power_info *pi = trinity_get_pi(rdev);
1137 for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1138 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1139 return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1142 if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1143 DRM_ERROR("engine clock out of range!");
1148 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1149 struct trinity_ps *ps,
1150 struct trinity_ps *current_ps)
1152 struct trinity_power_info *pi = trinity_get_pi(rdev);
1153 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1156 u32 current_index = 0;
1159 current_vddc = current_ps->levels[current_index].vddc_index;
1160 current_sclk = current_ps->levels[current_index].sclk;
1162 current_vddc = pi->boot_pl.vddc_index;
1163 current_sclk = pi->boot_pl.sclk;
1166 ps->levels[0].vddc_index = current_vddc;
1168 if (ps->levels[0].sclk > current_sclk)
1169 ps->levels[0].sclk = current_sclk;
1171 ps->levels[0].ds_divider_index =
1172 trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1173 ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1174 ps->levels[0].allow_gnb_slow = 1;
1175 ps->levels[0].force_nbp_state = 0;
1176 ps->levels[0].display_wm = 0;
1177 ps->levels[0].vce_wm =
1178 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1181 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1182 struct trinity_ps *ps, u32 index)
1184 if (ps == NULL || ps->num_levels <= 1)
1186 else if (ps->num_levels == 2) {
1194 else if (ps->levels[index].sclk < 30000)
1201 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev)
1203 struct radeon_ps *rps = rdev->pm.dpm.requested_ps;
1204 struct trinity_ps *ps = trinity_get_ps(rps);
1205 struct trinity_ps *current_ps = trinity_get_ps(rdev->pm.dpm.current_ps);
1206 struct trinity_power_info *pi = trinity_get_pi(rdev);
1207 u32 min_voltage = 0; /* ??? */
1208 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1209 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1212 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1214 if (rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1215 return trinity_patch_thermal_state(rdev, ps, current_ps);
1217 for (i = 0; i < ps->num_levels; i++) {
1218 if (ps->levels[i].vddc_index < min_voltage)
1219 ps->levels[i].vddc_index = min_voltage;
1221 if (ps->levels[i].sclk < min_sclk)
1222 ps->levels[i].sclk =
1223 trinity_get_valid_engine_clock(rdev, min_sclk);
1225 ps->levels[i].ds_divider_index =
1226 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1228 ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1230 ps->levels[i].allow_gnb_slow = 1;
1231 ps->levels[i].force_nbp_state = 0;
1232 ps->levels[i].display_wm =
1233 trinity_calculate_display_wm(rdev, ps, i);
1234 ps->levels[i].vce_wm =
1235 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1238 if ((rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1239 ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1240 ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1242 if (pi->sys_info.nb_dpm_enable) {
1243 ps->Dpm0PgNbPsLo = 0x1;
1244 ps->Dpm0PgNbPsHi = 0x0;
1245 ps->DpmXNbPsLo = 0x2;
1246 ps->DpmXNbPsHi = 0x1;
1248 if ((rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1249 ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1250 force_high = ((rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1251 ((rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1252 (pi->sys_info.uma_channel_number == 1)));
1253 force_high = (num_active_displays >= 3) || force_high;
1254 ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1255 ps->Dpm0PgNbPsHi = 0x1;
1256 ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1257 ps->DpmXNbPsHi = 0x2;
1258 ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1263 static void trinity_cleanup_asic(struct radeon_device *rdev)
1265 sumo_take_smu_control(rdev, false);
1269 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1271 struct trinity_power_info *pi = trinity_get_pi(rdev);
1273 if (pi->voltage_drop_in_dce)
1274 trinity_dce_enable_voltage_adjustment(rdev, false);
1278 static void trinity_add_dccac_value(struct radeon_device *rdev)
1280 u32 gpu_cac_avrg_cntl_window_size;
1281 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1282 u64 disp_clk = rdev->clock.default_dispclk / 100;
1285 gpu_cac_avrg_cntl_window_size =
1286 (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1288 dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1289 (32 - gpu_cac_avrg_cntl_window_size));
1291 WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1294 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1296 struct trinity_power_info *pi = trinity_get_pi(rdev);
1298 if (pi->voltage_drop_in_dce)
1299 trinity_dce_enable_voltage_adjustment(rdev, true);
1300 trinity_add_dccac_value(rdev);
1304 struct _ATOM_POWERPLAY_INFO info;
1305 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1306 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1307 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1308 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1309 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1312 union pplib_clock_info {
1313 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1314 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1315 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1316 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1319 union pplib_power_state {
1320 struct _ATOM_PPLIB_STATE v1;
1321 struct _ATOM_PPLIB_STATE_V2 v2;
1324 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1325 struct radeon_ps *rps,
1326 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1329 struct trinity_ps *ps = trinity_get_ps(rps);
1331 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1332 rps->class = le16_to_cpu(non_clock_info->usClassification);
1333 rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1335 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1336 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1337 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1343 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1344 rdev->pm.dpm.boot_ps = rps;
1345 trinity_patch_boot_state(rdev, ps);
1347 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1348 rdev->pm.dpm.uvd_ps = rps;
1351 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1352 struct radeon_ps *rps, int index,
1353 union pplib_clock_info *clock_info)
1355 struct trinity_power_info *pi = trinity_get_pi(rdev);
1356 struct trinity_ps *ps = trinity_get_ps(rps);
1357 struct trinity_pl *pl = &ps->levels[index];
1360 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1361 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1363 pl->vddc_index = clock_info->sumo.vddcIndex;
1365 ps->num_levels = index + 1;
1367 if (pi->enable_sclk_ds) {
1368 pl->ds_divider_index = 5;
1369 pl->ss_divider_index = 5;
1373 static int trinity_parse_power_table(struct radeon_device *rdev)
1375 struct radeon_mode_info *mode_info = &rdev->mode_info;
1376 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1377 union pplib_power_state *power_state;
1378 int i, j, k, non_clock_array_index, clock_array_index;
1379 union pplib_clock_info *clock_info;
1380 struct _StateArray *state_array;
1381 struct _ClockInfoArray *clock_info_array;
1382 struct _NonClockInfoArray *non_clock_info_array;
1383 union power_info *power_info;
1384 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1387 u8 *power_state_offset;
1390 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1391 &frev, &crev, &data_offset))
1393 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1395 state_array = (struct _StateArray *)
1396 (mode_info->atom_context->bios + data_offset +
1397 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1398 clock_info_array = (struct _ClockInfoArray *)
1399 (mode_info->atom_context->bios + data_offset +
1400 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1401 non_clock_info_array = (struct _NonClockInfoArray *)
1402 (mode_info->atom_context->bios + data_offset +
1403 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1405 rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
1406 state_array->ucNumEntries, GFP_KERNEL);
1407 if (!rdev->pm.dpm.ps)
1409 power_state_offset = (u8 *)state_array->states;
1410 rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
1411 rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
1412 rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
1413 for (i = 0; i < state_array->ucNumEntries; i++) {
1414 power_state = (union pplib_power_state *)power_state_offset;
1415 non_clock_array_index = power_state->v2.nonClockInfoIndex;
1416 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1417 &non_clock_info_array->nonClockInfo[non_clock_array_index];
1418 if (!rdev->pm.power_state[i].clock_info)
1420 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1422 kfree(rdev->pm.dpm.ps);
1425 rdev->pm.dpm.ps[i].ps_priv = ps;
1427 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1428 clock_array_index = power_state->v2.clockInfoIndex[j];
1429 if (clock_array_index >= clock_info_array->ucNumEntries)
1431 if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1433 clock_info = (union pplib_clock_info *)
1434 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
1435 trinity_parse_pplib_clock_info(rdev,
1436 &rdev->pm.dpm.ps[i], k,
1440 trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1442 non_clock_info_array->ucEntrySize);
1443 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1445 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1450 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1451 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1452 struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1453 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1454 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1457 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1459 struct trinity_power_info *pi = trinity_get_pi(rdev);
1460 struct radeon_mode_info *mode_info = &rdev->mode_info;
1461 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1462 union igp_info *igp_info;
1467 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1468 &frev, &crev, &data_offset)) {
1469 igp_info = (union igp_info *)(mode_info->atom_context->bios +
1473 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1476 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1477 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1478 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1479 pi->sys_info.bootup_nb_voltage_index =
1480 le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1481 if (igp_info->info_7.ucHtcTmpLmt == 0)
1482 pi->sys_info.htc_tmp_lmt = 203;
1484 pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1485 if (igp_info->info_7.ucHtcHystLmt == 0)
1486 pi->sys_info.htc_hyst_lmt = 5;
1488 pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1489 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1490 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1493 if (pi->enable_nbps_policy)
1494 pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1496 pi->sys_info.nb_dpm_enable = 0;
1498 for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1499 pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1500 pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1503 pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1504 pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1505 pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1506 pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1508 if (!pi->sys_info.nb_dpm_enable) {
1509 for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1510 pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1511 pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1512 pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1516 pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1518 sumo_construct_sclk_voltage_mapping_table(rdev,
1519 &pi->sys_info.sclk_voltage_mapping_table,
1520 igp_info->info_7.sAvail_SCLK);
1521 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1522 igp_info->info_7.sAvail_SCLK);
1528 int trinity_dpm_init(struct radeon_device *rdev)
1530 struct trinity_power_info *pi;
1533 pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1536 rdev->pm.dpm.priv = pi;
1538 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1539 pi->at[i] = TRINITY_AT_DFLT;
1541 pi->enable_nbps_policy = true;
1542 pi->enable_sclk_ds = true;
1543 pi->enable_gfx_power_gating = true;
1544 pi->enable_gfx_clock_gating = true;
1545 pi->enable_mg_clock_gating = true;
1546 pi->enable_gfx_dynamic_mgpg = true; /* ??? */
1547 pi->override_dynamic_mgpg = true;
1548 pi->enable_auto_thermal_throttling = true;
1549 pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1551 ret = trinity_parse_sys_info_table(rdev);
1555 trinity_construct_boot_state(rdev);
1557 ret = trinity_parse_power_table(rdev);
1561 pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1562 pi->enable_dpm = true;
1567 void trinity_dpm_print_power_state(struct radeon_device *rdev,
1568 struct radeon_ps *rps)
1571 struct trinity_ps *ps = trinity_get_ps(rps);
1573 r600_dpm_print_class_info(rps->class, rps->class2);
1574 r600_dpm_print_cap_info(rps->caps);
1575 printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1576 for (i = 0; i < ps->num_levels; i++) {
1577 struct trinity_pl *pl = &ps->levels[i];
1578 printk("\t\tpower level %d sclk: %u vddc: %u\n",
1580 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1582 r600_dpm_print_ps_status(rdev, rps);
1585 void trinity_dpm_fini(struct radeon_device *rdev)
1589 trinity_cleanup_asic(rdev); /* ??? */
1591 for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1592 kfree(rdev->pm.dpm.ps[i].ps_priv);
1594 kfree(rdev->pm.dpm.ps);
1595 kfree(rdev->pm.dpm.priv);
1598 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
1600 struct trinity_ps *requested_state = trinity_get_ps(rdev->pm.dpm.requested_ps);
1603 return requested_state->levels[0].sclk;
1605 return requested_state->levels[requested_state->num_levels - 1].sclk;
1608 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
1610 struct trinity_power_info *pi = trinity_get_pi(rdev);
1612 return pi->sys_info.bootup_uma_clk;