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