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