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