1 /*
2  * Copyright 2012 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 #include <linux/seq_file.h>
25 
26 #include <drm/drm_pci.h>
27 
28 #include "r600_dpm.h"
29 #include "radeon.h"
30 #include "radeon_asic.h"
31 #include "trinity_dpm.h"
32 #include "trinityd.h"
33 
34 #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
35 #define TRINITY_MINIMUM_ENGINE_CLOCK 800
36 #define SCLK_MIN_DIV_INTV_SHIFT     12
37 #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
38 
39 #ifndef TRINITY_MGCG_SEQUENCE
40 #define TRINITY_MGCG_SEQUENCE  100
41 
42 static const u32 trinity_mgcg_shls_default[] =
43 {
44 	/* Register, Value, Mask */
45 	0x0000802c, 0xc0000000, 0xffffffff,
46 	0x00003fc4, 0xc0000000, 0xffffffff,
47 	0x00005448, 0x00000100, 0xffffffff,
48 	0x000055e4, 0x00000100, 0xffffffff,
49 	0x0000160c, 0x00000100, 0xffffffff,
50 	0x00008984, 0x06000100, 0xffffffff,
51 	0x0000c164, 0x00000100, 0xffffffff,
52 	0x00008a18, 0x00000100, 0xffffffff,
53 	0x0000897c, 0x06000100, 0xffffffff,
54 	0x00008b28, 0x00000100, 0xffffffff,
55 	0x00009144, 0x00800200, 0xffffffff,
56 	0x00009a60, 0x00000100, 0xffffffff,
57 	0x00009868, 0x00000100, 0xffffffff,
58 	0x00008d58, 0x00000100, 0xffffffff,
59 	0x00009510, 0x00000100, 0xffffffff,
60 	0x0000949c, 0x00000100, 0xffffffff,
61 	0x00009654, 0x00000100, 0xffffffff,
62 	0x00009030, 0x00000100, 0xffffffff,
63 	0x00009034, 0x00000100, 0xffffffff,
64 	0x00009038, 0x00000100, 0xffffffff,
65 	0x0000903c, 0x00000100, 0xffffffff,
66 	0x00009040, 0x00000100, 0xffffffff,
67 	0x0000a200, 0x00000100, 0xffffffff,
68 	0x0000a204, 0x00000100, 0xffffffff,
69 	0x0000a208, 0x00000100, 0xffffffff,
70 	0x0000a20c, 0x00000100, 0xffffffff,
71 	0x00009744, 0x00000100, 0xffffffff,
72 	0x00003f80, 0x00000100, 0xffffffff,
73 	0x0000a210, 0x00000100, 0xffffffff,
74 	0x0000a214, 0x00000100, 0xffffffff,
75 	0x000004d8, 0x00000100, 0xffffffff,
76 	0x00009664, 0x00000100, 0xffffffff,
77 	0x00009698, 0x00000100, 0xffffffff,
78 	0x000004d4, 0x00000200, 0xffffffff,
79 	0x000004d0, 0x00000000, 0xffffffff,
80 	0x000030cc, 0x00000104, 0xffffffff,
81 	0x0000d0c0, 0x00000100, 0xffffffff,
82 	0x0000d8c0, 0x00000100, 0xffffffff,
83 	0x0000951c, 0x00010000, 0xffffffff,
84 	0x00009160, 0x00030002, 0xffffffff,
85 	0x00009164, 0x00050004, 0xffffffff,
86 	0x00009168, 0x00070006, 0xffffffff,
87 	0x00009178, 0x00070000, 0xffffffff,
88 	0x0000917c, 0x00030002, 0xffffffff,
89 	0x00009180, 0x00050004, 0xffffffff,
90 	0x0000918c, 0x00010006, 0xffffffff,
91 	0x00009190, 0x00090008, 0xffffffff,
92 	0x00009194, 0x00070000, 0xffffffff,
93 	0x00009198, 0x00030002, 0xffffffff,
94 	0x0000919c, 0x00050004, 0xffffffff,
95 	0x000091a8, 0x00010006, 0xffffffff,
96 	0x000091ac, 0x00090008, 0xffffffff,
97 	0x000091b0, 0x00070000, 0xffffffff,
98 	0x000091b4, 0x00030002, 0xffffffff,
99 	0x000091b8, 0x00050004, 0xffffffff,
100 	0x000091c4, 0x00010006, 0xffffffff,
101 	0x000091c8, 0x00090008, 0xffffffff,
102 	0x000091cc, 0x00070000, 0xffffffff,
103 	0x000091d0, 0x00030002, 0xffffffff,
104 	0x000091d4, 0x00050004, 0xffffffff,
105 	0x000091e0, 0x00010006, 0xffffffff,
106 	0x000091e4, 0x00090008, 0xffffffff,
107 	0x000091e8, 0x00000000, 0xffffffff,
108 	0x000091ec, 0x00070000, 0xffffffff,
109 	0x000091f0, 0x00030002, 0xffffffff,
110 	0x000091f4, 0x00050004, 0xffffffff,
111 	0x00009200, 0x00010006, 0xffffffff,
112 	0x00009204, 0x00090008, 0xffffffff,
113 	0x00009208, 0x00070000, 0xffffffff,
114 	0x0000920c, 0x00030002, 0xffffffff,
115 	0x00009210, 0x00050004, 0xffffffff,
116 	0x0000921c, 0x00010006, 0xffffffff,
117 	0x00009220, 0x00090008, 0xffffffff,
118 	0x00009294, 0x00000000, 0xffffffff
119 };
120 
121 static const u32 trinity_mgcg_shls_enable[] =
122 {
123 	/* Register, Value, Mask */
124 	0x0000802c, 0xc0000000, 0xffffffff,
125 	0x000008f8, 0x00000000, 0xffffffff,
126 	0x000008fc, 0x00000000, 0x000133FF,
127 	0x000008f8, 0x00000001, 0xffffffff,
128 	0x000008fc, 0x00000000, 0xE00B03FC,
129 	0x00009150, 0x96944200, 0xffffffff
130 };
131 
132 static const u32 trinity_mgcg_shls_disable[] =
133 {
134 	/* Register, Value, Mask */
135 	0x0000802c, 0xc0000000, 0xffffffff,
136 	0x00009150, 0x00600000, 0xffffffff,
137 	0x000008f8, 0x00000000, 0xffffffff,
138 	0x000008fc, 0xffffffff, 0x000133FF,
139 	0x000008f8, 0x00000001, 0xffffffff,
140 	0x000008fc, 0xffffffff, 0xE00B03FC
141 };
142 #endif
143 
144 #ifndef TRINITY_SYSLS_SEQUENCE
145 #define TRINITY_SYSLS_SEQUENCE  100
146 
147 static const u32 trinity_sysls_default[] =
148 {
149 	/* Register, Value, Mask */
150 	0x000055e8, 0x00000000, 0xffffffff,
151 	0x0000d0bc, 0x00000000, 0xffffffff,
152 	0x0000d8bc, 0x00000000, 0xffffffff,
153 	0x000015c0, 0x000c1401, 0xffffffff,
154 	0x0000264c, 0x000c0400, 0xffffffff,
155 	0x00002648, 0x000c0400, 0xffffffff,
156 	0x00002650, 0x000c0400, 0xffffffff,
157 	0x000020b8, 0x000c0400, 0xffffffff,
158 	0x000020bc, 0x000c0400, 0xffffffff,
159 	0x000020c0, 0x000c0c80, 0xffffffff,
160 	0x0000f4a0, 0x000000c0, 0xffffffff,
161 	0x0000f4a4, 0x00680fff, 0xffffffff,
162 	0x00002f50, 0x00000404, 0xffffffff,
163 	0x000004c8, 0x00000001, 0xffffffff,
164 	0x0000641c, 0x00000000, 0xffffffff,
165 	0x00000c7c, 0x00000000, 0xffffffff,
166 	0x00006dfc, 0x00000000, 0xffffffff
167 };
168 
169 static const u32 trinity_sysls_disable[] =
170 {
171 	/* Register, Value, Mask */
172 	0x0000d0c0, 0x00000000, 0xffffffff,
173 	0x0000d8c0, 0x00000000, 0xffffffff,
174 	0x000055e8, 0x00000000, 0xffffffff,
175 	0x0000d0bc, 0x00000000, 0xffffffff,
176 	0x0000d8bc, 0x00000000, 0xffffffff,
177 	0x000015c0, 0x00041401, 0xffffffff,
178 	0x0000264c, 0x00040400, 0xffffffff,
179 	0x00002648, 0x00040400, 0xffffffff,
180 	0x00002650, 0x00040400, 0xffffffff,
181 	0x000020b8, 0x00040400, 0xffffffff,
182 	0x000020bc, 0x00040400, 0xffffffff,
183 	0x000020c0, 0x00040c80, 0xffffffff,
184 	0x0000f4a0, 0x000000c0, 0xffffffff,
185 	0x0000f4a4, 0x00680000, 0xffffffff,
186 	0x00002f50, 0x00000404, 0xffffffff,
187 	0x000004c8, 0x00000001, 0xffffffff,
188 	0x0000641c, 0x00007ffd, 0xffffffff,
189 	0x00000c7c, 0x0000ff00, 0xffffffff,
190 	0x00006dfc, 0x0000007f, 0xffffffff
191 };
192 
193 static const u32 trinity_sysls_enable[] =
194 {
195 	/* Register, Value, Mask */
196 	0x000055e8, 0x00000001, 0xffffffff,
197 	0x0000d0bc, 0x00000100, 0xffffffff,
198 	0x0000d8bc, 0x00000100, 0xffffffff,
199 	0x000015c0, 0x000c1401, 0xffffffff,
200 	0x0000264c, 0x000c0400, 0xffffffff,
201 	0x00002648, 0x000c0400, 0xffffffff,
202 	0x00002650, 0x000c0400, 0xffffffff,
203 	0x000020b8, 0x000c0400, 0xffffffff,
204 	0x000020bc, 0x000c0400, 0xffffffff,
205 	0x000020c0, 0x000c0c80, 0xffffffff,
206 	0x0000f4a0, 0x000000c0, 0xffffffff,
207 	0x0000f4a4, 0x00680fff, 0xffffffff,
208 	0x00002f50, 0x00000903, 0xffffffff,
209 	0x000004c8, 0x00000000, 0xffffffff,
210 	0x0000641c, 0x00000000, 0xffffffff,
211 	0x00000c7c, 0x00000000, 0xffffffff,
212 	0x00006dfc, 0x00000000, 0xffffffff
213 };
214 #endif
215 
216 static const u32 trinity_override_mgpg_sequences[] =
217 {
218 	/* Register, Value */
219 	0x00000200, 0xE030032C,
220 	0x00000204, 0x00000FFF,
221 	0x00000200, 0xE0300058,
222 	0x00000204, 0x00030301,
223 	0x00000200, 0xE0300054,
224 	0x00000204, 0x500010FF,
225 	0x00000200, 0xE0300074,
226 	0x00000204, 0x00030301,
227 	0x00000200, 0xE0300070,
228 	0x00000204, 0x500010FF,
229 	0x00000200, 0xE0300090,
230 	0x00000204, 0x00030301,
231 	0x00000200, 0xE030008C,
232 	0x00000204, 0x500010FF,
233 	0x00000200, 0xE03000AC,
234 	0x00000204, 0x00030301,
235 	0x00000200, 0xE03000A8,
236 	0x00000204, 0x500010FF,
237 	0x00000200, 0xE03000C8,
238 	0x00000204, 0x00030301,
239 	0x00000200, 0xE03000C4,
240 	0x00000204, 0x500010FF,
241 	0x00000200, 0xE03000E4,
242 	0x00000204, 0x00030301,
243 	0x00000200, 0xE03000E0,
244 	0x00000204, 0x500010FF,
245 	0x00000200, 0xE0300100,
246 	0x00000204, 0x00030301,
247 	0x00000200, 0xE03000FC,
248 	0x00000204, 0x500010FF,
249 	0x00000200, 0xE0300058,
250 	0x00000204, 0x00030303,
251 	0x00000200, 0xE0300054,
252 	0x00000204, 0x600010FF,
253 	0x00000200, 0xE0300074,
254 	0x00000204, 0x00030303,
255 	0x00000200, 0xE0300070,
256 	0x00000204, 0x600010FF,
257 	0x00000200, 0xE0300090,
258 	0x00000204, 0x00030303,
259 	0x00000200, 0xE030008C,
260 	0x00000204, 0x600010FF,
261 	0x00000200, 0xE03000AC,
262 	0x00000204, 0x00030303,
263 	0x00000200, 0xE03000A8,
264 	0x00000204, 0x600010FF,
265 	0x00000200, 0xE03000C8,
266 	0x00000204, 0x00030303,
267 	0x00000200, 0xE03000C4,
268 	0x00000204, 0x600010FF,
269 	0x00000200, 0xE03000E4,
270 	0x00000204, 0x00030303,
271 	0x00000200, 0xE03000E0,
272 	0x00000204, 0x600010FF,
273 	0x00000200, 0xE0300100,
274 	0x00000204, 0x00030303,
275 	0x00000200, 0xE03000FC,
276 	0x00000204, 0x600010FF,
277 	0x00000200, 0xE0300058,
278 	0x00000204, 0x00030303,
279 	0x00000200, 0xE0300054,
280 	0x00000204, 0x700010FF,
281 	0x00000200, 0xE0300074,
282 	0x00000204, 0x00030303,
283 	0x00000200, 0xE0300070,
284 	0x00000204, 0x700010FF,
285 	0x00000200, 0xE0300090,
286 	0x00000204, 0x00030303,
287 	0x00000200, 0xE030008C,
288 	0x00000204, 0x700010FF,
289 	0x00000200, 0xE03000AC,
290 	0x00000204, 0x00030303,
291 	0x00000200, 0xE03000A8,
292 	0x00000204, 0x700010FF,
293 	0x00000200, 0xE03000C8,
294 	0x00000204, 0x00030303,
295 	0x00000200, 0xE03000C4,
296 	0x00000204, 0x700010FF,
297 	0x00000200, 0xE03000E4,
298 	0x00000204, 0x00030303,
299 	0x00000200, 0xE03000E0,
300 	0x00000204, 0x700010FF,
301 	0x00000200, 0xE0300100,
302 	0x00000204, 0x00030303,
303 	0x00000200, 0xE03000FC,
304 	0x00000204, 0x700010FF,
305 	0x00000200, 0xE0300058,
306 	0x00000204, 0x00010303,
307 	0x00000200, 0xE0300054,
308 	0x00000204, 0x800010FF,
309 	0x00000200, 0xE0300074,
310 	0x00000204, 0x00010303,
311 	0x00000200, 0xE0300070,
312 	0x00000204, 0x800010FF,
313 	0x00000200, 0xE0300090,
314 	0x00000204, 0x00010303,
315 	0x00000200, 0xE030008C,
316 	0x00000204, 0x800010FF,
317 	0x00000200, 0xE03000AC,
318 	0x00000204, 0x00010303,
319 	0x00000200, 0xE03000A8,
320 	0x00000204, 0x800010FF,
321 	0x00000200, 0xE03000C4,
322 	0x00000204, 0x800010FF,
323 	0x00000200, 0xE03000C8,
324 	0x00000204, 0x00010303,
325 	0x00000200, 0xE03000E4,
326 	0x00000204, 0x00010303,
327 	0x00000200, 0xE03000E0,
328 	0x00000204, 0x800010FF,
329 	0x00000200, 0xE0300100,
330 	0x00000204, 0x00010303,
331 	0x00000200, 0xE03000FC,
332 	0x00000204, 0x800010FF,
333 	0x00000200, 0x0001f198,
334 	0x00000204, 0x0003ffff,
335 	0x00000200, 0x0001f19C,
336 	0x00000204, 0x3fffffff,
337 	0x00000200, 0xE030032C,
338 	0x00000204, 0x00000000,
339 };
340 
341 extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
342 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
343 						   const u32 *seq, u32 count);
344 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
345 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
346 					     struct radeon_ps *new_rps,
347 					     struct radeon_ps *old_rps);
348 
349 static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
350 {
351 	struct trinity_ps *ps = rps->ps_priv;
352 
353 	return ps;
354 }
355 
356 static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
357 {
358 	struct trinity_power_info *pi = rdev->pm.dpm.priv;
359 
360 	return pi;
361 }
362 
363 static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
364 {
365 	struct trinity_power_info *pi = trinity_get_pi(rdev);
366 	u32 p, u;
367 	u32 value;
368 	struct atom_clock_dividers dividers;
369 	u32 xclk = radeon_get_xclk(rdev);
370 	u32 sssd = 1;
371 	int ret;
372 	u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
373 
374 	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
375 					     25000, false, &dividers);
376 	if (ret)
377 		return;
378 
379 	value = RREG32_SMC(GFX_POWER_GATING_CNTL);
380 	value &= ~(SSSD_MASK | PDS_DIV_MASK);
381 	if (sssd)
382 		value |= SSSD(1);
383 	value |= PDS_DIV(dividers.post_div);
384 	WREG32_SMC(GFX_POWER_GATING_CNTL, value);
385 
386 	r600_calculate_u_and_p(500, xclk, 16, &p, &u);
387 
388 	WREG32(CG_PG_CTRL, SP(p) | SU(u));
389 
390 	WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
391 
392 	/* XXX double check hw_rev */
393 	if (pi->override_dynamic_mgpg && (hw_rev == 0))
394 		trinity_override_dynamic_mg_powergating(rdev);
395 
396 }
397 
398 #define CGCG_CGTT_LOCAL0_MASK       0xFFFF33FF
399 #define CGCG_CGTT_LOCAL1_MASK       0xFFFB0FFE
400 #define CGTS_SM_CTRL_REG_DISABLE    0x00600000
401 #define CGTS_SM_CTRL_REG_ENABLE     0x96944200
402 
403 static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
404 					  bool enable)
405 {
406 	u32 local0;
407 	u32 local1;
408 
409 	if (enable) {
410 		local0 = RREG32_CG(CG_CGTT_LOCAL_0);
411 		local1 = RREG32_CG(CG_CGTT_LOCAL_1);
412 
413 		WREG32_CG(CG_CGTT_LOCAL_0,
414 			  (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
415 		WREG32_CG(CG_CGTT_LOCAL_1,
416 			  (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
417 
418 		WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
419 	} else {
420 		WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
421 
422 		local0 = RREG32_CG(CG_CGTT_LOCAL_0);
423 		local1 = RREG32_CG(CG_CGTT_LOCAL_1);
424 
425 		WREG32_CG(CG_CGTT_LOCAL_0,
426 			  CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
427 		WREG32_CG(CG_CGTT_LOCAL_1,
428 			  CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
429 	}
430 }
431 
432 static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
433 {
434 	u32 count;
435 	const u32 *seq = NULL;
436 
437 	seq = &trinity_mgcg_shls_default[0];
438 	count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
439 
440 	trinity_program_clk_gating_hw_sequence(rdev, seq, count);
441 }
442 
443 static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
444 					   bool enable)
445 {
446 	if (enable) {
447 		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
448 	} else {
449 		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
450 		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
451 		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
452 		RREG32(GB_ADDR_CONFIG);
453 	}
454 }
455 
456 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
457 						   const u32 *seq, u32 count)
458 {
459 	u32 i, length = count * 3;
460 
461 	for (i = 0; i < length; i += 3)
462 		WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
463 }
464 
465 static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
466 						    const u32 *seq, u32 count)
467 {
468 	u32  i, length = count * 2;
469 
470 	for (i = 0; i < length; i += 2)
471 		WREG32(seq[i], seq[i+1]);
472 
473 }
474 
475 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
476 {
477 	u32 count;
478 	const u32 *seq = NULL;
479 
480 	seq = &trinity_override_mgpg_sequences[0];
481 	count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
482 
483 	trinity_program_override_mgpg_sequences(rdev, seq, count);
484 }
485 
486 static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
487 					  bool enable)
488 {
489 	u32 count;
490 	const u32 *seq = NULL;
491 
492 	if (enable) {
493 		seq = &trinity_sysls_enable[0];
494 		count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
495 	} else {
496 		seq = &trinity_sysls_disable[0];
497 		count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
498 	}
499 
500 	trinity_program_clk_gating_hw_sequence(rdev, seq, count);
501 }
502 
503 static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
504 					   bool enable)
505 {
506 	if (enable) {
507 		if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
508 			WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
509 
510 		WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
511 	} else {
512 		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
513 		RREG32(GB_ADDR_CONFIG);
514 	}
515 }
516 
517 static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
518 					    bool enable)
519 {
520 	u32 value;
521 
522 	if (enable) {
523 		value = RREG32_SMC(PM_I_CNTL_1);
524 		value &= ~DS_PG_CNTL_MASK;
525 		value |= DS_PG_CNTL(1);
526 		WREG32_SMC(PM_I_CNTL_1, value);
527 
528 		value = RREG32_SMC(SMU_S_PG_CNTL);
529 		value &= ~DS_PG_EN_MASK;
530 		value |= DS_PG_EN(1);
531 		WREG32_SMC(SMU_S_PG_CNTL, value);
532 	} else {
533 		value = RREG32_SMC(SMU_S_PG_CNTL);
534 		value &= ~DS_PG_EN_MASK;
535 		WREG32_SMC(SMU_S_PG_CNTL, value);
536 
537 		value = RREG32_SMC(PM_I_CNTL_1);
538 		value &= ~DS_PG_CNTL_MASK;
539 		WREG32_SMC(PM_I_CNTL_1, value);
540 	}
541 
542 	trinity_gfx_dynamic_mgpg_config(rdev);
543 
544 }
545 
546 static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
547 {
548 	struct trinity_power_info *pi = trinity_get_pi(rdev);
549 
550 	if (pi->enable_gfx_clock_gating)
551 		sumo_gfx_clockgating_initialize(rdev);
552 	if (pi->enable_mg_clock_gating)
553 		trinity_mg_clockgating_initialize(rdev);
554 	if (pi->enable_gfx_power_gating)
555 		trinity_gfx_powergating_initialize(rdev);
556 	if (pi->enable_mg_clock_gating) {
557 		trinity_ls_clockgating_enable(rdev, true);
558 		trinity_mg_clockgating_enable(rdev, true);
559 	}
560 	if (pi->enable_gfx_clock_gating)
561 		trinity_gfx_clockgating_enable(rdev, true);
562 	if (pi->enable_gfx_dynamic_mgpg)
563 		trinity_gfx_dynamic_mgpg_enable(rdev, true);
564 	if (pi->enable_gfx_power_gating)
565 		trinity_gfx_powergating_enable(rdev, true);
566 }
567 
568 static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
569 {
570 	struct trinity_power_info *pi = trinity_get_pi(rdev);
571 
572 	if (pi->enable_gfx_power_gating)
573 		trinity_gfx_powergating_enable(rdev, false);
574 	if (pi->enable_gfx_dynamic_mgpg)
575 		trinity_gfx_dynamic_mgpg_enable(rdev, false);
576 	if (pi->enable_gfx_clock_gating)
577 		trinity_gfx_clockgating_enable(rdev, false);
578 	if (pi->enable_mg_clock_gating) {
579 		trinity_mg_clockgating_enable(rdev, false);
580 		trinity_ls_clockgating_enable(rdev, false);
581 	}
582 }
583 
584 static void trinity_set_divider_value(struct radeon_device *rdev,
585 				      u32 index, u32 sclk)
586 {
587 	struct atom_clock_dividers  dividers;
588 	int ret;
589 	u32 value;
590 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
591 
592 	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
593 					     sclk, false, &dividers);
594 	if (ret)
595 		return;
596 
597 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
598 	value &= ~CLK_DIVIDER_MASK;
599 	value |= CLK_DIVIDER(dividers.post_div);
600 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
601 
602 	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
603 					     sclk/2, false, &dividers);
604 	if (ret)
605 		return;
606 
607 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
608 	value &= ~PD_SCLK_DIVIDER_MASK;
609 	value |= PD_SCLK_DIVIDER(dividers.post_div);
610 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
611 }
612 
613 static void trinity_set_ds_dividers(struct radeon_device *rdev,
614 				    u32 index, u32 divider)
615 {
616 	u32 value;
617 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
618 
619 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
620 	value &= ~DS_DIV_MASK;
621 	value |= DS_DIV(divider);
622 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
623 }
624 
625 static void trinity_set_ss_dividers(struct radeon_device *rdev,
626 				    u32 index, u32 divider)
627 {
628 	u32 value;
629 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
630 
631 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
632 	value &= ~DS_SH_DIV_MASK;
633 	value |= DS_SH_DIV(divider);
634 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
635 }
636 
637 static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
638 {
639 	struct trinity_power_info *pi = trinity_get_pi(rdev);
640 	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
641 	u32 value;
642 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
643 
644 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
645 	value &= ~VID_MASK;
646 	value |= VID(vid_7bit);
647 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
648 
649 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
650 	value &= ~LVRT_MASK;
651 	value |= LVRT(0);
652 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
653 }
654 
655 static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
656 				       u32 index, u32 gnb_slow)
657 {
658 	u32 value;
659 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
660 
661 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
662 	value &= ~GNB_SLOW_MASK;
663 	value |= GNB_SLOW(gnb_slow);
664 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
665 }
666 
667 static void trinity_set_force_nbp_state(struct radeon_device *rdev,
668 					u32 index, u32 force_nbp_state)
669 {
670 	u32 value;
671 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
672 
673 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
674 	value &= ~FORCE_NBPS1_MASK;
675 	value |= FORCE_NBPS1(force_nbp_state);
676 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
677 }
678 
679 static void trinity_set_display_wm(struct radeon_device *rdev,
680 				   u32 index, u32 wm)
681 {
682 	u32 value;
683 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
684 
685 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
686 	value &= ~DISPLAY_WM_MASK;
687 	value |= DISPLAY_WM(wm);
688 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
689 }
690 
691 static void trinity_set_vce_wm(struct radeon_device *rdev,
692 			       u32 index, u32 wm)
693 {
694 	u32 value;
695 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
696 
697 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
698 	value &= ~VCE_WM_MASK;
699 	value |= VCE_WM(wm);
700 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
701 }
702 
703 static void trinity_set_at(struct radeon_device *rdev,
704 			   u32 index, u32 at)
705 {
706 	u32 value;
707 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
708 
709 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
710 	value &= ~AT_MASK;
711 	value |= AT(at);
712 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
713 }
714 
715 static void trinity_program_power_level(struct radeon_device *rdev,
716 					struct trinity_pl *pl, u32 index)
717 {
718 	struct trinity_power_info *pi = trinity_get_pi(rdev);
719 
720 	if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
721 		return;
722 
723 	trinity_set_divider_value(rdev, index, pl->sclk);
724 	trinity_set_vid(rdev, index, pl->vddc_index);
725 	trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
726 	trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
727 	trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
728 	trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
729 	trinity_set_display_wm(rdev, index, pl->display_wm);
730 	trinity_set_vce_wm(rdev, index, pl->vce_wm);
731 	trinity_set_at(rdev, index, pi->at[index]);
732 }
733 
734 static void trinity_power_level_enable_disable(struct radeon_device *rdev,
735 					       u32 index, bool enable)
736 {
737 	u32 value;
738 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
739 
740 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
741 	value &= ~STATE_VALID_MASK;
742 	if (enable)
743 		value |= STATE_VALID(1);
744 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
745 }
746 
747 static bool trinity_dpm_enabled(struct radeon_device *rdev)
748 {
749 	if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
750 		return true;
751 	else
752 		return false;
753 }
754 
755 static void trinity_start_dpm(struct radeon_device *rdev)
756 {
757 	u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
758 
759 	value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
760 	value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
761 	WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
762 
763 	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
764 	WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
765 
766 	trinity_dpm_config(rdev, true);
767 }
768 
769 static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
770 {
771 	int i;
772 
773 	for (i = 0; i < rdev->usec_timeout; i++) {
774 		if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
775 			break;
776 		udelay(1);
777 	}
778 	for (i = 0; i < rdev->usec_timeout; i++) {
779 		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
780 			break;
781 		udelay(1);
782 	}
783 	for (i = 0; i < rdev->usec_timeout; i++) {
784 		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
785 			break;
786 		udelay(1);
787 	}
788 }
789 
790 static void trinity_stop_dpm(struct radeon_device *rdev)
791 {
792 	u32 sclk_dpm_cntl;
793 
794 	WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
795 
796 	sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
797 	sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
798 	WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
799 
800 	trinity_dpm_config(rdev, false);
801 }
802 
803 static void trinity_start_am(struct radeon_device *rdev)
804 {
805 	WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
806 }
807 
808 static void trinity_reset_am(struct radeon_device *rdev)
809 {
810 	WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
811 		 ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
812 }
813 
814 static void trinity_wait_for_level_0(struct radeon_device *rdev)
815 {
816 	int i;
817 
818 	for (i = 0; i < rdev->usec_timeout; i++) {
819 		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
820 			break;
821 		udelay(1);
822 	}
823 }
824 
825 static void trinity_enable_power_level_0(struct radeon_device *rdev)
826 {
827 	trinity_power_level_enable_disable(rdev, 0, true);
828 }
829 
830 static void trinity_force_level_0(struct radeon_device *rdev)
831 {
832 	trinity_dpm_force_state(rdev, 0);
833 }
834 
835 static void trinity_unforce_levels(struct radeon_device *rdev)
836 {
837 	trinity_dpm_no_forced_level(rdev);
838 }
839 
840 static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev,
841 						struct radeon_ps *new_rps,
842 						struct radeon_ps *old_rps)
843 {
844 	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
845 	struct trinity_ps *old_ps = trinity_get_ps(old_rps);
846 	u32 i;
847 	u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
848 
849 	for (i = 0; i < new_ps->num_levels; i++) {
850 		trinity_program_power_level(rdev, &new_ps->levels[i], i);
851 		trinity_power_level_enable_disable(rdev, i, true);
852 	}
853 
854 	for (i = new_ps->num_levels; i < n_current_state_levels; i++)
855 		trinity_power_level_enable_disable(rdev, i, false);
856 }
857 
858 static void trinity_program_bootup_state(struct radeon_device *rdev)
859 {
860 	struct trinity_power_info *pi = trinity_get_pi(rdev);
861 	u32 i;
862 
863 	trinity_program_power_level(rdev, &pi->boot_pl, 0);
864 	trinity_power_level_enable_disable(rdev, 0, true);
865 
866 	for (i = 1; i < 8; i++)
867 		trinity_power_level_enable_disable(rdev, i, false);
868 }
869 
870 static void trinity_setup_uvd_clock_table(struct radeon_device *rdev,
871 					  struct radeon_ps *rps)
872 {
873 	struct trinity_ps *ps = trinity_get_ps(rps);
874 	u32 uvdstates = (ps->vclk_low_divider |
875 			 ps->vclk_high_divider << 8 |
876 			 ps->dclk_low_divider << 16 |
877 			 ps->dclk_high_divider << 24);
878 
879 	WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates);
880 }
881 
882 static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev,
883 					   u32 interval)
884 {
885 	u32 p, u;
886 	u32 tp = RREG32_SMC(PM_TP);
887 	u32 val;
888 	u32 xclk = radeon_get_xclk(rdev);
889 
890 	r600_calculate_u_and_p(interval, xclk, 16, &p, &u);
891 
892 	val = (p + tp - 1) / tp;
893 
894 	WREG32_SMC(SMU_UVD_DPM_CNTL, val);
895 }
896 
897 static bool trinity_uvd_clocks_zero(struct radeon_ps *rps)
898 {
899 	if ((rps->vclk == 0) && (rps->dclk == 0))
900 		return true;
901 	else
902 		return false;
903 }
904 
905 static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1,
906 				     struct radeon_ps *rps2)
907 {
908 	struct trinity_ps *ps1 = trinity_get_ps(rps1);
909 	struct trinity_ps *ps2 = trinity_get_ps(rps2);
910 
911 	if ((rps1->vclk == rps2->vclk) &&
912 	    (rps1->dclk == rps2->dclk) &&
913 	    (ps1->vclk_low_divider == ps2->vclk_low_divider) &&
914 	    (ps1->vclk_high_divider == ps2->vclk_high_divider) &&
915 	    (ps1->dclk_low_divider == ps2->dclk_low_divider) &&
916 	    (ps1->dclk_high_divider == ps2->dclk_high_divider))
917 		return true;
918 	else
919 		return false;
920 }
921 
922 static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
923 				     struct radeon_ps *new_rps,
924 				     struct radeon_ps *old_rps)
925 {
926 	struct trinity_power_info *pi = trinity_get_pi(rdev);
927 
928 	if (pi->enable_gfx_power_gating) {
929 		trinity_gfx_powergating_enable(rdev, false);
930 	}
931 
932 	if (pi->uvd_dpm) {
933 		if (trinity_uvd_clocks_zero(new_rps) &&
934 		    !trinity_uvd_clocks_zero(old_rps)) {
935 			trinity_setup_uvd_dpm_interval(rdev, 0);
936 		} else if (!trinity_uvd_clocks_zero(new_rps)) {
937 			trinity_setup_uvd_clock_table(rdev, new_rps);
938 
939 			if (trinity_uvd_clocks_zero(old_rps)) {
940 				u32 tmp = RREG32(CG_MISC_REG);
941 				tmp &= 0xfffffffd;
942 				WREG32(CG_MISC_REG, tmp);
943 
944 				radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
945 
946 				trinity_setup_uvd_dpm_interval(rdev, 3000);
947 			}
948 		}
949 		trinity_uvd_dpm_config(rdev);
950 	} else {
951 		if (trinity_uvd_clocks_zero(new_rps) ||
952 		    trinity_uvd_clocks_equal(new_rps, old_rps))
953 			return;
954 
955 		radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
956 	}
957 
958 	if (pi->enable_gfx_power_gating) {
959 		trinity_gfx_powergating_enable(rdev, true);
960 	}
961 }
962 
963 static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
964 						       struct radeon_ps *new_rps,
965 						       struct radeon_ps *old_rps)
966 {
967 	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
968 	struct trinity_ps *current_ps = trinity_get_ps(new_rps);
969 
970 	if (new_ps->levels[new_ps->num_levels - 1].sclk >=
971 	    current_ps->levels[current_ps->num_levels - 1].sclk)
972 		return;
973 
974 	trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
975 }
976 
977 static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
978 						      struct radeon_ps *new_rps,
979 						      struct radeon_ps *old_rps)
980 {
981 	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
982 	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
983 
984 	if (new_ps->levels[new_ps->num_levels - 1].sclk <
985 	    current_ps->levels[current_ps->num_levels - 1].sclk)
986 		return;
987 
988 	trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
989 }
990 
991 static void trinity_set_vce_clock(struct radeon_device *rdev,
992 				  struct radeon_ps *new_rps,
993 				  struct radeon_ps *old_rps)
994 {
995 	if ((old_rps->evclk != new_rps->evclk) ||
996 	    (old_rps->ecclk != new_rps->ecclk)) {
997 		/* turn the clocks on when encoding, off otherwise */
998 		if (new_rps->evclk || new_rps->ecclk)
999 			vce_v1_0_enable_mgcg(rdev, false);
1000 		else
1001 			vce_v1_0_enable_mgcg(rdev, true);
1002 		radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
1003 	}
1004 }
1005 
1006 static void trinity_program_ttt(struct radeon_device *rdev)
1007 {
1008 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1009 	u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
1010 
1011 	value &= ~(HT_MASK | LT_MASK);
1012 	value |= HT((pi->thermal_auto_throttling + 49) * 8);
1013 	value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
1014 	WREG32_SMC(SMU_SCLK_DPM_TTT, value);
1015 }
1016 
1017 static void trinity_enable_att(struct radeon_device *rdev)
1018 {
1019 	u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
1020 
1021 	value &= ~SCLK_TT_EN_MASK;
1022 	value |= SCLK_TT_EN(1);
1023 	WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
1024 }
1025 
1026 static void trinity_program_sclk_dpm(struct radeon_device *rdev)
1027 {
1028 	u32 p, u;
1029 	u32 tp = RREG32_SMC(PM_TP);
1030 	u32 ni;
1031 	u32 xclk = radeon_get_xclk(rdev);
1032 	u32 value;
1033 
1034 	r600_calculate_u_and_p(400, xclk, 16, &p, &u);
1035 
1036 	ni = (p + tp - 1) / tp;
1037 
1038 	value = RREG32_SMC(PM_I_CNTL_1);
1039 	value &= ~SCLK_DPM_MASK;
1040 	value |= SCLK_DPM(ni);
1041 	WREG32_SMC(PM_I_CNTL_1, value);
1042 }
1043 
1044 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
1045 						 int min_temp, int max_temp)
1046 {
1047 	int low_temp = 0 * 1000;
1048 	int high_temp = 255 * 1000;
1049 
1050 	if (low_temp < min_temp)
1051 		low_temp = min_temp;
1052 	if (high_temp > max_temp)
1053 		high_temp = max_temp;
1054 	if (high_temp < low_temp) {
1055 		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
1056 		return -EINVAL;
1057 	}
1058 
1059 	WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
1060 	WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
1061 
1062 	rdev->pm.dpm.thermal.min_temp = low_temp;
1063 	rdev->pm.dpm.thermal.max_temp = high_temp;
1064 
1065 	return 0;
1066 }
1067 
1068 static void trinity_update_current_ps(struct radeon_device *rdev,
1069 				      struct radeon_ps *rps)
1070 {
1071 	struct trinity_ps *new_ps = trinity_get_ps(rps);
1072 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1073 
1074 	pi->current_rps = *rps;
1075 	pi->current_ps = *new_ps;
1076 	pi->current_rps.ps_priv = &pi->current_ps;
1077 }
1078 
1079 static void trinity_update_requested_ps(struct radeon_device *rdev,
1080 					struct radeon_ps *rps)
1081 {
1082 	struct trinity_ps *new_ps = trinity_get_ps(rps);
1083 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1084 
1085 	pi->requested_rps = *rps;
1086 	pi->requested_ps = *new_ps;
1087 	pi->requested_rps.ps_priv = &pi->requested_ps;
1088 }
1089 
1090 void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
1091 {
1092 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1093 
1094 	if (pi->enable_bapm) {
1095 		trinity_acquire_mutex(rdev);
1096 		trinity_dpm_bapm_enable(rdev, enable);
1097 		trinity_release_mutex(rdev);
1098 	}
1099 }
1100 
1101 int trinity_dpm_enable(struct radeon_device *rdev)
1102 {
1103 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1104 
1105 	trinity_acquire_mutex(rdev);
1106 
1107 	if (trinity_dpm_enabled(rdev)) {
1108 		trinity_release_mutex(rdev);
1109 		return -EINVAL;
1110 	}
1111 
1112 	trinity_program_bootup_state(rdev);
1113 	sumo_program_vc(rdev, 0x00C00033);
1114 	trinity_start_am(rdev);
1115 	if (pi->enable_auto_thermal_throttling) {
1116 		trinity_program_ttt(rdev);
1117 		trinity_enable_att(rdev);
1118 	}
1119 	trinity_program_sclk_dpm(rdev);
1120 	trinity_start_dpm(rdev);
1121 	trinity_wait_for_dpm_enabled(rdev);
1122 	trinity_dpm_bapm_enable(rdev, false);
1123 	trinity_release_mutex(rdev);
1124 
1125 	trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1126 
1127 	return 0;
1128 }
1129 
1130 int trinity_dpm_late_enable(struct radeon_device *rdev)
1131 {
1132 	int ret;
1133 
1134 	trinity_acquire_mutex(rdev);
1135 	trinity_enable_clock_power_gating(rdev);
1136 
1137 	if (rdev->irq.installed &&
1138 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1139 		ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
1140 		if (ret) {
1141 			trinity_release_mutex(rdev);
1142 			return ret;
1143 		}
1144 		rdev->irq.dpm_thermal = true;
1145 		radeon_irq_set(rdev);
1146 	}
1147 	trinity_release_mutex(rdev);
1148 
1149 	return 0;
1150 }
1151 
1152 void trinity_dpm_disable(struct radeon_device *rdev)
1153 {
1154 	trinity_acquire_mutex(rdev);
1155 	if (!trinity_dpm_enabled(rdev)) {
1156 		trinity_release_mutex(rdev);
1157 		return;
1158 	}
1159 	trinity_dpm_bapm_enable(rdev, false);
1160 	trinity_disable_clock_power_gating(rdev);
1161 	sumo_clear_vc(rdev);
1162 	trinity_wait_for_level_0(rdev);
1163 	trinity_stop_dpm(rdev);
1164 	trinity_reset_am(rdev);
1165 	trinity_release_mutex(rdev);
1166 
1167 	if (rdev->irq.installed &&
1168 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1169 		rdev->irq.dpm_thermal = false;
1170 		radeon_irq_set(rdev);
1171 	}
1172 
1173 	trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1174 }
1175 
1176 static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
1177 {
1178 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1179 
1180 	pi->min_sclk_did =
1181 		(RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
1182 }
1183 
1184 static void trinity_setup_nbp_sim(struct radeon_device *rdev,
1185 				  struct radeon_ps *rps)
1186 {
1187 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1188 	struct trinity_ps *new_ps = trinity_get_ps(rps);
1189 	u32 nbpsconfig;
1190 
1191 	if (pi->sys_info.nb_dpm_enable) {
1192 		nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
1193 		nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
1194 		nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
1195 			       Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
1196 			       DpmXNbPsLo(new_ps->DpmXNbPsLo) |
1197 			       DpmXNbPsHi(new_ps->DpmXNbPsHi));
1198 		WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
1199 	}
1200 }
1201 
1202 int trinity_dpm_force_performance_level(struct radeon_device *rdev,
1203 					enum radeon_dpm_forced_level level)
1204 {
1205 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1206 	struct radeon_ps *rps = &pi->current_rps;
1207 	struct trinity_ps *ps = trinity_get_ps(rps);
1208 	int i, ret;
1209 
1210 	if (ps->num_levels <= 1)
1211 		return 0;
1212 
1213 	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
1214 		/* not supported by the hw */
1215 		return -EINVAL;
1216 	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
1217 		ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1);
1218 		if (ret)
1219 			return ret;
1220 	} else {
1221 		for (i = 0; i < ps->num_levels; i++) {
1222 			ret = trinity_dpm_n_levels_disabled(rdev, 0);
1223 			if (ret)
1224 				return ret;
1225 		}
1226 	}
1227 
1228 	rdev->pm.dpm.forced_level = level;
1229 
1230 	return 0;
1231 }
1232 
1233 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev)
1234 {
1235 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1236 	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
1237 	struct radeon_ps *new_ps = &requested_ps;
1238 
1239 	trinity_update_requested_ps(rdev, new_ps);
1240 
1241 	trinity_apply_state_adjust_rules(rdev,
1242 					 &pi->requested_rps,
1243 					 &pi->current_rps);
1244 
1245 	return 0;
1246 }
1247 
1248 int trinity_dpm_set_power_state(struct radeon_device *rdev)
1249 {
1250 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1251 	struct radeon_ps *new_ps = &pi->requested_rps;
1252 	struct radeon_ps *old_ps = &pi->current_rps;
1253 
1254 	trinity_acquire_mutex(rdev);
1255 	if (pi->enable_dpm) {
1256 		if (pi->enable_bapm)
1257 			trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power);
1258 		trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
1259 		trinity_enable_power_level_0(rdev);
1260 		trinity_force_level_0(rdev);
1261 		trinity_wait_for_level_0(rdev);
1262 		trinity_setup_nbp_sim(rdev, new_ps);
1263 		trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
1264 		trinity_force_level_0(rdev);
1265 		trinity_unforce_levels(rdev);
1266 		trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1267 		trinity_set_vce_clock(rdev, new_ps, old_ps);
1268 	}
1269 	trinity_release_mutex(rdev);
1270 
1271 	return 0;
1272 }
1273 
1274 void trinity_dpm_post_set_power_state(struct radeon_device *rdev)
1275 {
1276 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1277 	struct radeon_ps *new_ps = &pi->requested_rps;
1278 
1279 	trinity_update_current_ps(rdev, new_ps);
1280 }
1281 
1282 void trinity_dpm_setup_asic(struct radeon_device *rdev)
1283 {
1284 	trinity_acquire_mutex(rdev);
1285 	sumo_program_sstp(rdev);
1286 	sumo_take_smu_control(rdev, true);
1287 	trinity_get_min_sclk_divider(rdev);
1288 	trinity_release_mutex(rdev);
1289 }
1290 
1291 #if 0
1292 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1293 {
1294 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1295 
1296 	trinity_acquire_mutex(rdev);
1297 	if (pi->enable_dpm) {
1298 		trinity_enable_power_level_0(rdev);
1299 		trinity_force_level_0(rdev);
1300 		trinity_wait_for_level_0(rdev);
1301 		trinity_program_bootup_state(rdev);
1302 		trinity_force_level_0(rdev);
1303 		trinity_unforce_levels(rdev);
1304 	}
1305 	trinity_release_mutex(rdev);
1306 }
1307 #endif
1308 
1309 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1310 						  u32 vid_2bit)
1311 {
1312 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1313 	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1314 	u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1315 	u32 step = (svi_mode == 0) ? 1250 : 625;
1316 	u32 delta = vid_7bit * step + 50;
1317 
1318 	if (delta > 155000)
1319 		return 0;
1320 
1321 	return (155000 - delta) / 100;
1322 }
1323 
1324 static void trinity_patch_boot_state(struct radeon_device *rdev,
1325 				     struct trinity_ps *ps)
1326 {
1327 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1328 
1329 	ps->num_levels = 1;
1330 	ps->nbps_flags = 0;
1331 	ps->bapm_flags = 0;
1332 	ps->levels[0] = pi->boot_pl;
1333 }
1334 
1335 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1336 {
1337 	if (sclk < 20000)
1338 		return 1;
1339 	return 0;
1340 }
1341 
1342 static void trinity_construct_boot_state(struct radeon_device *rdev)
1343 {
1344 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1345 
1346 	pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1347 	pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1348 	pi->boot_pl.ds_divider_index = 0;
1349 	pi->boot_pl.ss_divider_index = 0;
1350 	pi->boot_pl.allow_gnb_slow = 1;
1351 	pi->boot_pl.force_nbp_state = 0;
1352 	pi->boot_pl.display_wm = 0;
1353 	pi->boot_pl.vce_wm = 0;
1354 	pi->current_ps.num_levels = 1;
1355 	pi->current_ps.levels[0] = pi->boot_pl;
1356 }
1357 
1358 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1359 						  u32 sclk, u32 min_sclk_in_sr)
1360 {
1361 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1362 	u32 i;
1363 	u32 temp;
1364 	u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1365 		min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1366 
1367 	if (sclk < min)
1368 		return 0;
1369 
1370 	if (!pi->enable_sclk_ds)
1371 		return 0;
1372 
1373 	for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
1374 		temp = sclk / sumo_get_sleep_divider_from_id(i);
1375 		if (temp >= min || i == 0)
1376 			break;
1377 	}
1378 
1379 	return (u8)i;
1380 }
1381 
1382 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1383 					  u32 lower_limit)
1384 {
1385 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1386 	u32 i;
1387 
1388 	for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1389 		if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1390 			return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1391 	}
1392 
1393 	if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1394 		DRM_ERROR("engine clock out of range!");
1395 
1396 	return 0;
1397 }
1398 
1399 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1400 					struct trinity_ps *ps,
1401 					struct trinity_ps *current_ps)
1402 {
1403 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1404 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1405 	u32 current_vddc;
1406 	u32 current_sclk;
1407 	u32 current_index = 0;
1408 
1409 	if (current_ps) {
1410 		current_vddc = current_ps->levels[current_index].vddc_index;
1411 		current_sclk = current_ps->levels[current_index].sclk;
1412 	} else {
1413 		current_vddc = pi->boot_pl.vddc_index;
1414 		current_sclk = pi->boot_pl.sclk;
1415 	}
1416 
1417 	ps->levels[0].vddc_index = current_vddc;
1418 
1419 	if (ps->levels[0].sclk > current_sclk)
1420 		ps->levels[0].sclk = current_sclk;
1421 
1422 	ps->levels[0].ds_divider_index =
1423 		trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1424 	ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1425 	ps->levels[0].allow_gnb_slow = 1;
1426 	ps->levels[0].force_nbp_state = 0;
1427 	ps->levels[0].display_wm = 0;
1428 	ps->levels[0].vce_wm =
1429 		trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1430 }
1431 
1432 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1433 				       struct trinity_ps *ps, u32 index)
1434 {
1435 	if (ps == NULL || ps->num_levels <= 1)
1436 		return 0;
1437 	else if (ps->num_levels == 2) {
1438 		if (index == 0)
1439 			return 0;
1440 		else
1441 			return 1;
1442 	} else {
1443 		if (index == 0)
1444 			return 0;
1445 		else if (ps->levels[index].sclk < 30000)
1446 			return 0;
1447 		else
1448 			return 1;
1449 	}
1450 }
1451 
1452 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
1453 				       struct radeon_ps *rps)
1454 {
1455 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1456 	u32 i = 0;
1457 
1458 	for (i = 0; i < 4; i++) {
1459 		if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
1460 		    (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
1461 		    break;
1462 	}
1463 
1464 	if (i >= 4) {
1465 		DRM_ERROR("UVD clock index not found!\n");
1466 		i = 3;
1467 	}
1468 	return i;
1469 }
1470 
1471 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1472 				     struct radeon_ps *rps)
1473 {
1474 	struct trinity_ps *ps = trinity_get_ps(rps);
1475 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1476 	u32 high_index = 0;
1477 	u32 low_index = 0;
1478 
1479 	if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
1480 		high_index = trinity_get_uvd_clock_index(rdev, rps);
1481 
1482 		switch(high_index) {
1483 		case 3:
1484 		case 2:
1485 			low_index = 1;
1486 			break;
1487 		case 1:
1488 		case 0:
1489 		default:
1490 			low_index = 0;
1491 			break;
1492 		}
1493 
1494 		ps->vclk_low_divider =
1495 			pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
1496 		ps->dclk_low_divider =
1497 			pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
1498 		ps->vclk_high_divider =
1499 			pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
1500 		ps->dclk_high_divider =
1501 			pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
1502 	}
1503 }
1504 
1505 static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
1506 					 u32 evclk, u32 ecclk, u16 *voltage)
1507 {
1508 	u32 i;
1509 	int ret = -EINVAL;
1510 	struct radeon_vce_clock_voltage_dependency_table *table =
1511 		&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
1512 
1513 	if (((evclk == 0) && (ecclk == 0)) ||
1514 	    (table && (table->count == 0))) {
1515 		*voltage = 0;
1516 		return 0;
1517 	}
1518 
1519 	for (i = 0; i < table->count; i++) {
1520 		if ((evclk <= table->entries[i].evclk) &&
1521 		    (ecclk <= table->entries[i].ecclk)) {
1522 			*voltage = table->entries[i].v;
1523 			ret = 0;
1524 			break;
1525 		}
1526 	}
1527 
1528 	/* if no match return the highest voltage */
1529 	if (ret)
1530 		*voltage = table->entries[table->count - 1].v;
1531 
1532 	return ret;
1533 }
1534 
1535 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1536 					     struct radeon_ps *new_rps,
1537 					     struct radeon_ps *old_rps)
1538 {
1539 	struct trinity_ps *ps = trinity_get_ps(new_rps);
1540 	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
1541 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1542 	u32 min_voltage = 0; /* ??? */
1543 	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1544 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1545 	u32 i;
1546 	u16 min_vce_voltage;
1547 	bool force_high;
1548 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1549 
1550 	if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1551 		return trinity_patch_thermal_state(rdev, ps, current_ps);
1552 
1553 	trinity_adjust_uvd_state(rdev, new_rps);
1554 
1555 	if (new_rps->vce_active) {
1556 		new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
1557 		new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
1558 	} else {
1559 		new_rps->evclk = 0;
1560 		new_rps->ecclk = 0;
1561 	}
1562 
1563 	for (i = 0; i < ps->num_levels; i++) {
1564 		if (ps->levels[i].vddc_index < min_voltage)
1565 			ps->levels[i].vddc_index = min_voltage;
1566 
1567 		if (ps->levels[i].sclk < min_sclk)
1568 			ps->levels[i].sclk =
1569 				trinity_get_valid_engine_clock(rdev, min_sclk);
1570 
1571 		/* patch in vce limits */
1572 		if (new_rps->vce_active) {
1573 			/* sclk */
1574 			if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
1575 				ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
1576 			/* vddc */
1577 			trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
1578 			if (ps->levels[i].vddc_index < min_vce_voltage)
1579 				ps->levels[i].vddc_index = min_vce_voltage;
1580 		}
1581 
1582 		ps->levels[i].ds_divider_index =
1583 			sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1584 
1585 		ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1586 
1587 		ps->levels[i].allow_gnb_slow = 1;
1588 		ps->levels[i].force_nbp_state = 0;
1589 		ps->levels[i].display_wm =
1590 			trinity_calculate_display_wm(rdev, ps, i);
1591 		ps->levels[i].vce_wm =
1592 			trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1593 	}
1594 
1595 	if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1596 	    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1597 		ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1598 
1599 	if (pi->sys_info.nb_dpm_enable) {
1600 		ps->Dpm0PgNbPsLo = 0x1;
1601 		ps->Dpm0PgNbPsHi = 0x0;
1602 		ps->DpmXNbPsLo = 0x2;
1603 		ps->DpmXNbPsHi = 0x1;
1604 
1605 		if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1606 		    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1607 			force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1608 				      ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1609 				       (pi->sys_info.uma_channel_number == 1)));
1610 			force_high = (num_active_displays >= 3) || force_high;
1611 			ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1612 			ps->Dpm0PgNbPsHi = 0x1;
1613 			ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1614 			ps->DpmXNbPsHi = 0x2;
1615 			ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1616 		}
1617 	}
1618 }
1619 
1620 static void trinity_cleanup_asic(struct radeon_device *rdev)
1621 {
1622 	sumo_take_smu_control(rdev, false);
1623 }
1624 
1625 #if 0
1626 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1627 {
1628 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1629 
1630 	if (pi->voltage_drop_in_dce)
1631 		trinity_dce_enable_voltage_adjustment(rdev, false);
1632 }
1633 #endif
1634 
1635 static void trinity_add_dccac_value(struct radeon_device *rdev)
1636 {
1637 	u32 gpu_cac_avrg_cntl_window_size;
1638 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1639 	u64 disp_clk = rdev->clock.default_dispclk / 100;
1640 	u32 dc_cac_value;
1641 
1642 	gpu_cac_avrg_cntl_window_size =
1643 		(RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1644 
1645 	dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1646 			     (32 - gpu_cac_avrg_cntl_window_size));
1647 
1648 	WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1649 }
1650 
1651 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1652 {
1653 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1654 
1655 	if (pi->voltage_drop_in_dce)
1656 		trinity_dce_enable_voltage_adjustment(rdev, true);
1657 	trinity_add_dccac_value(rdev);
1658 }
1659 
1660 union power_info {
1661 	struct _ATOM_POWERPLAY_INFO info;
1662 	struct _ATOM_POWERPLAY_INFO_V2 info_2;
1663 	struct _ATOM_POWERPLAY_INFO_V3 info_3;
1664 	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1665 	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1666 	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1667 };
1668 
1669 union pplib_clock_info {
1670 	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1671 	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1672 	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1673 	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1674 };
1675 
1676 union pplib_power_state {
1677 	struct _ATOM_PPLIB_STATE v1;
1678 	struct _ATOM_PPLIB_STATE_V2 v2;
1679 };
1680 
1681 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1682 					       struct radeon_ps *rps,
1683 					       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1684 					       u8 table_rev)
1685 {
1686 	struct trinity_ps *ps = trinity_get_ps(rps);
1687 
1688 	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1689 	rps->class = le16_to_cpu(non_clock_info->usClassification);
1690 	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1691 
1692 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1693 		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1694 		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1695 	} else {
1696 		rps->vclk = 0;
1697 		rps->dclk = 0;
1698 	}
1699 
1700 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1701 		rdev->pm.dpm.boot_ps = rps;
1702 		trinity_patch_boot_state(rdev, ps);
1703 	}
1704 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1705 		rdev->pm.dpm.uvd_ps = rps;
1706 }
1707 
1708 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1709 					   struct radeon_ps *rps, int index,
1710 					   union pplib_clock_info *clock_info)
1711 {
1712 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1713 	struct trinity_ps *ps = trinity_get_ps(rps);
1714 	struct trinity_pl *pl = &ps->levels[index];
1715 	u32 sclk;
1716 
1717 	sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1718 	sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1719 	pl->sclk = sclk;
1720 	pl->vddc_index = clock_info->sumo.vddcIndex;
1721 
1722 	ps->num_levels = index + 1;
1723 
1724 	if (pi->enable_sclk_ds) {
1725 		pl->ds_divider_index = 5;
1726 		pl->ss_divider_index = 5;
1727 	}
1728 }
1729 
1730 static int trinity_parse_power_table(struct radeon_device *rdev)
1731 {
1732 	struct radeon_mode_info *mode_info = &rdev->mode_info;
1733 	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1734 	union pplib_power_state *power_state;
1735 	int i, j, k, non_clock_array_index, clock_array_index;
1736 	union pplib_clock_info *clock_info;
1737 	struct _StateArray *state_array;
1738 	struct _ClockInfoArray *clock_info_array;
1739 	struct _NonClockInfoArray *non_clock_info_array;
1740 	union power_info *power_info;
1741 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1742 	u16 data_offset;
1743 	u8 frev, crev;
1744 	u8 *power_state_offset;
1745 	struct sumo_ps *ps;
1746 
1747 	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1748 				   &frev, &crev, &data_offset))
1749 		return -EINVAL;
1750 	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1751 
1752 	state_array = (struct _StateArray *)
1753 		(mode_info->atom_context->bios + data_offset +
1754 		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1755 	clock_info_array = (struct _ClockInfoArray *)
1756 		(mode_info->atom_context->bios + data_offset +
1757 		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1758 	non_clock_info_array = (struct _NonClockInfoArray *)
1759 		(mode_info->atom_context->bios + data_offset +
1760 		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1761 
1762 	rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
1763 				  sizeof(struct radeon_ps),
1764 				  GFP_KERNEL);
1765 	if (!rdev->pm.dpm.ps)
1766 		return -ENOMEM;
1767 	power_state_offset = (u8 *)state_array->states;
1768 	for (i = 0; i < state_array->ucNumEntries; i++) {
1769 		u8 *idx;
1770 		power_state = (union pplib_power_state *)power_state_offset;
1771 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
1772 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1773 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
1774 		if (!rdev->pm.power_state[i].clock_info)
1775 			return -EINVAL;
1776 		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1777 		if (ps == NULL) {
1778 			kfree(rdev->pm.dpm.ps);
1779 			return -ENOMEM;
1780 		}
1781 		rdev->pm.dpm.ps[i].ps_priv = ps;
1782 		k = 0;
1783 		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
1784 		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1785 			clock_array_index = idx[j];
1786 			if (clock_array_index >= clock_info_array->ucNumEntries)
1787 				continue;
1788 			if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1789 				break;
1790 			clock_info = (union pplib_clock_info *)
1791 				((u8 *)&clock_info_array->clockInfo[0] +
1792 				 (clock_array_index * clock_info_array->ucEntrySize));
1793 			trinity_parse_pplib_clock_info(rdev,
1794 						       &rdev->pm.dpm.ps[i], k,
1795 						       clock_info);
1796 			k++;
1797 		}
1798 		trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1799 						   non_clock_info,
1800 						   non_clock_info_array->ucEntrySize);
1801 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1802 	}
1803 	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1804 
1805 	/* fill in the vce power states */
1806 	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
1807 		u32 sclk;
1808 		clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
1809 		clock_info = (union pplib_clock_info *)
1810 			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
1811 		sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1812 		sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1813 		rdev->pm.dpm.vce_states[i].sclk = sclk;
1814 		rdev->pm.dpm.vce_states[i].mclk = 0;
1815 	}
1816 
1817 	return 0;
1818 }
1819 
1820 union igp_info {
1821 	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1822 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1823 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1824 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1825 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1826 };
1827 
1828 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
1829 {
1830 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1831 	u32 divider;
1832 
1833 	if (did >= 8 && did <= 0x3f)
1834 		divider = did * 25;
1835 	else if (did > 0x3f && did <= 0x5f)
1836 		divider = (did - 64) * 50 + 1600;
1837 	else if (did > 0x5f && did <= 0x7e)
1838 		divider = (did - 96) * 100 + 3200;
1839 	else if (did == 0x7f)
1840 		divider = 128 * 100;
1841 	else
1842 		return 10000;
1843 
1844 	return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
1845 }
1846 
1847 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1848 {
1849 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1850 	struct radeon_mode_info *mode_info = &rdev->mode_info;
1851 	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1852 	union igp_info *igp_info;
1853 	u8 frev, crev;
1854 	u16 data_offset;
1855 	int i;
1856 
1857 	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1858 				   &frev, &crev, &data_offset)) {
1859 		igp_info = (union igp_info *)(mode_info->atom_context->bios +
1860 					      data_offset);
1861 
1862 		if (crev != 7) {
1863 			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1864 			return -EINVAL;
1865 		}
1866 		pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1867 		pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1868 		pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1869 		pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
1870 		pi->sys_info.bootup_nb_voltage_index =
1871 			le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1872 		if (igp_info->info_7.ucHtcTmpLmt == 0)
1873 			pi->sys_info.htc_tmp_lmt = 203;
1874 		else
1875 			pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1876 		if (igp_info->info_7.ucHtcHystLmt == 0)
1877 			pi->sys_info.htc_hyst_lmt = 5;
1878 		else
1879 			pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1880 		if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1881 			DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1882 		}
1883 
1884 		if (pi->enable_nbps_policy)
1885 			pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1886 		else
1887 			pi->sys_info.nb_dpm_enable = 0;
1888 
1889 		for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1890 			pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1891 			pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1892 		}
1893 
1894 		pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1895 		pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1896 		pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1897 		pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1898 
1899 		if (!pi->sys_info.nb_dpm_enable) {
1900 			for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1901 				pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1902 				pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1903 				pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1904 			}
1905 		}
1906 
1907 		pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1908 
1909 		sumo_construct_sclk_voltage_mapping_table(rdev,
1910 							  &pi->sys_info.sclk_voltage_mapping_table,
1911 							  igp_info->info_7.sAvail_SCLK);
1912 		sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1913 						 igp_info->info_7.sAvail_SCLK);
1914 
1915 		pi->sys_info.uvd_clock_table_entries[0].vclk_did =
1916 			igp_info->info_7.ucDPMState0VclkFid;
1917 		pi->sys_info.uvd_clock_table_entries[1].vclk_did =
1918 			igp_info->info_7.ucDPMState1VclkFid;
1919 		pi->sys_info.uvd_clock_table_entries[2].vclk_did =
1920 			igp_info->info_7.ucDPMState2VclkFid;
1921 		pi->sys_info.uvd_clock_table_entries[3].vclk_did =
1922 			igp_info->info_7.ucDPMState3VclkFid;
1923 
1924 		pi->sys_info.uvd_clock_table_entries[0].dclk_did =
1925 			igp_info->info_7.ucDPMState0DclkFid;
1926 		pi->sys_info.uvd_clock_table_entries[1].dclk_did =
1927 			igp_info->info_7.ucDPMState1DclkFid;
1928 		pi->sys_info.uvd_clock_table_entries[2].dclk_did =
1929 			igp_info->info_7.ucDPMState2DclkFid;
1930 		pi->sys_info.uvd_clock_table_entries[3].dclk_did =
1931 			igp_info->info_7.ucDPMState3DclkFid;
1932 
1933 		for (i = 0; i < 4; i++) {
1934 			pi->sys_info.uvd_clock_table_entries[i].vclk =
1935 				trinity_convert_did_to_freq(rdev,
1936 							    pi->sys_info.uvd_clock_table_entries[i].vclk_did);
1937 			pi->sys_info.uvd_clock_table_entries[i].dclk =
1938 				trinity_convert_did_to_freq(rdev,
1939 							    pi->sys_info.uvd_clock_table_entries[i].dclk_did);
1940 		}
1941 
1942 
1943 
1944 	}
1945 	return 0;
1946 }
1947 
1948 int trinity_dpm_init(struct radeon_device *rdev)
1949 {
1950 	struct trinity_power_info *pi;
1951 	int ret, i;
1952 
1953 	pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1954 	if (pi == NULL)
1955 		return -ENOMEM;
1956 	rdev->pm.dpm.priv = pi;
1957 
1958 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1959 		pi->at[i] = TRINITY_AT_DFLT;
1960 
1961 	if (radeon_bapm == -1) {
1962 		/* There are stability issues reported on with
1963 		 * bapm enabled when switching between AC and battery
1964 		 * power.  At the same time, some MSI boards hang
1965 		 * if it's not enabled and dpm is enabled.  Just enable
1966 		 * it for MSI boards right now.
1967 		 */
1968 		if (rdev->pdev->subsystem_vendor == 0x1462)
1969 			pi->enable_bapm = true;
1970 		else
1971 			pi->enable_bapm = false;
1972 	} else if (radeon_bapm == 0) {
1973 		pi->enable_bapm = false;
1974 	} else {
1975 		pi->enable_bapm = true;
1976 	}
1977 	pi->enable_nbps_policy = true;
1978 	pi->enable_sclk_ds = true;
1979 	pi->enable_gfx_power_gating = true;
1980 	pi->enable_gfx_clock_gating = true;
1981 	pi->enable_mg_clock_gating = false;
1982 	pi->enable_gfx_dynamic_mgpg = false;
1983 	pi->override_dynamic_mgpg = false;
1984 	pi->enable_auto_thermal_throttling = true;
1985 	pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1986 	pi->uvd_dpm = true; /* ??? */
1987 
1988 	ret = trinity_parse_sys_info_table(rdev);
1989 	if (ret)
1990 		return ret;
1991 
1992 	trinity_construct_boot_state(rdev);
1993 
1994 	ret = r600_get_platform_caps(rdev);
1995 	if (ret)
1996 		return ret;
1997 
1998 	ret = r600_parse_extended_power_table(rdev);
1999 	if (ret)
2000 		return ret;
2001 
2002 	ret = trinity_parse_power_table(rdev);
2003 	if (ret)
2004 		return ret;
2005 
2006 	pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
2007 	pi->enable_dpm = true;
2008 
2009 	return 0;
2010 }
2011 
2012 void trinity_dpm_print_power_state(struct radeon_device *rdev,
2013 				   struct radeon_ps *rps)
2014 {
2015 	int i;
2016 	struct trinity_ps *ps = trinity_get_ps(rps);
2017 
2018 	r600_dpm_print_class_info(rps->class, rps->class2);
2019 	r600_dpm_print_cap_info(rps->caps);
2020 	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
2021 	for (i = 0; i < ps->num_levels; i++) {
2022 		struct trinity_pl *pl = &ps->levels[i];
2023 		printk("\t\tpower level %d    sclk: %u vddc: %u\n",
2024 		       i, pl->sclk,
2025 		       trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
2026 	}
2027 	r600_dpm_print_ps_status(rdev, rps);
2028 }
2029 
2030 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
2031 							 struct seq_file *m)
2032 {
2033 	struct trinity_power_info *pi = trinity_get_pi(rdev);
2034 	struct radeon_ps *rps = &pi->current_rps;
2035 	struct trinity_ps *ps = trinity_get_ps(rps);
2036 	struct trinity_pl *pl;
2037 	u32 current_index =
2038 		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
2039 		CURRENT_STATE_SHIFT;
2040 
2041 	if (current_index >= ps->num_levels) {
2042 		seq_printf(m, "invalid dpm profile %d\n", current_index);
2043 	} else {
2044 		pl = &ps->levels[current_index];
2045 		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
2046 		seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
2047 			   current_index, pl->sclk,
2048 			   trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
2049 	}
2050 }
2051 
2052 u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev)
2053 {
2054 	struct trinity_power_info *pi = trinity_get_pi(rdev);
2055 	struct radeon_ps *rps = &pi->current_rps;
2056 	struct trinity_ps *ps = trinity_get_ps(rps);
2057 	struct trinity_pl *pl;
2058 	u32 current_index =
2059 		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
2060 		CURRENT_STATE_SHIFT;
2061 
2062 	if (current_index >= ps->num_levels) {
2063 		return 0;
2064 	} else {
2065 		pl = &ps->levels[current_index];
2066 		return pl->sclk;
2067 	}
2068 }
2069 
2070 u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev)
2071 {
2072 	struct trinity_power_info *pi = trinity_get_pi(rdev);
2073 
2074 	return pi->sys_info.bootup_uma_clk;
2075 }
2076 
2077 void trinity_dpm_fini(struct radeon_device *rdev)
2078 {
2079 	int i;
2080 
2081 	trinity_cleanup_asic(rdev); /* ??? */
2082 
2083 	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
2084 		kfree(rdev->pm.dpm.ps[i].ps_priv);
2085 	}
2086 	kfree(rdev->pm.dpm.ps);
2087 	kfree(rdev->pm.dpm.priv);
2088 	r600_free_extended_power_table(rdev);
2089 }
2090 
2091 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
2092 {
2093 	struct trinity_power_info *pi = trinity_get_pi(rdev);
2094 	struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
2095 
2096 	if (low)
2097 		return requested_state->levels[0].sclk;
2098 	else
2099 		return requested_state->levels[requested_state->num_levels - 1].sclk;
2100 }
2101 
2102 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
2103 {
2104 	struct trinity_power_info *pi = trinity_get_pi(rdev);
2105 
2106 	return pi->sys_info.bootup_uma_clk;
2107 }
2108