Merge tag 'fixes-against-v3.18-rc2' of git://git.kernel.org/pub/scm/linux/kernel...
[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 "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 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1273 {
1274         struct trinity_power_info *pi = trinity_get_pi(rdev);
1275
1276         trinity_acquire_mutex(rdev);
1277         if (pi->enable_dpm) {
1278                 trinity_enable_power_level_0(rdev);
1279                 trinity_force_level_0(rdev);
1280                 trinity_wait_for_level_0(rdev);
1281                 trinity_program_bootup_state(rdev);
1282                 trinity_force_level_0(rdev);
1283                 trinity_unforce_levels(rdev);
1284         }
1285         trinity_release_mutex(rdev);
1286 }
1287
1288 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1289                                                   u32 vid_2bit)
1290 {
1291         struct trinity_power_info *pi = trinity_get_pi(rdev);
1292         u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1293         u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1294         u32 step = (svi_mode == 0) ? 1250 : 625;
1295         u32 delta = vid_7bit * step + 50;
1296
1297         if (delta > 155000)
1298                 return 0;
1299
1300         return (155000 - delta) / 100;
1301 }
1302
1303 static void trinity_patch_boot_state(struct radeon_device *rdev,
1304                                      struct trinity_ps *ps)
1305 {
1306         struct trinity_power_info *pi = trinity_get_pi(rdev);
1307
1308         ps->num_levels = 1;
1309         ps->nbps_flags = 0;
1310         ps->bapm_flags = 0;
1311         ps->levels[0] = pi->boot_pl;
1312 }
1313
1314 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1315 {
1316         if (sclk < 20000)
1317                 return 1;
1318         return 0;
1319 }
1320
1321 static void trinity_construct_boot_state(struct radeon_device *rdev)
1322 {
1323         struct trinity_power_info *pi = trinity_get_pi(rdev);
1324
1325         pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1326         pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1327         pi->boot_pl.ds_divider_index = 0;
1328         pi->boot_pl.ss_divider_index = 0;
1329         pi->boot_pl.allow_gnb_slow = 1;
1330         pi->boot_pl.force_nbp_state = 0;
1331         pi->boot_pl.display_wm = 0;
1332         pi->boot_pl.vce_wm = 0;
1333         pi->current_ps.num_levels = 1;
1334         pi->current_ps.levels[0] = pi->boot_pl;
1335 }
1336
1337 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1338                                                   u32 sclk, u32 min_sclk_in_sr)
1339 {
1340         struct trinity_power_info *pi = trinity_get_pi(rdev);
1341         u32 i;
1342         u32 temp;
1343         u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1344                 min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1345
1346         if (sclk < min)
1347                 return 0;
1348
1349         if (!pi->enable_sclk_ds)
1350                 return 0;
1351
1352         for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
1353                 temp = sclk / sumo_get_sleep_divider_from_id(i);
1354                 if (temp >= min || i == 0)
1355                         break;
1356         }
1357
1358         return (u8)i;
1359 }
1360
1361 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1362                                           u32 lower_limit)
1363 {
1364         struct trinity_power_info *pi = trinity_get_pi(rdev);
1365         u32 i;
1366
1367         for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1368                 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1369                         return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1370         }
1371
1372         if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1373                 DRM_ERROR("engine clock out of range!");
1374
1375         return 0;
1376 }
1377
1378 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1379                                         struct trinity_ps *ps,
1380                                         struct trinity_ps *current_ps)
1381 {
1382         struct trinity_power_info *pi = trinity_get_pi(rdev);
1383         u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1384         u32 current_vddc;
1385         u32 current_sclk;
1386         u32 current_index = 0;
1387
1388         if (current_ps) {
1389                 current_vddc = current_ps->levels[current_index].vddc_index;
1390                 current_sclk = current_ps->levels[current_index].sclk;
1391         } else {
1392                 current_vddc = pi->boot_pl.vddc_index;
1393                 current_sclk = pi->boot_pl.sclk;
1394         }
1395
1396         ps->levels[0].vddc_index = current_vddc;
1397
1398         if (ps->levels[0].sclk > current_sclk)
1399                 ps->levels[0].sclk = current_sclk;
1400
1401         ps->levels[0].ds_divider_index =
1402                 trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1403         ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1404         ps->levels[0].allow_gnb_slow = 1;
1405         ps->levels[0].force_nbp_state = 0;
1406         ps->levels[0].display_wm = 0;
1407         ps->levels[0].vce_wm =
1408                 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1409 }
1410
1411 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1412                                        struct trinity_ps *ps, u32 index)
1413 {
1414         if (ps == NULL || ps->num_levels <= 1)
1415                 return 0;
1416         else if (ps->num_levels == 2) {
1417                 if (index == 0)
1418                         return 0;
1419                 else
1420                         return 1;
1421         } else {
1422                 if (index == 0)
1423                         return 0;
1424                 else if (ps->levels[index].sclk < 30000)
1425                         return 0;
1426                 else
1427                         return 1;
1428         }
1429 }
1430
1431 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
1432                                        struct radeon_ps *rps)
1433 {
1434         struct trinity_power_info *pi = trinity_get_pi(rdev);
1435         u32 i = 0;
1436
1437         for (i = 0; i < 4; i++) {
1438                 if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
1439                     (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
1440                     break;
1441         }
1442
1443         if (i >= 4) {
1444                 DRM_ERROR("UVD clock index not found!\n");
1445                 i = 3;
1446         }
1447         return i;
1448 }
1449
1450 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1451                                      struct radeon_ps *rps)
1452 {
1453         struct trinity_ps *ps = trinity_get_ps(rps);
1454         struct trinity_power_info *pi = trinity_get_pi(rdev);
1455         u32 high_index = 0;
1456         u32 low_index = 0;
1457
1458         if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
1459                 high_index = trinity_get_uvd_clock_index(rdev, rps);
1460
1461                 switch(high_index) {
1462                 case 3:
1463                 case 2:
1464                         low_index = 1;
1465                         break;
1466                 case 1:
1467                 case 0:
1468                 default:
1469                         low_index = 0;
1470                         break;
1471                 }
1472
1473                 ps->vclk_low_divider =
1474                         pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
1475                 ps->dclk_low_divider =
1476                         pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
1477                 ps->vclk_high_divider =
1478                         pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
1479                 ps->dclk_high_divider =
1480                         pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
1481         }
1482 }
1483
1484
1485
1486 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1487                                              struct radeon_ps *new_rps,
1488                                              struct radeon_ps *old_rps)
1489 {
1490         struct trinity_ps *ps = trinity_get_ps(new_rps);
1491         struct trinity_ps *current_ps = trinity_get_ps(old_rps);
1492         struct trinity_power_info *pi = trinity_get_pi(rdev);
1493         u32 min_voltage = 0; /* ??? */
1494         u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1495         u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1496         u32 i;
1497         bool force_high;
1498         u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1499
1500         if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1501                 return trinity_patch_thermal_state(rdev, ps, current_ps);
1502
1503         trinity_adjust_uvd_state(rdev, new_rps);
1504
1505         for (i = 0; i < ps->num_levels; i++) {
1506                 if (ps->levels[i].vddc_index < min_voltage)
1507                         ps->levels[i].vddc_index = min_voltage;
1508
1509                 if (ps->levels[i].sclk < min_sclk)
1510                         ps->levels[i].sclk =
1511                                 trinity_get_valid_engine_clock(rdev, min_sclk);
1512
1513                 ps->levels[i].ds_divider_index =
1514                         sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1515
1516                 ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1517
1518                 ps->levels[i].allow_gnb_slow = 1;
1519                 ps->levels[i].force_nbp_state = 0;
1520                 ps->levels[i].display_wm =
1521                         trinity_calculate_display_wm(rdev, ps, i);
1522                 ps->levels[i].vce_wm =
1523                         trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1524         }
1525
1526         if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1527             ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1528                 ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1529
1530         if (pi->sys_info.nb_dpm_enable) {
1531                 ps->Dpm0PgNbPsLo = 0x1;
1532                 ps->Dpm0PgNbPsHi = 0x0;
1533                 ps->DpmXNbPsLo = 0x2;
1534                 ps->DpmXNbPsHi = 0x1;
1535
1536                 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1537                     ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1538                         force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1539                                       ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1540                                        (pi->sys_info.uma_channel_number == 1)));
1541                         force_high = (num_active_displays >= 3) || force_high;
1542                         ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1543                         ps->Dpm0PgNbPsHi = 0x1;
1544                         ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1545                         ps->DpmXNbPsHi = 0x2;
1546                         ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1547                 }
1548         }
1549 }
1550
1551 static void trinity_cleanup_asic(struct radeon_device *rdev)
1552 {
1553         sumo_take_smu_control(rdev, false);
1554 }
1555
1556 #if 0
1557 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1558 {
1559         struct trinity_power_info *pi = trinity_get_pi(rdev);
1560
1561         if (pi->voltage_drop_in_dce)
1562                 trinity_dce_enable_voltage_adjustment(rdev, false);
1563 }
1564 #endif
1565
1566 static void trinity_add_dccac_value(struct radeon_device *rdev)
1567 {
1568         u32 gpu_cac_avrg_cntl_window_size;
1569         u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1570         u64 disp_clk = rdev->clock.default_dispclk / 100;
1571         u32 dc_cac_value;
1572
1573         gpu_cac_avrg_cntl_window_size =
1574                 (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1575
1576         dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1577                              (32 - gpu_cac_avrg_cntl_window_size));
1578
1579         WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1580 }
1581
1582 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1583 {
1584         struct trinity_power_info *pi = trinity_get_pi(rdev);
1585
1586         if (pi->voltage_drop_in_dce)
1587                 trinity_dce_enable_voltage_adjustment(rdev, true);
1588         trinity_add_dccac_value(rdev);
1589 }
1590
1591 union power_info {
1592         struct _ATOM_POWERPLAY_INFO info;
1593         struct _ATOM_POWERPLAY_INFO_V2 info_2;
1594         struct _ATOM_POWERPLAY_INFO_V3 info_3;
1595         struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1596         struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1597         struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1598 };
1599
1600 union pplib_clock_info {
1601         struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1602         struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1603         struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1604         struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1605 };
1606
1607 union pplib_power_state {
1608         struct _ATOM_PPLIB_STATE v1;
1609         struct _ATOM_PPLIB_STATE_V2 v2;
1610 };
1611
1612 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1613                                                struct radeon_ps *rps,
1614                                                struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1615                                                u8 table_rev)
1616 {
1617         struct trinity_ps *ps = trinity_get_ps(rps);
1618
1619         rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1620         rps->class = le16_to_cpu(non_clock_info->usClassification);
1621         rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1622
1623         if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1624                 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1625                 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1626         } else {
1627                 rps->vclk = 0;
1628                 rps->dclk = 0;
1629         }
1630
1631         if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1632                 rdev->pm.dpm.boot_ps = rps;
1633                 trinity_patch_boot_state(rdev, ps);
1634         }
1635         if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1636                 rdev->pm.dpm.uvd_ps = rps;
1637 }
1638
1639 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1640                                            struct radeon_ps *rps, int index,
1641                                            union pplib_clock_info *clock_info)
1642 {
1643         struct trinity_power_info *pi = trinity_get_pi(rdev);
1644         struct trinity_ps *ps = trinity_get_ps(rps);
1645         struct trinity_pl *pl = &ps->levels[index];
1646         u32 sclk;
1647
1648         sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1649         sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1650         pl->sclk = sclk;
1651         pl->vddc_index = clock_info->sumo.vddcIndex;
1652
1653         ps->num_levels = index + 1;
1654
1655         if (pi->enable_sclk_ds) {
1656                 pl->ds_divider_index = 5;
1657                 pl->ss_divider_index = 5;
1658         }
1659 }
1660
1661 static int trinity_parse_power_table(struct radeon_device *rdev)
1662 {
1663         struct radeon_mode_info *mode_info = &rdev->mode_info;
1664         struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1665         union pplib_power_state *power_state;
1666         int i, j, k, non_clock_array_index, clock_array_index;
1667         union pplib_clock_info *clock_info;
1668         struct _StateArray *state_array;
1669         struct _ClockInfoArray *clock_info_array;
1670         struct _NonClockInfoArray *non_clock_info_array;
1671         union power_info *power_info;
1672         int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1673         u16 data_offset;
1674         u8 frev, crev;
1675         u8 *power_state_offset;
1676         struct sumo_ps *ps;
1677
1678         if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1679                                    &frev, &crev, &data_offset))
1680                 return -EINVAL;
1681         power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1682
1683         state_array = (struct _StateArray *)
1684                 (mode_info->atom_context->bios + data_offset +
1685                  le16_to_cpu(power_info->pplib.usStateArrayOffset));
1686         clock_info_array = (struct _ClockInfoArray *)
1687                 (mode_info->atom_context->bios + data_offset +
1688                  le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1689         non_clock_info_array = (struct _NonClockInfoArray *)
1690                 (mode_info->atom_context->bios + data_offset +
1691                  le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1692
1693         rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
1694                                   state_array->ucNumEntries, GFP_KERNEL);
1695         if (!rdev->pm.dpm.ps)
1696                 return -ENOMEM;
1697         power_state_offset = (u8 *)state_array->states;
1698         for (i = 0; i < state_array->ucNumEntries; i++) {
1699                 u8 *idx;
1700                 power_state = (union pplib_power_state *)power_state_offset;
1701                 non_clock_array_index = power_state->v2.nonClockInfoIndex;
1702                 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1703                         &non_clock_info_array->nonClockInfo[non_clock_array_index];
1704                 if (!rdev->pm.power_state[i].clock_info)
1705                         return -EINVAL;
1706                 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1707                 if (ps == NULL) {
1708                         kfree(rdev->pm.dpm.ps);
1709                         return -ENOMEM;
1710                 }
1711                 rdev->pm.dpm.ps[i].ps_priv = ps;
1712                 k = 0;
1713                 idx = (u8 *)&power_state->v2.clockInfoIndex[0];
1714                 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1715                         clock_array_index = idx[j];
1716                         if (clock_array_index >= clock_info_array->ucNumEntries)
1717                                 continue;
1718                         if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1719                                 break;
1720                         clock_info = (union pplib_clock_info *)
1721                                 ((u8 *)&clock_info_array->clockInfo[0] +
1722                                  (clock_array_index * clock_info_array->ucEntrySize));
1723                         trinity_parse_pplib_clock_info(rdev,
1724                                                        &rdev->pm.dpm.ps[i], k,
1725                                                        clock_info);
1726                         k++;
1727                 }
1728                 trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1729                                                    non_clock_info,
1730                                                    non_clock_info_array->ucEntrySize);
1731                 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1732         }
1733         rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1734         return 0;
1735 }
1736
1737 union igp_info {
1738         struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1739         struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1740         struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1741         struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1742         struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1743 };
1744
1745 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
1746 {
1747         struct trinity_power_info *pi = trinity_get_pi(rdev);
1748         u32 divider;
1749
1750         if (did >= 8 && did <= 0x3f)
1751                 divider = did * 25;
1752         else if (did > 0x3f && did <= 0x5f)
1753                 divider = (did - 64) * 50 + 1600;
1754         else if (did > 0x5f && did <= 0x7e)
1755                 divider = (did - 96) * 100 + 3200;
1756         else if (did == 0x7f)
1757                 divider = 128 * 100;
1758         else
1759                 return 10000;
1760
1761         return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
1762 }
1763
1764 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1765 {
1766         struct trinity_power_info *pi = trinity_get_pi(rdev);
1767         struct radeon_mode_info *mode_info = &rdev->mode_info;
1768         int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1769         union igp_info *igp_info;
1770         u8 frev, crev;
1771         u16 data_offset;
1772         int i;
1773
1774         if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1775                                    &frev, &crev, &data_offset)) {
1776                 igp_info = (union igp_info *)(mode_info->atom_context->bios +
1777                                               data_offset);
1778
1779                 if (crev != 7) {
1780                         DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1781                         return -EINVAL;
1782                 }
1783                 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1784                 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1785                 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1786                 pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
1787                 pi->sys_info.bootup_nb_voltage_index =
1788                         le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1789                 if (igp_info->info_7.ucHtcTmpLmt == 0)
1790                         pi->sys_info.htc_tmp_lmt = 203;
1791                 else
1792                         pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1793                 if (igp_info->info_7.ucHtcHystLmt == 0)
1794                         pi->sys_info.htc_hyst_lmt = 5;
1795                 else
1796                         pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1797                 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1798                         DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1799                 }
1800
1801                 if (pi->enable_nbps_policy)
1802                         pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1803                 else
1804                         pi->sys_info.nb_dpm_enable = 0;
1805
1806                 for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1807                         pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1808                         pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1809                 }
1810
1811                 pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1812                 pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1813                 pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1814                 pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1815
1816                 if (!pi->sys_info.nb_dpm_enable) {
1817                         for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1818                                 pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1819                                 pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1820                                 pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1821                         }
1822                 }
1823
1824                 pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1825
1826                 sumo_construct_sclk_voltage_mapping_table(rdev,
1827                                                           &pi->sys_info.sclk_voltage_mapping_table,
1828                                                           igp_info->info_7.sAvail_SCLK);
1829                 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1830                                                  igp_info->info_7.sAvail_SCLK);
1831
1832                 pi->sys_info.uvd_clock_table_entries[0].vclk_did =
1833                         igp_info->info_7.ucDPMState0VclkFid;
1834                 pi->sys_info.uvd_clock_table_entries[1].vclk_did =
1835                         igp_info->info_7.ucDPMState1VclkFid;
1836                 pi->sys_info.uvd_clock_table_entries[2].vclk_did =
1837                         igp_info->info_7.ucDPMState2VclkFid;
1838                 pi->sys_info.uvd_clock_table_entries[3].vclk_did =
1839                         igp_info->info_7.ucDPMState3VclkFid;
1840
1841                 pi->sys_info.uvd_clock_table_entries[0].dclk_did =
1842                         igp_info->info_7.ucDPMState0DclkFid;
1843                 pi->sys_info.uvd_clock_table_entries[1].dclk_did =
1844                         igp_info->info_7.ucDPMState1DclkFid;
1845                 pi->sys_info.uvd_clock_table_entries[2].dclk_did =
1846                         igp_info->info_7.ucDPMState2DclkFid;
1847                 pi->sys_info.uvd_clock_table_entries[3].dclk_did =
1848                         igp_info->info_7.ucDPMState3DclkFid;
1849
1850                 for (i = 0; i < 4; i++) {
1851                         pi->sys_info.uvd_clock_table_entries[i].vclk =
1852                                 trinity_convert_did_to_freq(rdev,
1853                                                             pi->sys_info.uvd_clock_table_entries[i].vclk_did);
1854                         pi->sys_info.uvd_clock_table_entries[i].dclk =
1855                                 trinity_convert_did_to_freq(rdev,
1856                                                             pi->sys_info.uvd_clock_table_entries[i].dclk_did);
1857                 }
1858
1859
1860
1861         }
1862         return 0;
1863 }
1864
1865 int trinity_dpm_init(struct radeon_device *rdev)
1866 {
1867         struct trinity_power_info *pi;
1868         int ret, i;
1869
1870         pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1871         if (pi == NULL)
1872                 return -ENOMEM;
1873         rdev->pm.dpm.priv = pi;
1874
1875         for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1876                 pi->at[i] = TRINITY_AT_DFLT;
1877
1878         if (radeon_bapm == -1) {
1879                 /* There are stability issues reported on with
1880                  * bapm enabled when switching between AC and battery
1881                  * power.  At the same time, some MSI boards hang
1882                  * if it's not enabled and dpm is enabled.  Just enable
1883                  * it for MSI boards right now.
1884                  */
1885                 if (rdev->pdev->subsystem_vendor == 0x1462)
1886                         pi->enable_bapm = true;
1887                 else
1888                         pi->enable_bapm = false;
1889         } else if (radeon_bapm == 0) {
1890                 pi->enable_bapm = false;
1891         } else {
1892                 pi->enable_bapm = true;
1893         }
1894         pi->enable_nbps_policy = true;
1895         pi->enable_sclk_ds = true;
1896         pi->enable_gfx_power_gating = true;
1897         pi->enable_gfx_clock_gating = true;
1898         pi->enable_mg_clock_gating = false;
1899         pi->enable_gfx_dynamic_mgpg = false;
1900         pi->override_dynamic_mgpg = false;
1901         pi->enable_auto_thermal_throttling = true;
1902         pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
1903         pi->uvd_dpm = true; /* ??? */
1904
1905         ret = trinity_parse_sys_info_table(rdev);
1906         if (ret)
1907                 return ret;
1908
1909         trinity_construct_boot_state(rdev);
1910
1911         ret = r600_get_platform_caps(rdev);
1912         if (ret)
1913                 return ret;
1914
1915         ret = trinity_parse_power_table(rdev);
1916         if (ret)
1917                 return ret;
1918
1919         pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1920         pi->enable_dpm = true;
1921
1922         return 0;
1923 }
1924
1925 void trinity_dpm_print_power_state(struct radeon_device *rdev,
1926                                    struct radeon_ps *rps)
1927 {
1928         int i;
1929         struct trinity_ps *ps = trinity_get_ps(rps);
1930
1931         r600_dpm_print_class_info(rps->class, rps->class2);
1932         r600_dpm_print_cap_info(rps->caps);
1933         printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1934         for (i = 0; i < ps->num_levels; i++) {
1935                 struct trinity_pl *pl = &ps->levels[i];
1936                 printk("\t\tpower level %d    sclk: %u vddc: %u\n",
1937                        i, pl->sclk,
1938                        trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1939         }
1940         r600_dpm_print_ps_status(rdev, rps);
1941 }
1942
1943 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
1944                                                          struct seq_file *m)
1945 {
1946         struct trinity_power_info *pi = trinity_get_pi(rdev);
1947         struct radeon_ps *rps = &pi->current_rps;
1948         struct trinity_ps *ps = trinity_get_ps(rps);
1949         struct trinity_pl *pl;
1950         u32 current_index =
1951                 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
1952                 CURRENT_STATE_SHIFT;
1953
1954         if (current_index >= ps->num_levels) {
1955                 seq_printf(m, "invalid dpm profile %d\n", current_index);
1956         } else {
1957                 pl = &ps->levels[current_index];
1958                 seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1959                 seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
1960                            current_index, pl->sclk,
1961                            trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1962         }
1963 }
1964
1965 void trinity_dpm_fini(struct radeon_device *rdev)
1966 {
1967         int i;
1968
1969         trinity_cleanup_asic(rdev); /* ??? */
1970
1971         for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1972                 kfree(rdev->pm.dpm.ps[i].ps_priv);
1973         }
1974         kfree(rdev->pm.dpm.ps);
1975         kfree(rdev->pm.dpm.priv);
1976 }
1977
1978 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
1979 {
1980         struct trinity_power_info *pi = trinity_get_pi(rdev);
1981         struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
1982
1983         if (low)
1984                 return requested_state->levels[0].sclk;
1985         else
1986                 return requested_state->levels[requested_state->num_levels - 1].sclk;
1987 }
1988
1989 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
1990 {
1991         struct trinity_power_info *pi = trinity_get_pi(rdev);
1992
1993         return pi->sys_info.bootup_uma_clk;
1994 }