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 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1273 {
1274 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1275 
1276 	trinity_acquire_mutex(rdev);
1277 	if (pi->enable_dpm) {
1278 		trinity_enable_power_level_0(rdev);
1279 		trinity_force_level_0(rdev);
1280 		trinity_wait_for_level_0(rdev);
1281 		trinity_program_bootup_state(rdev);
1282 		trinity_force_level_0(rdev);
1283 		trinity_unforce_levels(rdev);
1284 	}
1285 	trinity_release_mutex(rdev);
1286 }
1287 
1288 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1289 						  u32 vid_2bit)
1290 {
1291 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1292 	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1293 	u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1294 	u32 step = (svi_mode == 0) ? 1250 : 625;
1295 	u32 delta = vid_7bit * step + 50;
1296 
1297 	if (delta > 155000)
1298 		return 0;
1299 
1300 	return (155000 - delta) / 100;
1301 }
1302 
1303 static void trinity_patch_boot_state(struct radeon_device *rdev,
1304 				     struct trinity_ps *ps)
1305 {
1306 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1307 
1308 	ps->num_levels = 1;
1309 	ps->nbps_flags = 0;
1310 	ps->bapm_flags = 0;
1311 	ps->levels[0] = pi->boot_pl;
1312 }
1313 
1314 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1315 {
1316 	if (sclk < 20000)
1317 		return 1;
1318 	return 0;
1319 }
1320 
1321 static void trinity_construct_boot_state(struct radeon_device *rdev)
1322 {
1323 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1324 
1325 	pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1326 	pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1327 	pi->boot_pl.ds_divider_index = 0;
1328 	pi->boot_pl.ss_divider_index = 0;
1329 	pi->boot_pl.allow_gnb_slow = 1;
1330 	pi->boot_pl.force_nbp_state = 0;
1331 	pi->boot_pl.display_wm = 0;
1332 	pi->boot_pl.vce_wm = 0;
1333 	pi->current_ps.num_levels = 1;
1334 	pi->current_ps.levels[0] = pi->boot_pl;
1335 }
1336 
1337 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1338 						  u32 sclk, u32 min_sclk_in_sr)
1339 {
1340 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1341 	u32 i;
1342 	u32 temp;
1343 	u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1344 		min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1345 
1346 	if (sclk < min)
1347 		return 0;
1348 
1349 	if (!pi->enable_sclk_ds)
1350 		return 0;
1351 
1352 	for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
1353 		temp = sclk / sumo_get_sleep_divider_from_id(i);
1354 		if (temp >= min || i == 0)
1355 			break;
1356 	}
1357 
1358 	return (u8)i;
1359 }
1360 
1361 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1362 					  u32 lower_limit)
1363 {
1364 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1365 	u32 i;
1366 
1367 	for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1368 		if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1369 			return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1370 	}
1371 
1372 	if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1373 		DRM_ERROR("engine clock out of range!");
1374 
1375 	return 0;
1376 }
1377 
1378 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1379 					struct trinity_ps *ps,
1380 					struct trinity_ps *current_ps)
1381 {
1382 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1383 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1384 	u32 current_vddc;
1385 	u32 current_sclk;
1386 	u32 current_index = 0;
1387 
1388 	if (current_ps) {
1389 		current_vddc = current_ps->levels[current_index].vddc_index;
1390 		current_sclk = current_ps->levels[current_index].sclk;
1391 	} else {
1392 		current_vddc = pi->boot_pl.vddc_index;
1393 		current_sclk = pi->boot_pl.sclk;
1394 	}
1395 
1396 	ps->levels[0].vddc_index = current_vddc;
1397 
1398 	if (ps->levels[0].sclk > current_sclk)
1399 		ps->levels[0].sclk = current_sclk;
1400 
1401 	ps->levels[0].ds_divider_index =
1402 		trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1403 	ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1404 	ps->levels[0].allow_gnb_slow = 1;
1405 	ps->levels[0].force_nbp_state = 0;
1406 	ps->levels[0].display_wm = 0;
1407 	ps->levels[0].vce_wm =
1408 		trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1409 }
1410 
1411 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1412 				       struct trinity_ps *ps, u32 index)
1413 {
1414 	if (ps == NULL || ps->num_levels <= 1)
1415 		return 0;
1416 	else if (ps->num_levels == 2) {
1417 		if (index == 0)
1418 			return 0;
1419 		else
1420 			return 1;
1421 	} else {
1422 		if (index == 0)
1423 			return 0;
1424 		else if (ps->levels[index].sclk < 30000)
1425 			return 0;
1426 		else
1427 			return 1;
1428 	}
1429 }
1430 
1431 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
1432 				       struct radeon_ps *rps)
1433 {
1434 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1435 	u32 i = 0;
1436 
1437 	for (i = 0; i < 4; i++) {
1438 		if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
1439 		    (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
1440 		    break;
1441 	}
1442 
1443 	if (i >= 4) {
1444 		DRM_ERROR("UVD clock index not found!\n");
1445 		i = 3;
1446 	}
1447 	return i;
1448 }
1449 
1450 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1451 				     struct radeon_ps *rps)
1452 {
1453 	struct trinity_ps *ps = trinity_get_ps(rps);
1454 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1455 	u32 high_index = 0;
1456 	u32 low_index = 0;
1457 
1458 	if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
1459 		high_index = trinity_get_uvd_clock_index(rdev, rps);
1460 
1461 		switch(high_index) {
1462 		case 3:
1463 		case 2:
1464 			low_index = 1;
1465 			break;
1466 		case 1:
1467 		case 0:
1468 		default:
1469 			low_index = 0;
1470 			break;
1471 		}
1472 
1473 		ps->vclk_low_divider =
1474 			pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
1475 		ps->dclk_low_divider =
1476 			pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
1477 		ps->vclk_high_divider =
1478 			pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
1479 		ps->dclk_high_divider =
1480 			pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
1481 	}
1482 }
1483 
1484 
1485 
1486 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1487 					     struct radeon_ps *new_rps,
1488 					     struct radeon_ps *old_rps)
1489 {
1490 	struct trinity_ps *ps = trinity_get_ps(new_rps);
1491 	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
1492 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1493 	u32 min_voltage = 0; /* ??? */
1494 	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1495 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1496 	u32 i;
1497 	bool force_high;
1498 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1499 
1500 	if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1501 		return trinity_patch_thermal_state(rdev, ps, current_ps);
1502 
1503 	trinity_adjust_uvd_state(rdev, new_rps);
1504 
1505 	for (i = 0; i < ps->num_levels; i++) {
1506 		if (ps->levels[i].vddc_index < min_voltage)
1507 			ps->levels[i].vddc_index = min_voltage;
1508 
1509 		if (ps->levels[i].sclk < min_sclk)
1510 			ps->levels[i].sclk =
1511 				trinity_get_valid_engine_clock(rdev, min_sclk);
1512 
1513 		ps->levels[i].ds_divider_index =
1514 			sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1515 
1516 		ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1517 
1518 		ps->levels[i].allow_gnb_slow = 1;
1519 		ps->levels[i].force_nbp_state = 0;
1520 		ps->levels[i].display_wm =
1521 			trinity_calculate_display_wm(rdev, ps, i);
1522 		ps->levels[i].vce_wm =
1523 			trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1524 	}
1525 
1526 	if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1527 	    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1528 		ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1529 
1530 	if (pi->sys_info.nb_dpm_enable) {
1531 		ps->Dpm0PgNbPsLo = 0x1;
1532 		ps->Dpm0PgNbPsHi = 0x0;
1533 		ps->DpmXNbPsLo = 0x2;
1534 		ps->DpmXNbPsHi = 0x1;
1535 
1536 		if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1537 		    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1538 			force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1539 				      ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1540 				       (pi->sys_info.uma_channel_number == 1)));
1541 			force_high = (num_active_displays >= 3) || force_high;
1542 			ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1543 			ps->Dpm0PgNbPsHi = 0x1;
1544 			ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1545 			ps->DpmXNbPsHi = 0x2;
1546 			ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1547 		}
1548 	}
1549 }
1550 
1551 static void trinity_cleanup_asic(struct radeon_device *rdev)
1552 {
1553 	sumo_take_smu_control(rdev, false);
1554 }
1555 
1556 #if 0
1557 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1558 {
1559 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1560 
1561 	if (pi->voltage_drop_in_dce)
1562 		trinity_dce_enable_voltage_adjustment(rdev, false);
1563 }
1564 #endif
1565 
1566 static void trinity_add_dccac_value(struct radeon_device *rdev)
1567 {
1568 	u32 gpu_cac_avrg_cntl_window_size;
1569 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1570 	u64 disp_clk = rdev->clock.default_dispclk / 100;
1571 	u32 dc_cac_value;
1572 
1573 	gpu_cac_avrg_cntl_window_size =
1574 		(RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1575 
1576 	dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1577 			     (32 - gpu_cac_avrg_cntl_window_size));
1578 
1579 	WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1580 }
1581 
1582 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1583 {
1584 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1585 
1586 	if (pi->voltage_drop_in_dce)
1587 		trinity_dce_enable_voltage_adjustment(rdev, true);
1588 	trinity_add_dccac_value(rdev);
1589 }
1590 
1591 union power_info {
1592 	struct _ATOM_POWERPLAY_INFO info;
1593 	struct _ATOM_POWERPLAY_INFO_V2 info_2;
1594 	struct _ATOM_POWERPLAY_INFO_V3 info_3;
1595 	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1596 	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1597 	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1598 };
1599 
1600 union pplib_clock_info {
1601 	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1602 	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1603 	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1604 	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1605 };
1606 
1607 union pplib_power_state {
1608 	struct _ATOM_PPLIB_STATE v1;
1609 	struct _ATOM_PPLIB_STATE_V2 v2;
1610 };
1611 
1612 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1613 					       struct radeon_ps *rps,
1614 					       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1615 					       u8 table_rev)
1616 {
1617 	struct trinity_ps *ps = trinity_get_ps(rps);
1618 
1619 	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1620 	rps->class = le16_to_cpu(non_clock_info->usClassification);
1621 	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1622 
1623 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1624 		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1625 		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1626 	} else {
1627 		rps->vclk = 0;
1628 		rps->dclk = 0;
1629 	}
1630 
1631 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1632 		rdev->pm.dpm.boot_ps = rps;
1633 		trinity_patch_boot_state(rdev, ps);
1634 	}
1635 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1636 		rdev->pm.dpm.uvd_ps = rps;
1637 }
1638 
1639 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1640 					   struct radeon_ps *rps, int index,
1641 					   union pplib_clock_info *clock_info)
1642 {
1643 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1644 	struct trinity_ps *ps = trinity_get_ps(rps);
1645 	struct trinity_pl *pl = &ps->levels[index];
1646 	u32 sclk;
1647 
1648 	sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1649 	sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1650 	pl->sclk = sclk;
1651 	pl->vddc_index = clock_info->sumo.vddcIndex;
1652 
1653 	ps->num_levels = index + 1;
1654 
1655 	if (pi->enable_sclk_ds) {
1656 		pl->ds_divider_index = 5;
1657 		pl->ss_divider_index = 5;
1658 	}
1659 }
1660 
1661 static int trinity_parse_power_table(struct radeon_device *rdev)
1662 {
1663 	struct radeon_mode_info *mode_info = &rdev->mode_info;
1664 	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1665 	union pplib_power_state *power_state;
1666 	int i, j, k, non_clock_array_index, clock_array_index;
1667 	union pplib_clock_info *clock_info;
1668 	struct _StateArray *state_array;
1669 	struct _ClockInfoArray *clock_info_array;
1670 	struct _NonClockInfoArray *non_clock_info_array;
1671 	union power_info *power_info;
1672 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1673         u16 data_offset;
1674 	u8 frev, crev;
1675 	u8 *power_state_offset;
1676 	struct sumo_ps *ps;
1677 
1678 	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1679 				   &frev, &crev, &data_offset))
1680 		return -EINVAL;
1681 	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1682 
1683 	state_array = (struct _StateArray *)
1684 		(mode_info->atom_context->bios + data_offset +
1685 		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1686 	clock_info_array = (struct _ClockInfoArray *)
1687 		(mode_info->atom_context->bios + data_offset +
1688 		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1689 	non_clock_info_array = (struct _NonClockInfoArray *)
1690 		(mode_info->atom_context->bios + data_offset +
1691 		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1692 
1693 	rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
1694 				  state_array->ucNumEntries, GFP_KERNEL);
1695 	if (!rdev->pm.dpm.ps)
1696 		return -ENOMEM;
1697 	power_state_offset = (u8 *)state_array->states;
1698 	for (i = 0; i < state_array->ucNumEntries; i++) {
1699 		u8 *idx;
1700 		power_state = (union pplib_power_state *)power_state_offset;
1701 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
1702 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1703 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
1704 		if (!rdev->pm.power_state[i].clock_info)
1705 			return -EINVAL;
1706 		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1707 		if (ps == NULL) {
1708 			kfree(rdev->pm.dpm.ps);
1709 			return -ENOMEM;
1710 		}
1711 		rdev->pm.dpm.ps[i].ps_priv = ps;
1712 		k = 0;
1713 		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
1714 		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1715 			clock_array_index = idx[j];
1716 			if (clock_array_index >= clock_info_array->ucNumEntries)
1717 				continue;
1718 			if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1719 				break;
1720 			clock_info = (union pplib_clock_info *)
1721 				((u8 *)&clock_info_array->clockInfo[0] +
1722 				 (clock_array_index * clock_info_array->ucEntrySize));
1723 			trinity_parse_pplib_clock_info(rdev,
1724 						       &rdev->pm.dpm.ps[i], k,
1725 						       clock_info);
1726 			k++;
1727 		}
1728 		trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1729 						   non_clock_info,
1730 						   non_clock_info_array->ucEntrySize);
1731 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1732 	}
1733 	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1734 	return 0;
1735 }
1736 
1737 union igp_info {
1738 	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1739 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1740 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1741 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1742 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1743 };
1744 
1745 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
1746 {
1747 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1748 	u32 divider;
1749 
1750 	if (did >= 8 && did <= 0x3f)
1751 		divider = did * 25;
1752 	else if (did > 0x3f && did <= 0x5f)
1753 		divider = (did - 64) * 50 + 1600;
1754 	else if (did > 0x5f && did <= 0x7e)
1755 		divider = (did - 96) * 100 + 3200;
1756 	else if (did == 0x7f)
1757 		divider = 128 * 100;
1758 	else
1759 		return 10000;
1760 
1761 	return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
1762 }
1763 
1764 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1765 {
1766 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1767 	struct radeon_mode_info *mode_info = &rdev->mode_info;
1768 	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1769 	union igp_info *igp_info;
1770 	u8 frev, crev;
1771 	u16 data_offset;
1772 	int i;
1773 
1774 	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1775 				   &frev, &crev, &data_offset)) {
1776 		igp_info = (union igp_info *)(mode_info->atom_context->bios +
1777 					      data_offset);
1778 
1779 		if (crev != 7) {
1780 			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1781 			return -EINVAL;
1782 		}
1783 		pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1784 		pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1785 		pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1786 		pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
1787 		pi->sys_info.bootup_nb_voltage_index =
1788 			le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1789 		if (igp_info->info_7.ucHtcTmpLmt == 0)
1790 			pi->sys_info.htc_tmp_lmt = 203;
1791 		else
1792 			pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1793 		if (igp_info->info_7.ucHtcHystLmt == 0)
1794 			pi->sys_info.htc_hyst_lmt = 5;
1795 		else
1796 			pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1797 		if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1798 			DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1799 		}
1800 
1801 		if (pi->enable_nbps_policy)
1802 			pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1803 		else
1804 			pi->sys_info.nb_dpm_enable = 0;
1805 
1806 		for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1807 			pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1808 			pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1809 		}
1810 
1811 		pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1812 		pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1813 		pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1814 		pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1815 
1816 		if (!pi->sys_info.nb_dpm_enable) {
1817 			for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1818 				pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1819 				pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1820 				pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1821 			}
1822 		}
1823 
1824 		pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1825 
1826 		sumo_construct_sclk_voltage_mapping_table(rdev,
1827 							  &pi->sys_info.sclk_voltage_mapping_table,
1828 							  igp_info->info_7.sAvail_SCLK);
1829 		sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1830 						 igp_info->info_7.sAvail_SCLK);
1831 
1832 		pi->sys_info.uvd_clock_table_entries[0].vclk_did =
1833 			igp_info->info_7.ucDPMState0VclkFid;
1834 		pi->sys_info.uvd_clock_table_entries[1].vclk_did =
1835 			igp_info->info_7.ucDPMState1VclkFid;
1836 		pi->sys_info.uvd_clock_table_entries[2].vclk_did =
1837 			igp_info->info_7.ucDPMState2VclkFid;
1838 		pi->sys_info.uvd_clock_table_entries[3].vclk_did =
1839 			igp_info->info_7.ucDPMState3VclkFid;
1840 
1841 		pi->sys_info.uvd_clock_table_entries[0].dclk_did =
1842 			igp_info->info_7.ucDPMState0DclkFid;
1843 		pi->sys_info.uvd_clock_table_entries[1].dclk_did =
1844 			igp_info->info_7.ucDPMState1DclkFid;
1845 		pi->sys_info.uvd_clock_table_entries[2].dclk_did =
1846 			igp_info->info_7.ucDPMState2DclkFid;
1847 		pi->sys_info.uvd_clock_table_entries[3].dclk_did =
1848 			igp_info->info_7.ucDPMState3DclkFid;
1849 
1850 		for (i = 0; i < 4; i++) {
1851 			pi->sys_info.uvd_clock_table_entries[i].vclk =
1852 				trinity_convert_did_to_freq(rdev,
1853 							    pi->sys_info.uvd_clock_table_entries[i].vclk_did);
1854 			pi->sys_info.uvd_clock_table_entries[i].dclk =
1855 				trinity_convert_did_to_freq(rdev,
1856 							    pi->sys_info.uvd_clock_table_entries[i].dclk_did);
1857 		}
1858 
1859 
1860 
1861 	}
1862 	return 0;
1863 }
1864 
1865 int trinity_dpm_init(struct radeon_device *rdev)
1866 {
1867 	struct trinity_power_info *pi;
1868 	int ret, i;
1869 
1870 	pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1871 	if (pi == NULL)
1872 		return -ENOMEM;
1873 	rdev->pm.dpm.priv = pi;
1874 
1875 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1876 		pi->at[i] = TRINITY_AT_DFLT;
1877 
1878 	if (radeon_bapm == -1) {
1879 		/* There are stability issues reported on with
1880 		 * bapm enabled when switching between AC and battery
1881 		 * power.  At the same time, some MSI boards hang
1882 		 * if it's not enabled and dpm is enabled.  Just enable
1883 		 * it for MSI boards right now.
1884 		 */
1885 		if (rdev->pdev->subsystem_vendor == 0x1462)
1886 			pi->enable_bapm = true;
1887 		else
1888 			pi->enable_bapm = false;
1889 	} else if (radeon_bapm == 0) {
1890 		pi->enable_bapm = false;
1891 	} else {
1892 		pi->enable_bapm = true;
1893 	}
1894 	pi->enable_nbps_policy = true;
1895 	pi->enable_sclk_ds = true;
1896 	pi->enable_gfx_power_gating = true;
1897 	pi->enable_gfx_clock_gating = true;
1898 	pi->enable_mg_clock_gating = false;
1899 	pi->enable_gfx_dynamic_mgpg = false;
1900 	pi->override_dynamic_mgpg = false;
1901 	pi->enable_auto_thermal_throttling = true;
1902 	pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1903 	pi->uvd_dpm = true; /* ??? */
1904 
1905 	ret = trinity_parse_sys_info_table(rdev);
1906 	if (ret)
1907 		return ret;
1908 
1909 	trinity_construct_boot_state(rdev);
1910 
1911 	ret = r600_get_platform_caps(rdev);
1912 	if (ret)
1913 		return ret;
1914 
1915 	ret = trinity_parse_power_table(rdev);
1916 	if (ret)
1917 		return ret;
1918 
1919 	pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1920 	pi->enable_dpm = true;
1921 
1922 	return 0;
1923 }
1924 
1925 void trinity_dpm_print_power_state(struct radeon_device *rdev,
1926 				   struct radeon_ps *rps)
1927 {
1928 	int i;
1929 	struct trinity_ps *ps = trinity_get_ps(rps);
1930 
1931 	r600_dpm_print_class_info(rps->class, rps->class2);
1932 	r600_dpm_print_cap_info(rps->caps);
1933 	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1934 	for (i = 0; i < ps->num_levels; i++) {
1935 		struct trinity_pl *pl = &ps->levels[i];
1936 		printk("\t\tpower level %d    sclk: %u vddc: %u\n",
1937 		       i, pl->sclk,
1938 		       trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1939 	}
1940 	r600_dpm_print_ps_status(rdev, rps);
1941 }
1942 
1943 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
1944 							 struct seq_file *m)
1945 {
1946 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1947 	struct radeon_ps *rps = &pi->current_rps;
1948 	struct trinity_ps *ps = trinity_get_ps(rps);
1949 	struct trinity_pl *pl;
1950 	u32 current_index =
1951 		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
1952 		CURRENT_STATE_SHIFT;
1953 
1954 	if (current_index >= ps->num_levels) {
1955 		seq_printf(m, "invalid dpm profile %d\n", current_index);
1956 	} else {
1957 		pl = &ps->levels[current_index];
1958 		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1959 		seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
1960 			   current_index, pl->sclk,
1961 			   trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1962 	}
1963 }
1964 
1965 void trinity_dpm_fini(struct radeon_device *rdev)
1966 {
1967 	int i;
1968 
1969 	trinity_cleanup_asic(rdev); /* ??? */
1970 
1971 	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1972 		kfree(rdev->pm.dpm.ps[i].ps_priv);
1973 	}
1974 	kfree(rdev->pm.dpm.ps);
1975 	kfree(rdev->pm.dpm.priv);
1976 }
1977 
1978 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
1979 {
1980 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1981 	struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
1982 
1983 	if (low)
1984 		return requested_state->levels[0].sclk;
1985 	else
1986 		return requested_state->levels[requested_state->num_levels - 1].sclk;
1987 }
1988 
1989 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
1990 {
1991 	struct trinity_power_info *pi = trinity_get_pi(rdev);
1992 
1993 	return pi->sys_info.bootup_uma_clk;
1994 }
1995