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