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