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