drm/radeon: Update to Linux 4.7.10
[dragonfly.git] / sys / dev / drm / radeon / trinity_dpm.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
829 static void trinity_enable_power_level_0(struct radeon_device *rdev)
830 {
831         trinity_power_level_enable_disable(rdev, 0, true);
832 }
833
834 static void trinity_force_level_0(struct radeon_device *rdev)
835 {
836         trinity_dpm_force_state(rdev, 0);
837 }
838
839 static void trinity_unforce_levels(struct radeon_device *rdev)
840 {
841         trinity_dpm_no_forced_level(rdev);
842 }
843
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }