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