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