Subversion Repositories Kolibri OS

Rev

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