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