Subversion Repositories Kolibri OS

Rev

Rev 5271 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5078 serge 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"
5271 serge 26
#include "radeon_asic.h"
5078 serge 27
#include "trinityd.h"
28
#include "r600_dpm.h"
29
#include "trinity_dpm.h"
30
#include 
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
 
6104 serge 339
extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
5078 serge 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, ÷rs);
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, ÷rs);
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, ÷rs);
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
 
6104 serge 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
 
5078 serge 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);
6104 serge 1265
		trinity_set_vce_clock(rdev, new_ps, old_ps);
5078 serge 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
 
6104 serge 1289
#if 0
5078 serge 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
}
6104 serge 1305
#endif
5078 serge 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
 
6104 serge 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;
5078 serge 1510
 
6104 serge 1511
	if (((evclk == 0) && (ecclk == 0)) ||
1512
	    (table && (table->count == 0))) {
1513
		*voltage = 0;
1514
		return 0;
1515
	}
5078 serge 1516
 
6104 serge 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
 
5078 serge 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;
6104 serge 1544
	u16 min_vce_voltage;
5078 serge 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
 
6104 serge 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
 
5078 serge 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
 
6104 serge 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
 
5078 serge 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;
6104 serge 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
 
5078 serge 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) {
6104 serge 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;
5078 serge 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
 
6104 serge 1995
	ret = r600_parse_extended_power_table(rdev);
1996
	if (ret)
1997
		return ret;
1998
 
5078 serge 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
 
6104 serge 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
 
5078 serge 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);
6104 serge 2085
	r600_free_extended_power_table(rdev);
5078 serge 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
}