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