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