xref: /dragonfly/sys/dev/drm/radeon/trinity_dpm.c (revision 7bcb6caf)
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 <drm/drmP.h>
25 #include "radeon.h"
26 #include "radeon_asic.h"
27 #include "trinityd.h"
28 #include "r600_dpm.h"
29 #include "trinity_dpm.h"
30 #include <linux/seq_file.h>
31 
32 #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
33 #define TRINITY_MINIMUM_ENGINE_CLOCK 800
34 #define SCLK_MIN_DIV_INTV_SHIFT     12
35 #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
36 
37 #ifndef TRINITY_MGCG_SEQUENCE
38 #define TRINITY_MGCG_SEQUENCE  100
39 
40 static const u32 trinity_mgcg_shls_default[] =
41 {
42 	/* Register, Value, Mask */
43 	0x0000802c, 0xc0000000, 0xffffffff,
44 	0x00003fc4, 0xc0000000, 0xffffffff,
45 	0x00005448, 0x00000100, 0xffffffff,
46 	0x000055e4, 0x00000100, 0xffffffff,
47 	0x0000160c, 0x00000100, 0xffffffff,
48 	0x00008984, 0x06000100, 0xffffffff,
49 	0x0000c164, 0x00000100, 0xffffffff,
50 	0x00008a18, 0x00000100, 0xffffffff,
51 	0x0000897c, 0x06000100, 0xffffffff,
52 	0x00008b28, 0x00000100, 0xffffffff,
53 	0x00009144, 0x00800200, 0xffffffff,
54 	0x00009a60, 0x00000100, 0xffffffff,
55 	0x00009868, 0x00000100, 0xffffffff,
56 	0x00008d58, 0x00000100, 0xffffffff,
57 	0x00009510, 0x00000100, 0xffffffff,
58 	0x0000949c, 0x00000100, 0xffffffff,
59 	0x00009654, 0x00000100, 0xffffffff,
60 	0x00009030, 0x00000100, 0xffffffff,
61 	0x00009034, 0x00000100, 0xffffffff,
62 	0x00009038, 0x00000100, 0xffffffff,
63 	0x0000903c, 0x00000100, 0xffffffff,
64 	0x00009040, 0x00000100, 0xffffffff,
65 	0x0000a200, 0x00000100, 0xffffffff,
66 	0x0000a204, 0x00000100, 0xffffffff,
67 	0x0000a208, 0x00000100, 0xffffffff,
68 	0x0000a20c, 0x00000100, 0xffffffff,
69 	0x00009744, 0x00000100, 0xffffffff,
70 	0x00003f80, 0x00000100, 0xffffffff,
71 	0x0000a210, 0x00000100, 0xffffffff,
72 	0x0000a214, 0x00000100, 0xffffffff,
73 	0x000004d8, 0x00000100, 0xffffffff,
74 	0x00009664, 0x00000100, 0xffffffff,
75 	0x00009698, 0x00000100, 0xffffffff,
76 	0x000004d4, 0x00000200, 0xffffffff,
77 	0x000004d0, 0x00000000, 0xffffffff,
78 	0x000030cc, 0x00000104, 0xffffffff,
79 	0x0000d0c0, 0x00000100, 0xffffffff,
80 	0x0000d8c0, 0x00000100, 0xffffffff,
81 	0x0000951c, 0x00010000, 0xffffffff,
82 	0x00009160, 0x00030002, 0xffffffff,
83 	0x00009164, 0x00050004, 0xffffffff,
84 	0x00009168, 0x00070006, 0xffffffff,
85 	0x00009178, 0x00070000, 0xffffffff,
86 	0x0000917c, 0x00030002, 0xffffffff,
87 	0x00009180, 0x00050004, 0xffffffff,
88 	0x0000918c, 0x00010006, 0xffffffff,
89 	0x00009190, 0x00090008, 0xffffffff,
90 	0x00009194, 0x00070000, 0xffffffff,
91 	0x00009198, 0x00030002, 0xffffffff,
92 	0x0000919c, 0x00050004, 0xffffffff,
93 	0x000091a8, 0x00010006, 0xffffffff,
94 	0x000091ac, 0x00090008, 0xffffffff,
95 	0x000091b0, 0x00070000, 0xffffffff,
96 	0x000091b4, 0x00030002, 0xffffffff,
97 	0x000091b8, 0x00050004, 0xffffffff,
98 	0x000091c4, 0x00010006, 0xffffffff,
99 	0x000091c8, 0x00090008, 0xffffffff,
100 	0x000091cc, 0x00070000, 0xffffffff,
101 	0x000091d0, 0x00030002, 0xffffffff,
102 	0x000091d4, 0x00050004, 0xffffffff,
103 	0x000091e0, 0x00010006, 0xffffffff,
104 	0x000091e4, 0x00090008, 0xffffffff,
105 	0x000091e8, 0x00000000, 0xffffffff,
106 	0x000091ec, 0x00070000, 0xffffffff,
107 	0x000091f0, 0x00030002, 0xffffffff,
108 	0x000091f4, 0x00050004, 0xffffffff,
109 	0x00009200, 0x00010006, 0xffffffff,
110 	0x00009204, 0x00090008, 0xffffffff,
111 	0x00009208, 0x00070000, 0xffffffff,
112 	0x0000920c, 0x00030002, 0xffffffff,
113 	0x00009210, 0x00050004, 0xffffffff,
114 	0x0000921c, 0x00010006, 0xffffffff,
115 	0x00009220, 0x00090008, 0xffffffff,
116 	0x00009294, 0x00000000, 0xffffffff
117 };
118 
119 #if 0 /* unused */
120 static const u32 trinity_mgcg_shls_enable[] =
121 {
122 	/* Register, Value, Mask */
123 	0x0000802c, 0xc0000000, 0xffffffff,
124 	0x000008f8, 0x00000000, 0xffffffff,
125 	0x000008fc, 0x00000000, 0x000133FF,
126 	0x000008f8, 0x00000001, 0xffffffff,
127 	0x000008fc, 0x00000000, 0xE00B03FC,
128 	0x00009150, 0x96944200, 0xffffffff
129 };
130 #endif
131 
132 #if 0 /* unused */
133 static const u32 trinity_mgcg_shls_disable[] =
134 {
135 	/* Register, Value, Mask */
136 	0x0000802c, 0xc0000000, 0xffffffff,
137 	0x00009150, 0x00600000, 0xffffffff,
138 	0x000008f8, 0x00000000, 0xffffffff,
139 	0x000008fc, 0xffffffff, 0x000133FF,
140 	0x000008f8, 0x00000001, 0xffffffff,
141 	0x000008fc, 0xffffffff, 0xE00B03FC
142 };
143 #endif
144 #endif
145 
146 #ifndef TRINITY_SYSLS_SEQUENCE
147 #define TRINITY_SYSLS_SEQUENCE  100
148 
149 #if 0 /* unused */
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 #endif
172 
173 static const u32 trinity_sysls_disable[] =
174 {
175 	/* Register, Value, Mask */
176 	0x0000d0c0, 0x00000000, 0xffffffff,
177 	0x0000d8c0, 0x00000000, 0xffffffff,
178 	0x000055e8, 0x00000000, 0xffffffff,
179 	0x0000d0bc, 0x00000000, 0xffffffff,
180 	0x0000d8bc, 0x00000000, 0xffffffff,
181 	0x000015c0, 0x00041401, 0xffffffff,
182 	0x0000264c, 0x00040400, 0xffffffff,
183 	0x00002648, 0x00040400, 0xffffffff,
184 	0x00002650, 0x00040400, 0xffffffff,
185 	0x000020b8, 0x00040400, 0xffffffff,
186 	0x000020bc, 0x00040400, 0xffffffff,
187 	0x000020c0, 0x00040c80, 0xffffffff,
188 	0x0000f4a0, 0x000000c0, 0xffffffff,
189 	0x0000f4a4, 0x00680000, 0xffffffff,
190 	0x00002f50, 0x00000404, 0xffffffff,
191 	0x000004c8, 0x00000001, 0xffffffff,
192 	0x0000641c, 0x00007ffd, 0xffffffff,
193 	0x00000c7c, 0x0000ff00, 0xffffffff,
194 	0x00006dfc, 0x0000007f, 0xffffffff
195 };
196 
197 static const u32 trinity_sysls_enable[] =
198 {
199 	/* Register, Value, Mask */
200 	0x000055e8, 0x00000001, 0xffffffff,
201 	0x0000d0bc, 0x00000100, 0xffffffff,
202 	0x0000d8bc, 0x00000100, 0xffffffff,
203 	0x000015c0, 0x000c1401, 0xffffffff,
204 	0x0000264c, 0x000c0400, 0xffffffff,
205 	0x00002648, 0x000c0400, 0xffffffff,
206 	0x00002650, 0x000c0400, 0xffffffff,
207 	0x000020b8, 0x000c0400, 0xffffffff,
208 	0x000020bc, 0x000c0400, 0xffffffff,
209 	0x000020c0, 0x000c0c80, 0xffffffff,
210 	0x0000f4a0, 0x000000c0, 0xffffffff,
211 	0x0000f4a4, 0x00680fff, 0xffffffff,
212 	0x00002f50, 0x00000903, 0xffffffff,
213 	0x000004c8, 0x00000000, 0xffffffff,
214 	0x0000641c, 0x00000000, 0xffffffff,
215 	0x00000c7c, 0x00000000, 0xffffffff,
216 	0x00006dfc, 0x00000000, 0xffffffff
217 };
218 #endif
219 
220 static const u32 trinity_override_mgpg_sequences[] =
221 {
222 	/* Register, Value */
223 	0x00000200, 0xE030032C,
224 	0x00000204, 0x00000FFF,
225 	0x00000200, 0xE0300058,
226 	0x00000204, 0x00030301,
227 	0x00000200, 0xE0300054,
228 	0x00000204, 0x500010FF,
229 	0x00000200, 0xE0300074,
230 	0x00000204, 0x00030301,
231 	0x00000200, 0xE0300070,
232 	0x00000204, 0x500010FF,
233 	0x00000200, 0xE0300090,
234 	0x00000204, 0x00030301,
235 	0x00000200, 0xE030008C,
236 	0x00000204, 0x500010FF,
237 	0x00000200, 0xE03000AC,
238 	0x00000204, 0x00030301,
239 	0x00000200, 0xE03000A8,
240 	0x00000204, 0x500010FF,
241 	0x00000200, 0xE03000C8,
242 	0x00000204, 0x00030301,
243 	0x00000200, 0xE03000C4,
244 	0x00000204, 0x500010FF,
245 	0x00000200, 0xE03000E4,
246 	0x00000204, 0x00030301,
247 	0x00000200, 0xE03000E0,
248 	0x00000204, 0x500010FF,
249 	0x00000200, 0xE0300100,
250 	0x00000204, 0x00030301,
251 	0x00000200, 0xE03000FC,
252 	0x00000204, 0x500010FF,
253 	0x00000200, 0xE0300058,
254 	0x00000204, 0x00030303,
255 	0x00000200, 0xE0300054,
256 	0x00000204, 0x600010FF,
257 	0x00000200, 0xE0300074,
258 	0x00000204, 0x00030303,
259 	0x00000200, 0xE0300070,
260 	0x00000204, 0x600010FF,
261 	0x00000200, 0xE0300090,
262 	0x00000204, 0x00030303,
263 	0x00000200, 0xE030008C,
264 	0x00000204, 0x600010FF,
265 	0x00000200, 0xE03000AC,
266 	0x00000204, 0x00030303,
267 	0x00000200, 0xE03000A8,
268 	0x00000204, 0x600010FF,
269 	0x00000200, 0xE03000C8,
270 	0x00000204, 0x00030303,
271 	0x00000200, 0xE03000C4,
272 	0x00000204, 0x600010FF,
273 	0x00000200, 0xE03000E4,
274 	0x00000204, 0x00030303,
275 	0x00000200, 0xE03000E0,
276 	0x00000204, 0x600010FF,
277 	0x00000200, 0xE0300100,
278 	0x00000204, 0x00030303,
279 	0x00000200, 0xE03000FC,
280 	0x00000204, 0x600010FF,
281 	0x00000200, 0xE0300058,
282 	0x00000204, 0x00030303,
283 	0x00000200, 0xE0300054,
284 	0x00000204, 0x700010FF,
285 	0x00000200, 0xE0300074,
286 	0x00000204, 0x00030303,
287 	0x00000200, 0xE0300070,
288 	0x00000204, 0x700010FF,
289 	0x00000200, 0xE0300090,
290 	0x00000204, 0x00030303,
291 	0x00000200, 0xE030008C,
292 	0x00000204, 0x700010FF,
293 	0x00000200, 0xE03000AC,
294 	0x00000204, 0x00030303,
295 	0x00000200, 0xE03000A8,
296 	0x00000204, 0x700010FF,
297 	0x00000200, 0xE03000C8,
298 	0x00000204, 0x00030303,
299 	0x00000200, 0xE03000C4,
300 	0x00000204, 0x700010FF,
301 	0x00000200, 0xE03000E4,
302 	0x00000204, 0x00030303,
303 	0x00000200, 0xE03000E0,
304 	0x00000204, 0x700010FF,
305 	0x00000200, 0xE0300100,
306 	0x00000204, 0x00030303,
307 	0x00000200, 0xE03000FC,
308 	0x00000204, 0x700010FF,
309 	0x00000200, 0xE0300058,
310 	0x00000204, 0x00010303,
311 	0x00000200, 0xE0300054,
312 	0x00000204, 0x800010FF,
313 	0x00000200, 0xE0300074,
314 	0x00000204, 0x00010303,
315 	0x00000200, 0xE0300070,
316 	0x00000204, 0x800010FF,
317 	0x00000200, 0xE0300090,
318 	0x00000204, 0x00010303,
319 	0x00000200, 0xE030008C,
320 	0x00000204, 0x800010FF,
321 	0x00000200, 0xE03000AC,
322 	0x00000204, 0x00010303,
323 	0x00000200, 0xE03000A8,
324 	0x00000204, 0x800010FF,
325 	0x00000200, 0xE03000C4,
326 	0x00000204, 0x800010FF,
327 	0x00000200, 0xE03000C8,
328 	0x00000204, 0x00010303,
329 	0x00000200, 0xE03000E4,
330 	0x00000204, 0x00010303,
331 	0x00000200, 0xE03000E0,
332 	0x00000204, 0x800010FF,
333 	0x00000200, 0xE0300100,
334 	0x00000204, 0x00010303,
335 	0x00000200, 0xE03000FC,
336 	0x00000204, 0x800010FF,
337 	0x00000200, 0x0001f198,
338 	0x00000204, 0x0003ffff,
339 	0x00000200, 0x0001f19C,
340 	0x00000204, 0x3fffffff,
341 	0x00000200, 0xE030032C,
342 	0x00000204, 0x00000000,
343 };
344 
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_program_ttt(struct radeon_device *rdev)
995 {
996 	struct trinity_power_info *pi = trinity_get_pi(rdev);
997 	u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
998 
999 	value &= ~(HT_MASK | LT_MASK);
1000 	value |= HT((pi->thermal_auto_throttling + 49) * 8);
1001 	value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
1002 	WREG32_SMC(SMU_SCLK_DPM_TTT, value);
1003 }
1004 
1005 static void trinity_enable_att(struct radeon_device *rdev)
1006 {
1007 	u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
1008 
1009 	value &= ~SCLK_TT_EN_MASK;
1010 	value |= SCLK_TT_EN(1);
1011 	WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
1012 }
1013 
1014 static void trinity_program_sclk_dpm(struct radeon_device *rdev)
1015 {
1016 	u32 p, u;
1017 	u32 tp = RREG32_SMC(PM_TP);
1018 	u32 ni;
1019 	u32 xclk = radeon_get_xclk(rdev);
1020 	u32 value;
1021 
1022 	r600_calculate_u_and_p(400, xclk, 16, &p, &u);
1023 
1024 	ni = (p + tp - 1) / tp;
1025 
1026 	value = RREG32_SMC(PM_I_CNTL_1);
1027 	value &= ~SCLK_DPM_MASK;
1028 	value |= SCLK_DPM(ni);
1029 	WREG32_SMC(PM_I_CNTL_1, value);
1030 }
1031 
1032 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
1033 						 int min_temp, int max_temp)
1034 {
1035 	int low_temp = 0 * 1000;
1036 	int high_temp = 255 * 1000;
1037 
1038         if (low_temp < min_temp)
1039 		low_temp = min_temp;
1040         if (high_temp > max_temp)
1041 		high_temp = max_temp;
1042         if (high_temp < low_temp) {
1043 		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
1044                 return -EINVAL;
1045         }
1046 
1047 	WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
1048 	WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
1049 
1050 	rdev->pm.dpm.thermal.min_temp = low_temp;
1051 	rdev->pm.dpm.thermal.max_temp = high_temp;
1052 
1053 	return 0;
1054 }
1055 
1056 static void trinity_update_current_ps(struct radeon_device *rdev,
1057 				      struct radeon_ps *rps)
1058 {
1059 	struct trinity_ps *new_ps = trinity_get_ps(rps);
1060 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1061 
1062 	pi->current_rps = *rps;
1063 	pi->current_ps = *new_ps;
1064 	pi->current_rps.ps_priv = &pi->current_ps;
1065 }
1066 
1067 static void trinity_update_requested_ps(struct radeon_device *rdev,
1068 					struct radeon_ps *rps)
1069 {
1070 	struct trinity_ps *new_ps = trinity_get_ps(rps);
1071 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1072 
1073 	pi->requested_rps = *rps;
1074 	pi->requested_ps = *new_ps;
1075 	pi->requested_rps.ps_priv = &pi->requested_ps;
1076 }
1077 
1078 void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
1079 {
1080 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1081 
1082 	if (pi->enable_bapm) {
1083 		trinity_acquire_mutex(rdev);
1084 		trinity_dpm_bapm_enable(rdev, enable);
1085 		trinity_release_mutex(rdev);
1086 	}
1087 }
1088 
1089 int trinity_dpm_enable(struct radeon_device *rdev)
1090 {
1091 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1092 
1093 	trinity_acquire_mutex(rdev);
1094 
1095 	if (trinity_dpm_enabled(rdev)) {
1096 		trinity_release_mutex(rdev);
1097 		return -EINVAL;
1098 	}
1099 
1100 	trinity_program_bootup_state(rdev);
1101 	sumo_program_vc(rdev, 0x00C00033);
1102 	trinity_start_am(rdev);
1103 	if (pi->enable_auto_thermal_throttling) {
1104 		trinity_program_ttt(rdev);
1105 		trinity_enable_att(rdev);
1106 	}
1107 	trinity_program_sclk_dpm(rdev);
1108 	trinity_start_dpm(rdev);
1109 	trinity_wait_for_dpm_enabled(rdev);
1110 	trinity_dpm_bapm_enable(rdev, false);
1111 	trinity_release_mutex(rdev);
1112 
1113 	trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1114 
1115 	return 0;
1116 }
1117 
1118 int trinity_dpm_late_enable(struct radeon_device *rdev)
1119 {
1120 	int ret;
1121 
1122 	trinity_acquire_mutex(rdev);
1123 	trinity_enable_clock_power_gating(rdev);
1124 
1125 	if (rdev->irq.installed &&
1126 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1127 		ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
1128 		if (ret) {
1129 			trinity_release_mutex(rdev);
1130 			return ret;
1131 		}
1132 		rdev->irq.dpm_thermal = true;
1133 		radeon_irq_set(rdev);
1134 	}
1135 	trinity_release_mutex(rdev);
1136 
1137 	return 0;
1138 }
1139 
1140 void trinity_dpm_disable(struct radeon_device *rdev)
1141 {
1142 	trinity_acquire_mutex(rdev);
1143 	if (!trinity_dpm_enabled(rdev)) {
1144 		trinity_release_mutex(rdev);
1145 		return;
1146 	}
1147 	trinity_dpm_bapm_enable(rdev, false);
1148 	trinity_disable_clock_power_gating(rdev);
1149 	sumo_clear_vc(rdev);
1150 	trinity_wait_for_level_0(rdev);
1151 	trinity_stop_dpm(rdev);
1152 	trinity_reset_am(rdev);
1153 	trinity_release_mutex(rdev);
1154 
1155 	if (rdev->irq.installed &&
1156 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1157 		rdev->irq.dpm_thermal = false;
1158 		radeon_irq_set(rdev);
1159 	}
1160 
1161 	trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1162 }
1163 
1164 static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
1165 {
1166 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1167 
1168 	pi->min_sclk_did =
1169 		(RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
1170 }
1171 
1172 static void trinity_setup_nbp_sim(struct radeon_device *rdev,
1173 				  struct radeon_ps *rps)
1174 {
1175 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1176 	struct trinity_ps *new_ps = trinity_get_ps(rps);
1177 	u32 nbpsconfig;
1178 
1179 	if (pi->sys_info.nb_dpm_enable) {
1180 		nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
1181 		nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
1182 		nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
1183 			       Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
1184 			       DpmXNbPsLo(new_ps->DpmXNbPsLo) |
1185 			       DpmXNbPsHi(new_ps->DpmXNbPsHi));
1186 		WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
1187 	}
1188 }
1189 
1190 int trinity_dpm_force_performance_level(struct radeon_device *rdev,
1191 					enum radeon_dpm_forced_level level)
1192 {
1193 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1194 	struct radeon_ps *rps = &pi->current_rps;
1195 	struct trinity_ps *ps = trinity_get_ps(rps);
1196 	int i, ret;
1197 
1198 	if (ps->num_levels <= 1)
1199 		return 0;
1200 
1201 	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
1202 		/* not supported by the hw */
1203 		return -EINVAL;
1204 	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
1205 		ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1);
1206 		if (ret)
1207 			return ret;
1208 	} else {
1209 		for (i = 0; i < ps->num_levels; i++) {
1210 			ret = trinity_dpm_n_levels_disabled(rdev, 0);
1211 			if (ret)
1212 				return ret;
1213 		}
1214 	}
1215 
1216 	rdev->pm.dpm.forced_level = level;
1217 
1218 	return 0;
1219 }
1220 
1221 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev)
1222 {
1223 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1224 	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
1225 	struct radeon_ps *new_ps = &requested_ps;
1226 
1227 	trinity_update_requested_ps(rdev, new_ps);
1228 
1229 	trinity_apply_state_adjust_rules(rdev,
1230 					 &pi->requested_rps,
1231 					 &pi->current_rps);
1232 
1233 	return 0;
1234 }
1235 
1236 int trinity_dpm_set_power_state(struct radeon_device *rdev)
1237 {
1238 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1239 	struct radeon_ps *new_ps = &pi->requested_rps;
1240 	struct radeon_ps *old_ps = &pi->current_rps;
1241 
1242 	trinity_acquire_mutex(rdev);
1243 	if (pi->enable_dpm) {
1244 		if (pi->enable_bapm)
1245 			trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power);
1246 		trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
1247 		trinity_enable_power_level_0(rdev);
1248 		trinity_force_level_0(rdev);
1249 		trinity_wait_for_level_0(rdev);
1250 		trinity_setup_nbp_sim(rdev, new_ps);
1251 		trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
1252 		trinity_force_level_0(rdev);
1253 		trinity_unforce_levels(rdev);
1254 		trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1255 	}
1256 	trinity_release_mutex(rdev);
1257 
1258 	return 0;
1259 }
1260 
1261 void trinity_dpm_post_set_power_state(struct radeon_device *rdev)
1262 {
1263 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1264 	struct radeon_ps *new_ps = &pi->requested_rps;
1265 
1266 	trinity_update_current_ps(rdev, new_ps);
1267 }
1268 
1269 void trinity_dpm_setup_asic(struct radeon_device *rdev)
1270 {
1271 	trinity_acquire_mutex(rdev);
1272 	sumo_program_sstp(rdev);
1273 	sumo_take_smu_control(rdev, true);
1274 	trinity_get_min_sclk_divider(rdev);
1275 	trinity_release_mutex(rdev);
1276 }
1277 
1278 #if 0
1279 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1280 {
1281 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1282 
1283 	trinity_acquire_mutex(rdev);
1284 	if (pi->enable_dpm) {
1285 		trinity_enable_power_level_0(rdev);
1286 		trinity_force_level_0(rdev);
1287 		trinity_wait_for_level_0(rdev);
1288 		trinity_program_bootup_state(rdev);
1289 		trinity_force_level_0(rdev);
1290 		trinity_unforce_levels(rdev);
1291 	}
1292 	trinity_release_mutex(rdev);
1293 }
1294 #endif
1295 
1296 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1297 						  u32 vid_2bit)
1298 {
1299 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1300 	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1301 	u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1302 	u32 step = (svi_mode == 0) ? 1250 : 625;
1303 	u32 delta = vid_7bit * step + 50;
1304 
1305 	if (delta > 155000)
1306 		return 0;
1307 
1308 	return (155000 - delta) / 100;
1309 }
1310 
1311 static void trinity_patch_boot_state(struct radeon_device *rdev,
1312 				     struct trinity_ps *ps)
1313 {
1314 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1315 
1316 	ps->num_levels = 1;
1317 	ps->nbps_flags = 0;
1318 	ps->bapm_flags = 0;
1319 	ps->levels[0] = pi->boot_pl;
1320 }
1321 
1322 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1323 {
1324 	if (sclk < 20000)
1325 		return 1;
1326 	return 0;
1327 }
1328 
1329 static void trinity_construct_boot_state(struct radeon_device *rdev)
1330 {
1331 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1332 
1333 	pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1334 	pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1335 	pi->boot_pl.ds_divider_index = 0;
1336 	pi->boot_pl.ss_divider_index = 0;
1337 	pi->boot_pl.allow_gnb_slow = 1;
1338 	pi->boot_pl.force_nbp_state = 0;
1339 	pi->boot_pl.display_wm = 0;
1340 	pi->boot_pl.vce_wm = 0;
1341 	pi->current_ps.num_levels = 1;
1342 	pi->current_ps.levels[0] = pi->boot_pl;
1343 }
1344 
1345 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1346 						  u32 sclk, u32 min_sclk_in_sr)
1347 {
1348 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1349 	u32 i;
1350 	u32 temp;
1351 	u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1352 		min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1353 
1354 	if (sclk < min)
1355 		return 0;
1356 
1357 	if (!pi->enable_sclk_ds)
1358 		return 0;
1359 
1360 	for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
1361 		temp = sclk / sumo_get_sleep_divider_from_id(i);
1362 		if (temp >= min || i == 0)
1363 			break;
1364 	}
1365 
1366 	return (u8)i;
1367 }
1368 
1369 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1370 					  u32 lower_limit)
1371 {
1372 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1373 	u32 i;
1374 
1375 	for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1376 		if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1377 			return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1378 	}
1379 
1380 	if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1381 		DRM_ERROR("engine clock out of range!");
1382 
1383 	return 0;
1384 }
1385 
1386 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1387 					struct trinity_ps *ps,
1388 					struct trinity_ps *current_ps)
1389 {
1390 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1391 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1392 	u32 current_vddc;
1393 	u32 current_sclk;
1394 	u32 current_index = 0;
1395 
1396 	if (current_ps) {
1397 		current_vddc = current_ps->levels[current_index].vddc_index;
1398 		current_sclk = current_ps->levels[current_index].sclk;
1399 	} else {
1400 		current_vddc = pi->boot_pl.vddc_index;
1401 		current_sclk = pi->boot_pl.sclk;
1402 	}
1403 
1404 	ps->levels[0].vddc_index = current_vddc;
1405 
1406 	if (ps->levels[0].sclk > current_sclk)
1407 		ps->levels[0].sclk = current_sclk;
1408 
1409 	ps->levels[0].ds_divider_index =
1410 		trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1411 	ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1412 	ps->levels[0].allow_gnb_slow = 1;
1413 	ps->levels[0].force_nbp_state = 0;
1414 	ps->levels[0].display_wm = 0;
1415 	ps->levels[0].vce_wm =
1416 		trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1417 }
1418 
1419 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1420 				       struct trinity_ps *ps, u32 index)
1421 {
1422 	if (ps == NULL || ps->num_levels <= 1)
1423 		return 0;
1424 	else if (ps->num_levels == 2) {
1425 		if (index == 0)
1426 			return 0;
1427 		else
1428 			return 1;
1429 	} else {
1430 		if (index == 0)
1431 			return 0;
1432 		else if (ps->levels[index].sclk < 30000)
1433 			return 0;
1434 		else
1435 			return 1;
1436 	}
1437 }
1438 
1439 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
1440 				       struct radeon_ps *rps)
1441 {
1442 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1443 	u32 i = 0;
1444 
1445 	for (i = 0; i < 4; i++) {
1446 		if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
1447 		    (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
1448 		    break;
1449 	}
1450 
1451 	if (i >= 4) {
1452 		DRM_ERROR("UVD clock index not found!\n");
1453 		i = 3;
1454 	}
1455 	return i;
1456 }
1457 
1458 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1459 				     struct radeon_ps *rps)
1460 {
1461 	struct trinity_ps *ps = trinity_get_ps(rps);
1462 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1463 	u32 high_index = 0;
1464 	u32 low_index = 0;
1465 
1466 	if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
1467 		high_index = trinity_get_uvd_clock_index(rdev, rps);
1468 
1469 		switch(high_index) {
1470 		case 3:
1471 		case 2:
1472 			low_index = 1;
1473 			break;
1474 		case 1:
1475 		case 0:
1476 		default:
1477 			low_index = 0;
1478 			break;
1479 		}
1480 
1481 		ps->vclk_low_divider =
1482 			pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
1483 		ps->dclk_low_divider =
1484 			pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
1485 		ps->vclk_high_divider =
1486 			pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
1487 		ps->dclk_high_divider =
1488 			pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
1489 	}
1490 }
1491 
1492 
1493 
1494 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1495 					     struct radeon_ps *new_rps,
1496 					     struct radeon_ps *old_rps)
1497 {
1498 	struct trinity_ps *ps = trinity_get_ps(new_rps);
1499 	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
1500 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1501 	u32 min_voltage = 0; /* ??? */
1502 	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1503 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1504 	u32 i;
1505 	bool force_high;
1506 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1507 
1508 	if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1509 		return trinity_patch_thermal_state(rdev, ps, current_ps);
1510 
1511 	trinity_adjust_uvd_state(rdev, new_rps);
1512 
1513 	for (i = 0; i < ps->num_levels; i++) {
1514 		if (ps->levels[i].vddc_index < min_voltage)
1515 			ps->levels[i].vddc_index = min_voltage;
1516 
1517 		if (ps->levels[i].sclk < min_sclk)
1518 			ps->levels[i].sclk =
1519 				trinity_get_valid_engine_clock(rdev, min_sclk);
1520 
1521 		ps->levels[i].ds_divider_index =
1522 			sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1523 
1524 		ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1525 
1526 		ps->levels[i].allow_gnb_slow = 1;
1527 		ps->levels[i].force_nbp_state = 0;
1528 		ps->levels[i].display_wm =
1529 			trinity_calculate_display_wm(rdev, ps, i);
1530 		ps->levels[i].vce_wm =
1531 			trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1532 	}
1533 
1534 	if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1535 	    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1536 		ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1537 
1538 	if (pi->sys_info.nb_dpm_enable) {
1539 		ps->Dpm0PgNbPsLo = 0x1;
1540 		ps->Dpm0PgNbPsHi = 0x0;
1541 		ps->DpmXNbPsLo = 0x2;
1542 		ps->DpmXNbPsHi = 0x1;
1543 
1544 		if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1545 		    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1546 			force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1547 				      ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1548 				       (pi->sys_info.uma_channel_number == 1)));
1549 			force_high = (num_active_displays >= 3) || force_high;
1550 			ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1551 			ps->Dpm0PgNbPsHi = 0x1;
1552 			ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1553 			ps->DpmXNbPsHi = 0x2;
1554 			ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1555 		}
1556 	}
1557 }
1558 
1559 static void trinity_cleanup_asic(struct radeon_device *rdev)
1560 {
1561 	sumo_take_smu_control(rdev, false);
1562 }
1563 
1564 #if 0
1565 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1566 {
1567 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1568 
1569 	if (pi->voltage_drop_in_dce)
1570 		trinity_dce_enable_voltage_adjustment(rdev, false);
1571 }
1572 #endif
1573 
1574 static void trinity_add_dccac_value(struct radeon_device *rdev)
1575 {
1576 	u32 gpu_cac_avrg_cntl_window_size;
1577 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1578 	u64 disp_clk = rdev->clock.default_dispclk / 100;
1579 	u32 dc_cac_value;
1580 
1581 	gpu_cac_avrg_cntl_window_size =
1582 		(RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1583 
1584 	dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1585 			     (32 - gpu_cac_avrg_cntl_window_size));
1586 
1587 	WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1588 }
1589 
1590 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1591 {
1592 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1593 
1594 	if (pi->voltage_drop_in_dce)
1595 		trinity_dce_enable_voltage_adjustment(rdev, true);
1596 	trinity_add_dccac_value(rdev);
1597 }
1598 
1599 union power_info {
1600 	struct _ATOM_POWERPLAY_INFO info;
1601 	struct _ATOM_POWERPLAY_INFO_V2 info_2;
1602 	struct _ATOM_POWERPLAY_INFO_V3 info_3;
1603 	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1604 	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1605 	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1606 };
1607 
1608 union pplib_clock_info {
1609 	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1610 	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1611 	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1612 	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1613 };
1614 
1615 union pplib_power_state {
1616 	struct _ATOM_PPLIB_STATE v1;
1617 	struct _ATOM_PPLIB_STATE_V2 v2;
1618 };
1619 
1620 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1621 					       struct radeon_ps *rps,
1622 					       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1623 					       u8 table_rev)
1624 {
1625 	struct trinity_ps *ps = trinity_get_ps(rps);
1626 
1627 	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1628 	rps->class = le16_to_cpu(non_clock_info->usClassification);
1629 	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1630 
1631 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1632 		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1633 		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1634 	} else {
1635 		rps->vclk = 0;
1636 		rps->dclk = 0;
1637 	}
1638 
1639 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1640 		rdev->pm.dpm.boot_ps = rps;
1641 		trinity_patch_boot_state(rdev, ps);
1642 	}
1643 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1644 		rdev->pm.dpm.uvd_ps = rps;
1645 }
1646 
1647 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1648 					   struct radeon_ps *rps, int index,
1649 					   union pplib_clock_info *clock_info)
1650 {
1651 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1652 	struct trinity_ps *ps = trinity_get_ps(rps);
1653 	struct trinity_pl *pl = &ps->levels[index];
1654 	u32 sclk;
1655 
1656 	sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1657 	sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1658 	pl->sclk = sclk;
1659 	pl->vddc_index = clock_info->sumo.vddcIndex;
1660 
1661 	ps->num_levels = index + 1;
1662 
1663 	if (pi->enable_sclk_ds) {
1664 		pl->ds_divider_index = 5;
1665 		pl->ss_divider_index = 5;
1666 	}
1667 }
1668 
1669 static int trinity_parse_power_table(struct radeon_device *rdev)
1670 {
1671 	struct radeon_mode_info *mode_info = &rdev->mode_info;
1672 	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1673 	union pplib_power_state *power_state;
1674 	int i, j, k, non_clock_array_index, clock_array_index;
1675 	union pplib_clock_info *clock_info;
1676 	struct _StateArray *state_array;
1677 	struct _ClockInfoArray *clock_info_array;
1678 	struct _NonClockInfoArray *non_clock_info_array;
1679 	union power_info *power_info;
1680 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1681         u16 data_offset;
1682 	u8 frev, crev;
1683 	u8 *power_state_offset;
1684 	struct sumo_ps *ps;
1685 
1686 	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1687 				   &frev, &crev, &data_offset))
1688 		return -EINVAL;
1689 	power_info = (union power_info *)((uint8_t*)mode_info->atom_context->bios + data_offset);
1690 
1691 	state_array = (struct _StateArray *)
1692 		((uint8_t*)mode_info->atom_context->bios + data_offset +
1693 		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1694 	clock_info_array = (struct _ClockInfoArray *)
1695 		((uint8_t*)mode_info->atom_context->bios + data_offset +
1696 		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1697 	non_clock_info_array = (struct _NonClockInfoArray *)
1698 		((uint8_t*)mode_info->atom_context->bios + data_offset +
1699 		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1700 
1701 	rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
1702 				  state_array->ucNumEntries, GFP_KERNEL);
1703 	if (!rdev->pm.dpm.ps)
1704 		return -ENOMEM;
1705 	power_state_offset = (u8 *)state_array->states;
1706 	for (i = 0; i < state_array->ucNumEntries; i++) {
1707 		u8 *idx;
1708 		power_state = (union pplib_power_state *)power_state_offset;
1709 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
1710 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1711 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
1712 		if (!rdev->pm.power_state[i].clock_info)
1713 			return -EINVAL;
1714 		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1715 		if (ps == NULL) {
1716 			kfree(rdev->pm.dpm.ps);
1717 			return -ENOMEM;
1718 		}
1719 		rdev->pm.dpm.ps[i].ps_priv = ps;
1720 		k = 0;
1721 		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
1722 		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1723 			clock_array_index = idx[j];
1724 			if (clock_array_index >= clock_info_array->ucNumEntries)
1725 				continue;
1726 			if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1727 				break;
1728 			clock_info = (union pplib_clock_info *)
1729 				((u8 *)&clock_info_array->clockInfo[0] +
1730 				 (clock_array_index * clock_info_array->ucEntrySize));
1731 			trinity_parse_pplib_clock_info(rdev,
1732 						       &rdev->pm.dpm.ps[i], k,
1733 						       clock_info);
1734 			k++;
1735 		}
1736 		trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1737 						   non_clock_info,
1738 						   non_clock_info_array->ucEntrySize);
1739 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1740 	}
1741 	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1742 	return 0;
1743 }
1744 
1745 union igp_info {
1746 	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1747 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1748 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1749 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1750 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1751 };
1752 
1753 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
1754 {
1755 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1756 	u32 divider;
1757 
1758 	if (did >= 8 && did <= 0x3f)
1759 		divider = did * 25;
1760 	else if (did > 0x3f && did <= 0x5f)
1761 		divider = (did - 64) * 50 + 1600;
1762 	else if (did > 0x5f && did <= 0x7e)
1763 		divider = (did - 96) * 100 + 3200;
1764 	else if (did == 0x7f)
1765 		divider = 128 * 100;
1766 	else
1767 		return 10000;
1768 
1769 	return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
1770 }
1771 
1772 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1773 {
1774 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1775 	struct radeon_mode_info *mode_info = &rdev->mode_info;
1776 	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1777 	union igp_info *igp_info;
1778 	u8 frev, crev;
1779 	u16 data_offset;
1780 	int i;
1781 
1782 	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1783 				   &frev, &crev, &data_offset)) {
1784 		igp_info = (union igp_info *)((uint8_t*)mode_info->atom_context->bios +
1785 					      data_offset);
1786 
1787 		if (crev != 7) {
1788 			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1789 			return -EINVAL;
1790 		}
1791 		pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1792 		pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1793 		pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1794 		pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
1795 		pi->sys_info.bootup_nb_voltage_index =
1796 			le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1797 		if (igp_info->info_7.ucHtcTmpLmt == 0)
1798 			pi->sys_info.htc_tmp_lmt = 203;
1799 		else
1800 			pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1801 		if (igp_info->info_7.ucHtcHystLmt == 0)
1802 			pi->sys_info.htc_hyst_lmt = 5;
1803 		else
1804 			pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1805 		if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1806 			DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1807 		}
1808 
1809 		if (pi->enable_nbps_policy)
1810 			pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1811 		else
1812 			pi->sys_info.nb_dpm_enable = 0;
1813 
1814 		for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1815 			pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1816 			pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1817 		}
1818 
1819 		pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1820 		pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1821 		pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1822 		pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1823 
1824 		if (!pi->sys_info.nb_dpm_enable) {
1825 			for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1826 				pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1827 				pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1828 				pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1829 			}
1830 		}
1831 
1832 		pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1833 
1834 		sumo_construct_sclk_voltage_mapping_table(rdev,
1835 							  &pi->sys_info.sclk_voltage_mapping_table,
1836 							  igp_info->info_7.sAvail_SCLK);
1837 		sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1838 						 igp_info->info_7.sAvail_SCLK);
1839 
1840 		pi->sys_info.uvd_clock_table_entries[0].vclk_did =
1841 			igp_info->info_7.ucDPMState0VclkFid;
1842 		pi->sys_info.uvd_clock_table_entries[1].vclk_did =
1843 			igp_info->info_7.ucDPMState1VclkFid;
1844 		pi->sys_info.uvd_clock_table_entries[2].vclk_did =
1845 			igp_info->info_7.ucDPMState2VclkFid;
1846 		pi->sys_info.uvd_clock_table_entries[3].vclk_did =
1847 			igp_info->info_7.ucDPMState3VclkFid;
1848 
1849 		pi->sys_info.uvd_clock_table_entries[0].dclk_did =
1850 			igp_info->info_7.ucDPMState0DclkFid;
1851 		pi->sys_info.uvd_clock_table_entries[1].dclk_did =
1852 			igp_info->info_7.ucDPMState1DclkFid;
1853 		pi->sys_info.uvd_clock_table_entries[2].dclk_did =
1854 			igp_info->info_7.ucDPMState2DclkFid;
1855 		pi->sys_info.uvd_clock_table_entries[3].dclk_did =
1856 			igp_info->info_7.ucDPMState3DclkFid;
1857 
1858 		for (i = 0; i < 4; i++) {
1859 			pi->sys_info.uvd_clock_table_entries[i].vclk =
1860 				trinity_convert_did_to_freq(rdev,
1861 							    pi->sys_info.uvd_clock_table_entries[i].vclk_did);
1862 			pi->sys_info.uvd_clock_table_entries[i].dclk =
1863 				trinity_convert_did_to_freq(rdev,
1864 							    pi->sys_info.uvd_clock_table_entries[i].dclk_did);
1865 		}
1866 
1867 
1868 
1869 	}
1870 	return 0;
1871 }
1872 
1873 int trinity_dpm_init(struct radeon_device *rdev)
1874 {
1875 	struct trinity_power_info *pi;
1876 	int ret, i;
1877 
1878 	pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1879 	if (pi == NULL)
1880 		return -ENOMEM;
1881 	rdev->pm.dpm.priv = pi;
1882 
1883 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1884 		pi->at[i] = TRINITY_AT_DFLT;
1885 
1886 	if (radeon_bapm == -1) {
1887 		/* There are stability issues reported on with
1888 		 * bapm enabled when switching between AC and battery
1889 		 * power.  At the same time, some MSI boards hang
1890 		 * if it's not enabled and dpm is enabled.  Just enable
1891 		 * it for MSI boards right now.
1892 		 */
1893 		if (rdev->pdev->subsystem_vendor == 0x1462)
1894 			pi->enable_bapm = true;
1895 		else
1896 			pi->enable_bapm = false;
1897 	} else if (radeon_bapm == 0) {
1898 		pi->enable_bapm = false;
1899 	} else {
1900 		pi->enable_bapm = true;
1901 	}
1902 	pi->enable_nbps_policy = true;
1903 	pi->enable_sclk_ds = true;
1904 	pi->enable_gfx_power_gating = true;
1905 	pi->enable_gfx_clock_gating = true;
1906 	pi->enable_mg_clock_gating = false;
1907 	pi->enable_gfx_dynamic_mgpg = false;
1908 	pi->override_dynamic_mgpg = false;
1909 	pi->enable_auto_thermal_throttling = true;
1910 	pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1911 	pi->uvd_dpm = true; /* ??? */
1912 
1913 	ret = trinity_parse_sys_info_table(rdev);
1914 	if (ret)
1915 		return ret;
1916 
1917 	trinity_construct_boot_state(rdev);
1918 
1919 	ret = r600_get_platform_caps(rdev);
1920 	if (ret)
1921 		return ret;
1922 
1923 	ret = trinity_parse_power_table(rdev);
1924 	if (ret)
1925 		return ret;
1926 
1927 	pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1928 	pi->enable_dpm = true;
1929 
1930 	return 0;
1931 }
1932 
1933 void trinity_dpm_print_power_state(struct radeon_device *rdev,
1934 				   struct radeon_ps *rps)
1935 {
1936 	int i;
1937 	struct trinity_ps *ps = trinity_get_ps(rps);
1938 
1939 	r600_dpm_print_class_info(rps->class, rps->class2);
1940 	r600_dpm_print_cap_info(rps->caps);
1941 	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1942 	for (i = 0; i < ps->num_levels; i++) {
1943 		struct trinity_pl *pl = &ps->levels[i];
1944 		printk("\t\tpower level %d    sclk: %u vddc: %u\n",
1945 		       i, pl->sclk,
1946 		       trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1947 	}
1948 	r600_dpm_print_ps_status(rdev, rps);
1949 }
1950 
1951 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
1952 							 struct seq_file *m)
1953 {
1954 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1955 	struct radeon_ps *rps = &pi->current_rps;
1956 	struct trinity_ps *ps = trinity_get_ps(rps);
1957 	struct trinity_pl *pl;
1958 	u32 current_index =
1959 		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
1960 		CURRENT_STATE_SHIFT;
1961 
1962 	if (current_index >= ps->num_levels) {
1963 		seq_printf(m, "invalid dpm profile %d\n", current_index);
1964 	} else {
1965 		pl = &ps->levels[current_index];
1966 		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1967 		seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
1968 			   current_index, pl->sclk,
1969 			   trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1970 	}
1971 }
1972 
1973 void trinity_dpm_fini(struct radeon_device *rdev)
1974 {
1975 	int i;
1976 
1977 	trinity_cleanup_asic(rdev); /* ??? */
1978 
1979 	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1980 		kfree(rdev->pm.dpm.ps[i].ps_priv);
1981 	}
1982 	kfree(rdev->pm.dpm.ps);
1983 	kfree(rdev->pm.dpm.priv);
1984 }
1985 
1986 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
1987 {
1988 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1989 	struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
1990 
1991 	if (low)
1992 		return requested_state->levels[0].sclk;
1993 	else
1994 		return requested_state->levels[requested_state->num_levels - 1].sclk;
1995 }
1996 
1997 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
1998 {
1999 	struct trinity_power_info *pi = trinity_get_pi(rdev);
2000 
2001 	return pi->sys_info.bootup_uma_clk;
2002 }
2003