Subversion Repositories Kolibri OS

Rev

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