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