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