Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
26552 views
1
/*
2
* Copyright 2015 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
#include "pp_debug.h"
24
#include <linux/types.h>
25
#include <linux/kernel.h>
26
#include <linux/slab.h>
27
#include <linux/pci.h>
28
29
#include <drm/amdgpu_drm.h>
30
#include "processpptables.h"
31
#include <atom-types.h>
32
#include <atombios.h>
33
#include "pptable.h"
34
#include "power_state.h"
35
#include "hwmgr.h"
36
#include "hardwaremanager.h"
37
38
39
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
40
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
41
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
42
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
43
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
44
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
45
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
46
#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
47
48
#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
49
50
static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
51
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
52
{
53
uint16_t vce_table_offset = 0;
54
55
if (le16_to_cpu(powerplay_table->usTableSize) >=
56
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
57
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
58
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
59
60
if (powerplay_table3->usExtendendedHeaderOffset > 0) {
61
const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
62
(const ATOM_PPLIB_EXTENDEDHEADER *)
63
(((unsigned long)powerplay_table3) +
64
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
65
if (le16_to_cpu(extended_header->usSize) >=
66
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
67
vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
68
}
69
}
70
71
return vce_table_offset;
72
}
73
74
static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,
75
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
76
{
77
uint16_t table_offset = get_vce_table_offset(hwmgr,
78
powerplay_table);
79
80
if (table_offset > 0)
81
return table_offset + 1;
82
83
return 0;
84
}
85
86
static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
87
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
88
{
89
uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
90
powerplay_table);
91
uint16_t table_size = 0;
92
93
if (table_offset > 0) {
94
const VCEClockInfoArray *p = (const VCEClockInfoArray *)
95
(((unsigned long) powerplay_table) + table_offset);
96
table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
97
}
98
99
return table_size;
100
}
101
102
static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
103
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
104
{
105
uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
106
powerplay_table);
107
108
if (table_offset > 0)
109
return table_offset + get_vce_clock_info_array_size(hwmgr,
110
powerplay_table);
111
112
return 0;
113
}
114
115
static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
116
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
117
{
118
uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
119
uint16_t table_size = 0;
120
121
if (table_offset > 0) {
122
const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
123
(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
124
125
table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
126
}
127
return table_size;
128
}
129
130
static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
131
{
132
uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
133
134
if (table_offset > 0)
135
return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
136
137
return 0;
138
}
139
140
static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
141
struct pp_hwmgr *hwmgr,
142
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
143
{
144
uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
145
146
if (table_offset > 0)
147
return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
148
149
return NULL;
150
}
151
152
static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
153
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
154
{
155
uint16_t uvd_table_offset = 0;
156
157
if (le16_to_cpu(powerplay_table->usTableSize) >=
158
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
159
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
160
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
161
if (powerplay_table3->usExtendendedHeaderOffset > 0) {
162
const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
163
(const ATOM_PPLIB_EXTENDEDHEADER *)
164
(((unsigned long)powerplay_table3) +
165
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
166
if (le16_to_cpu(extended_header->usSize) >=
167
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
168
uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
169
}
170
}
171
return uvd_table_offset;
172
}
173
174
static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,
175
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
176
{
177
uint16_t table_offset = get_uvd_table_offset(hwmgr,
178
powerplay_table);
179
180
if (table_offset > 0)
181
return table_offset + 1;
182
return 0;
183
}
184
185
static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
186
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
187
{
188
uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
189
powerplay_table);
190
uint16_t table_size = 0;
191
192
if (table_offset > 0) {
193
const UVDClockInfoArray *p = (const UVDClockInfoArray *)
194
(((unsigned long) powerplay_table)
195
+ table_offset);
196
table_size = sizeof(UCHAR) +
197
p->ucNumEntries * sizeof(UVDClockInfo);
198
}
199
200
return table_size;
201
}
202
203
static uint16_t get_uvd_clock_voltage_limit_table_offset(
204
struct pp_hwmgr *hwmgr,
205
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
206
{
207
uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
208
powerplay_table);
209
210
if (table_offset > 0)
211
return table_offset +
212
get_uvd_clock_info_array_size(hwmgr, powerplay_table);
213
214
return 0;
215
}
216
217
static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
218
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
219
{
220
uint16_t samu_table_offset = 0;
221
222
if (le16_to_cpu(powerplay_table->usTableSize) >=
223
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
224
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
225
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
226
if (powerplay_table3->usExtendendedHeaderOffset > 0) {
227
const ATOM_PPLIB_EXTENDEDHEADER *extended_header =
228
(const ATOM_PPLIB_EXTENDEDHEADER *)
229
(((unsigned long)powerplay_table3) +
230
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
231
if (le16_to_cpu(extended_header->usSize) >=
232
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
233
samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
234
}
235
}
236
237
return samu_table_offset;
238
}
239
240
static uint16_t get_samu_clock_voltage_limit_table_offset(
241
struct pp_hwmgr *hwmgr,
242
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
243
{
244
uint16_t table_offset = get_samu_table_offset(hwmgr,
245
powerplay_table);
246
247
if (table_offset > 0)
248
return table_offset + 1;
249
250
return 0;
251
}
252
253
static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
254
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
255
{
256
uint16_t acp_table_offset = 0;
257
258
if (le16_to_cpu(powerplay_table->usTableSize) >=
259
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
260
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
261
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
262
if (powerplay_table3->usExtendendedHeaderOffset > 0) {
263
const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
264
(const ATOM_PPLIB_EXTENDEDHEADER *)
265
(((unsigned long)powerplay_table3) +
266
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
267
if (le16_to_cpu(pExtendedHeader->usSize) >=
268
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
269
acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
270
}
271
}
272
273
return acp_table_offset;
274
}
275
276
static uint16_t get_acp_clock_voltage_limit_table_offset(
277
struct pp_hwmgr *hwmgr,
278
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
279
{
280
uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);
281
282
if (tableOffset > 0)
283
return tableOffset + 1;
284
285
return 0;
286
}
287
288
static uint16_t get_cacp_tdp_table_offset(
289
struct pp_hwmgr *hwmgr,
290
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
291
{
292
uint16_t cacTdpTableOffset = 0;
293
294
if (le16_to_cpu(powerplay_table->usTableSize) >=
295
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
296
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
297
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
298
if (powerplay_table3->usExtendendedHeaderOffset > 0) {
299
const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
300
(const ATOM_PPLIB_EXTENDEDHEADER *)
301
(((unsigned long)powerplay_table3) +
302
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
303
if (le16_to_cpu(pExtendedHeader->usSize) >=
304
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
305
cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
306
}
307
}
308
309
return cacTdpTableOffset;
310
}
311
312
static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,
313
struct phm_cac_tdp_table **ptable,
314
const ATOM_PowerTune_Table *table,
315
uint16_t us_maximum_power_delivery_limit)
316
{
317
unsigned long table_size;
318
struct phm_cac_tdp_table *tdp_table;
319
320
table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);
321
322
tdp_table = kzalloc(table_size, GFP_KERNEL);
323
if (NULL == tdp_table)
324
return -ENOMEM;
325
326
tdp_table->usTDP = le16_to_cpu(table->usTDP);
327
tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);
328
tdp_table->usTDC = le16_to_cpu(table->usTDC);
329
tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);
330
tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);
331
tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);
332
tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);
333
tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;
334
335
*ptable = tdp_table;
336
337
return 0;
338
}
339
340
static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
341
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
342
{
343
uint16_t sclk_vdd_gfx_table_offset = 0;
344
345
if (le16_to_cpu(powerplay_table->usTableSize) >=
346
sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
347
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
348
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
349
if (powerplay_table3->usExtendendedHeaderOffset > 0) {
350
const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =
351
(const ATOM_PPLIB_EXTENDEDHEADER *)
352
(((unsigned long)powerplay_table3) +
353
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
354
if (le16_to_cpu(pExtendedHeader->usSize) >=
355
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
356
sclk_vdd_gfx_table_offset =
357
le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
358
}
359
}
360
361
return sclk_vdd_gfx_table_offset;
362
}
363
364
static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
365
struct pp_hwmgr *hwmgr,
366
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
367
{
368
uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);
369
370
if (tableOffset > 0)
371
return tableOffset;
372
373
return 0;
374
}
375
376
377
static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
378
struct phm_clock_voltage_dependency_table **ptable,
379
const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)
380
{
381
382
unsigned long i;
383
struct phm_clock_voltage_dependency_table *dep_table;
384
385
dep_table = kzalloc(struct_size(dep_table, entries, table->ucNumEntries),
386
GFP_KERNEL);
387
if (NULL == dep_table)
388
return -ENOMEM;
389
390
dep_table->count = (unsigned long)table->ucNumEntries;
391
392
for (i = 0; i < dep_table->count; i++) {
393
dep_table->entries[i].clk =
394
((unsigned long)table->entries[i].ucClockHigh << 16) |
395
le16_to_cpu(table->entries[i].usClockLow);
396
dep_table->entries[i].v =
397
(unsigned long)le16_to_cpu(table->entries[i].usVoltage);
398
}
399
400
*ptable = dep_table;
401
402
return 0;
403
}
404
405
static int get_valid_clk(struct pp_hwmgr *hwmgr,
406
struct phm_clock_array **ptable,
407
const struct phm_clock_voltage_dependency_table *table)
408
{
409
unsigned long i;
410
struct phm_clock_array *clock_table;
411
412
clock_table = kzalloc(struct_size(clock_table, values, table->count), GFP_KERNEL);
413
if (!clock_table)
414
return -ENOMEM;
415
416
clock_table->count = (unsigned long)table->count;
417
418
for (i = 0; i < clock_table->count; i++)
419
clock_table->values[i] = (unsigned long)table->entries[i].clk;
420
421
*ptable = clock_table;
422
423
return 0;
424
}
425
426
static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
427
struct phm_clock_and_voltage_limits *limits,
428
const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
429
{
430
limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
431
le16_to_cpu(table->entries[0].usSclkLow);
432
limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
433
le16_to_cpu(table->entries[0].usMclkLow);
434
limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
435
limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
436
437
return 0;
438
}
439
440
441
static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
442
enum phm_platform_caps cap)
443
{
444
if (enable)
445
phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
446
else
447
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
448
}
449
450
static int set_platform_caps(struct pp_hwmgr *hwmgr,
451
unsigned long powerplay_caps)
452
{
453
set_hw_cap(
454
hwmgr,
455
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
456
PHM_PlatformCaps_PowerPlaySupport
457
);
458
459
set_hw_cap(
460
hwmgr,
461
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
462
PHM_PlatformCaps_BiosPowerSourceControl
463
);
464
465
set_hw_cap(
466
hwmgr,
467
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
468
PHM_PlatformCaps_EnableASPML0s
469
);
470
471
set_hw_cap(
472
hwmgr,
473
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
474
PHM_PlatformCaps_EnableASPML1
475
);
476
477
set_hw_cap(
478
hwmgr,
479
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
480
PHM_PlatformCaps_EnableBackbias
481
);
482
483
set_hw_cap(
484
hwmgr,
485
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
486
PHM_PlatformCaps_AutomaticDCTransition
487
);
488
489
set_hw_cap(
490
hwmgr,
491
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
492
PHM_PlatformCaps_GeminiPrimary
493
);
494
495
set_hw_cap(
496
hwmgr,
497
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
498
PHM_PlatformCaps_StepVddc
499
);
500
501
set_hw_cap(
502
hwmgr,
503
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
504
PHM_PlatformCaps_EnableVoltageControl
505
);
506
507
set_hw_cap(
508
hwmgr,
509
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
510
PHM_PlatformCaps_EnableSideportControl
511
);
512
513
set_hw_cap(
514
hwmgr,
515
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
516
PHM_PlatformCaps_TurnOffPll_ASPML1
517
);
518
519
set_hw_cap(
520
hwmgr,
521
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
522
PHM_PlatformCaps_EnableHTLinkControl
523
);
524
525
set_hw_cap(
526
hwmgr,
527
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
528
PHM_PlatformCaps_EnableMVDDControl
529
);
530
531
set_hw_cap(
532
hwmgr,
533
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
534
PHM_PlatformCaps_ControlVDDCI
535
);
536
537
set_hw_cap(
538
hwmgr,
539
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
540
PHM_PlatformCaps_RegulatorHot
541
);
542
543
set_hw_cap(
544
hwmgr,
545
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
546
PHM_PlatformCaps_BootStateOnAlert
547
);
548
549
set_hw_cap(
550
hwmgr,
551
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
552
PHM_PlatformCaps_DontWaitForVBlankOnAlert
553
);
554
555
set_hw_cap(
556
hwmgr,
557
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
558
PHM_PlatformCaps_BACO
559
);
560
561
set_hw_cap(
562
hwmgr,
563
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
564
PHM_PlatformCaps_NewCACVoltage
565
);
566
567
set_hw_cap(
568
hwmgr,
569
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
570
PHM_PlatformCaps_RevertGPIO5Polarity
571
);
572
573
set_hw_cap(
574
hwmgr,
575
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
576
PHM_PlatformCaps_Thermal2GPIO17
577
);
578
579
set_hw_cap(
580
hwmgr,
581
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
582
PHM_PlatformCaps_VRHotGPIOConfigurable
583
);
584
585
set_hw_cap(
586
hwmgr,
587
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
588
PHM_PlatformCaps_TempInversion
589
);
590
591
set_hw_cap(
592
hwmgr,
593
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
594
PHM_PlatformCaps_EVV
595
);
596
597
set_hw_cap(
598
hwmgr,
599
0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
600
PHM_PlatformCaps_CombinePCCWithThermalSignal
601
);
602
603
set_hw_cap(
604
hwmgr,
605
0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
606
PHM_PlatformCaps_LoadPostProductionFirmware
607
);
608
609
set_hw_cap(
610
hwmgr,
611
0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
612
PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
613
);
614
615
return 0;
616
}
617
618
static PP_StateClassificationFlags make_classification_flags(
619
struct pp_hwmgr *hwmgr,
620
USHORT classification,
621
USHORT classification2)
622
{
623
PP_StateClassificationFlags result = 0;
624
625
if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
626
result |= PP_StateClassificationFlag_Boot;
627
628
if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
629
result |= PP_StateClassificationFlag_Thermal;
630
631
if (classification &
632
ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
633
result |= PP_StateClassificationFlag_LimitedPowerSource;
634
635
if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
636
result |= PP_StateClassificationFlag_Rest;
637
638
if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
639
result |= PP_StateClassificationFlag_Forced;
640
641
if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
642
result |= PP_StateClassificationFlag_3DPerformance;
643
644
645
if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
646
result |= PP_StateClassificationFlag_ACOverdriveTemplate;
647
648
if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
649
result |= PP_StateClassificationFlag_Uvd;
650
651
if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
652
result |= PP_StateClassificationFlag_UvdHD;
653
654
if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
655
result |= PP_StateClassificationFlag_UvdSD;
656
657
if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
658
result |= PP_StateClassificationFlag_HD2;
659
660
if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
661
result |= PP_StateClassificationFlag_ACPI;
662
663
if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
664
result |= PP_StateClassificationFlag_LimitedPowerSource_2;
665
666
667
if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
668
result |= PP_StateClassificationFlag_ULV;
669
670
if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
671
result |= PP_StateClassificationFlag_UvdMVC;
672
673
return result;
674
}
675
676
static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
677
struct pp_power_state *ps,
678
uint8_t version,
679
const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
680
unsigned long rrr_index;
681
unsigned long tmp;
682
683
ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
684
ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
685
ps->classification.flags = make_classification_flags(hwmgr,
686
le16_to_cpu(pnon_clock_info->usClassification),
687
le16_to_cpu(pnon_clock_info->usClassification2));
688
689
ps->classification.temporary_state = false;
690
ps->classification.to_be_deleted = false;
691
tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
692
ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
693
694
ps->validation.singleDisplayOnly = (0 != tmp);
695
696
tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
697
ATOM_PPLIB_DISALLOW_ON_DC;
698
699
ps->validation.disallowOnDC = (0 != tmp);
700
701
ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
702
ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
703
ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
704
705
ps->display.disableFrameModulation = false;
706
707
rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
708
ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
709
ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
710
711
if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
712
static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
713
{ 0, 50, 0 };
714
715
ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
716
ps->display.explicitRefreshrate = look_up[rrr_index];
717
ps->display.limitRefreshrate = true;
718
719
if (ps->display.explicitRefreshrate == 0)
720
ps->display.limitRefreshrate = false;
721
} else
722
ps->display.limitRefreshrate = false;
723
724
tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
725
ATOM_PPLIB_ENABLE_VARIBRIGHT;
726
727
ps->display.enableVariBright = (0 != tmp);
728
729
tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
730
ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
731
732
ps->memory.dllOff = (0 != tmp);
733
734
ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
735
ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
736
737
ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
738
pnon_clock_info->ucMinTemperature;
739
740
ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
741
pnon_clock_info->ucMaxTemperature;
742
743
tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
744
ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
745
746
ps->software.disableLoadBalancing = tmp;
747
748
tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
749
ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
750
751
ps->software.enableSleepForTimestamps = (0 != tmp);
752
753
ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
754
755
if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
756
ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
757
ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
758
} else {
759
ps->uvd_clocks.VCLK = 0;
760
ps->uvd_clocks.DCLK = 0;
761
}
762
763
return 0;
764
}
765
766
static ULONG size_of_entry_v2(ULONG num_dpm_levels)
767
{
768
return (sizeof(UCHAR) + sizeof(UCHAR) +
769
(num_dpm_levels * sizeof(UCHAR)));
770
}
771
772
static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
773
const StateArray * pstate_arrays,
774
ULONG entry_index)
775
{
776
ULONG i;
777
const ATOM_PPLIB_STATE_V2 *pstate;
778
779
pstate = pstate_arrays->states;
780
if (entry_index <= pstate_arrays->ucNumEntries) {
781
for (i = 0; i < entry_index; i++)
782
pstate = (ATOM_PPLIB_STATE_V2 *)(
783
(unsigned long)pstate +
784
size_of_entry_v2(pstate->ucNumDPMLevels));
785
}
786
return pstate;
787
}
788
789
static const unsigned char soft_dummy_pp_table[] = {
790
0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
791
0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
792
0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
793
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
795
0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
796
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
797
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
800
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
801
0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
802
0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
803
0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
804
0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
805
0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
806
0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
807
0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
808
0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
809
0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
810
0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
811
0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
812
0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
813
0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
814
0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
815
0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
816
0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
817
0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
818
0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
819
0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
820
0x00
821
};
822
823
static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
824
struct pp_hwmgr *hwmgr)
825
{
826
const void *table_addr = hwmgr->soft_pp_table;
827
uint8_t frev, crev;
828
uint16_t size;
829
830
if (!table_addr) {
831
if (hwmgr->chip_id == CHIP_RAVEN) {
832
table_addr = &soft_dummy_pp_table[0];
833
hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
834
hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
835
} else {
836
table_addr = smu_atom_get_data_table(hwmgr->adev,
837
GetIndexIntoMasterTable(DATA, PowerPlayInfo),
838
&size, &frev, &crev);
839
hwmgr->soft_pp_table = table_addr;
840
hwmgr->soft_pp_table_size = size;
841
}
842
}
843
844
return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
845
}
846
847
int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
848
uint32_t *vol_rep_time, uint32_t *bb_rep_time)
849
{
850
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
851
852
PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
853
"Missing PowerPlay Table!", return -EINVAL);
854
855
*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
856
*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
857
858
return 0;
859
}
860
861
int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
862
unsigned long *num_of_entries)
863
{
864
const StateArray *pstate_arrays;
865
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
866
867
if (powerplay_table == NULL)
868
return -1;
869
870
if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
871
pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
872
le16_to_cpu(powerplay_table->usStateArrayOffset));
873
874
*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
875
} else
876
*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
877
878
return 0;
879
}
880
881
int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
882
unsigned long entry_index,
883
struct pp_power_state *ps,
884
pp_tables_hw_clock_info_callback func)
885
{
886
int i;
887
const StateArray *pstate_arrays;
888
const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
889
const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
890
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
891
int result = 0;
892
int res = 0;
893
894
const ClockInfoArray *pclock_arrays;
895
896
const NonClockInfoArray *pnon_clock_arrays;
897
898
const ATOM_PPLIB_STATE *pstate_entry;
899
900
if (powerplay_table == NULL)
901
return -1;
902
903
ps->classification.bios_index = entry_index;
904
905
if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
906
pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
907
le16_to_cpu(powerplay_table->usStateArrayOffset));
908
909
if (entry_index > pstate_arrays->ucNumEntries)
910
return -1;
911
912
pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
913
pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
914
le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
915
916
pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
917
le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
918
919
pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
920
(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
921
922
result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
923
924
for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
925
const void *pclock_info = (const void *)(
926
(unsigned long)(pclock_arrays->clockInfo) +
927
(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
928
res = func(hwmgr, &ps->hardware, i, pclock_info);
929
if ((0 == result) && (0 != res))
930
result = res;
931
}
932
} else {
933
if (entry_index > powerplay_table->ucNumStates)
934
return -1;
935
936
pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
937
le16_to_cpu(powerplay_table->usStateArrayOffset) +
938
entry_index * powerplay_table->ucStateEntrySize);
939
940
pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
941
le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
942
pstate_entry->ucNonClockStateIndex *
943
powerplay_table->ucNonClockSize);
944
945
result = init_non_clock_fields(hwmgr, ps,
946
powerplay_table->ucNonClockSize,
947
pnon_clock_info);
948
949
for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
950
const void *pclock_info = (const void *)((unsigned long)powerplay_table +
951
le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
952
pstate_entry->ucClockStateIndices[i] *
953
powerplay_table->ucClockInfoSize);
954
955
int res = func(hwmgr, &ps->hardware, i, pclock_info);
956
957
if ((0 == result) && (0 != res))
958
result = res;
959
}
960
}
961
962
if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
963
if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
964
result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
965
}
966
967
return result;
968
}
969
970
static int init_powerplay_tables(
971
struct pp_hwmgr *hwmgr,
972
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
973
)
974
{
975
return 0;
976
}
977
978
979
static int init_thermal_controller(
980
struct pp_hwmgr *hwmgr,
981
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
982
{
983
struct amdgpu_device *adev = hwmgr->adev;
984
985
hwmgr->thermal_controller.ucType =
986
powerplay_table->sThermalController.ucType;
987
hwmgr->thermal_controller.ucI2cLine =
988
powerplay_table->sThermalController.ucI2cLine;
989
hwmgr->thermal_controller.ucI2cAddress =
990
powerplay_table->sThermalController.ucI2cAddress;
991
992
hwmgr->thermal_controller.fanInfo.bNoFan =
993
(0 != (powerplay_table->sThermalController.ucFanParameters &
994
ATOM_PP_FANPARAMETERS_NOFAN));
995
996
hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
997
powerplay_table->sThermalController.ucFanParameters &
998
ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
999
1000
hwmgr->thermal_controller.fanInfo.ulMinRPM
1001
= powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1002
hwmgr->thermal_controller.fanInfo.ulMaxRPM
1003
= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1004
1005
set_hw_cap(hwmgr,
1006
ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1007
PHM_PlatformCaps_ThermalController);
1008
1009
if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
1010
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
1011
(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1012
1013
if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {
1014
hwmgr->thermal_controller.use_hw_fan_control = 1;
1015
return 0;
1016
} else {
1017
const ATOM_PPLIB_FANTABLE *fan_table =
1018
(const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) +
1019
le16_to_cpu(powerplay_table3->usFanTableOffset));
1020
1021
if (1 <= fan_table->ucFanTableFormat) {
1022
hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst =
1023
fan_table->ucTHyst;
1024
hwmgr->thermal_controller.advanceFanControlParameters.usTMin =
1025
le16_to_cpu(fan_table->usTMin);
1026
hwmgr->thermal_controller.advanceFanControlParameters.usTMed =
1027
le16_to_cpu(fan_table->usTMed);
1028
hwmgr->thermal_controller.advanceFanControlParameters.usTHigh =
1029
le16_to_cpu(fan_table->usTHigh);
1030
hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
1031
le16_to_cpu(fan_table->usPWMMin);
1032
hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed =
1033
le16_to_cpu(fan_table->usPWMMed);
1034
hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh =
1035
le16_to_cpu(fan_table->usPWMHigh);
1036
hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900;
1037
hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000;
1038
1039
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1040
PHM_PlatformCaps_MicrocodeFanControl);
1041
}
1042
1043
if (2 <= fan_table->ucFanTableFormat) {
1044
const ATOM_PPLIB_FANTABLE2 *fan_table2 =
1045
(const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) +
1046
le16_to_cpu(powerplay_table3->usFanTableOffset));
1047
hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
1048
le16_to_cpu(fan_table2->usTMax);
1049
}
1050
1051
if (3 <= fan_table->ucFanTableFormat) {
1052
const ATOM_PPLIB_FANTABLE3 *fan_table3 =
1053
(const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) +
1054
le16_to_cpu(powerplay_table3->usFanTableOffset));
1055
1056
hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =
1057
fan_table3->ucFanControlMode;
1058
1059
if ((3 == fan_table->ucFanTableFormat) &&
1060
(0x67B1 == adev->pdev->device))
1061
hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1062
47;
1063
else
1064
hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1065
le16_to_cpu(fan_table3->usFanPWMMax);
1066
1067
hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity =
1068
4836;
1069
hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
1070
le16_to_cpu(fan_table3->usFanOutputSensitivity);
1071
}
1072
1073
if (6 <= fan_table->ucFanTableFormat) {
1074
const ATOM_PPLIB_FANTABLE4 *fan_table4 =
1075
(const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) +
1076
le16_to_cpu(powerplay_table3->usFanTableOffset));
1077
1078
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1079
PHM_PlatformCaps_FanSpeedInTableIsRPM);
1080
1081
hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM =
1082
le16_to_cpu(fan_table4->usFanRPMMax);
1083
}
1084
1085
if (7 <= fan_table->ucFanTableFormat) {
1086
const ATOM_PPLIB_FANTABLE5 *fan_table5 =
1087
(const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) +
1088
le16_to_cpu(powerplay_table3->usFanTableOffset));
1089
1090
if (0x67A2 == adev->pdev->device ||
1091
0x67A9 == adev->pdev->device ||
1092
0x67B9 == adev->pdev->device) {
1093
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1094
PHM_PlatformCaps_GeminiRegulatorFanControlSupport);
1095
hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow =
1096
le16_to_cpu(fan_table5->usFanCurrentLow);
1097
hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh =
1098
le16_to_cpu(fan_table5->usFanCurrentHigh);
1099
hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow =
1100
le16_to_cpu(fan_table5->usFanRPMLow);
1101
hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh =
1102
le16_to_cpu(fan_table5->usFanRPMHigh);
1103
}
1104
}
1105
}
1106
}
1107
1108
return 0;
1109
}
1110
1111
static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
1112
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1113
const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
1114
{
1115
hwmgr->platform_descriptor.overdriveLimit.engineClock =
1116
le32_to_cpu(fw_info->ulASICMaxEngineClock);
1117
1118
hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1119
le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1120
1121
hwmgr->platform_descriptor.maxOverdriveVDDC =
1122
le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1123
1124
hwmgr->platform_descriptor.minOverdriveVDDC =
1125
le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1126
1127
hwmgr->platform_descriptor.maxOverdriveVDDC =
1128
le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1129
1130
hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1131
return 0;
1132
}
1133
1134
static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1135
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1136
const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1137
{
1138
const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1139
const ATOM_PPLIB_EXTENDEDHEADER *header;
1140
1141
if (le16_to_cpu(powerplay_table->usTableSize) <
1142
sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1143
return 0;
1144
1145
powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1146
1147
if (0 == powerplay_table3->usExtendendedHeaderOffset)
1148
return 0;
1149
1150
header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1151
le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1152
1153
hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1154
hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1155
1156
1157
hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1158
hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1159
hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1160
1161
return 0;
1162
}
1163
1164
static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1165
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1166
{
1167
int result = 0;
1168
uint8_t frev, crev;
1169
uint16_t size;
1170
1171
const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1172
1173
hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1174
hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1175
hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1176
hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1177
hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1178
1179
if (hwmgr->chip_id == CHIP_RAVEN)
1180
return 0;
1181
1182
/* We assume here that fw_info is unchanged if this call fails.*/
1183
fw_info = smu_atom_get_data_table(hwmgr->adev,
1184
GetIndexIntoMasterTable(DATA, FirmwareInfo),
1185
&size, &frev, &crev);
1186
PP_ASSERT_WITH_CODE(fw_info != NULL,
1187
"Missing firmware info!", return -EINVAL);
1188
1189
if ((fw_info->ucTableFormatRevision == 1)
1190
&& (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1191
result = init_overdrive_limits_V1_4(hwmgr,
1192
powerplay_table,
1193
(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1194
1195
else if ((fw_info->ucTableFormatRevision == 2)
1196
&& (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1197
result = init_overdrive_limits_V2_1(hwmgr,
1198
powerplay_table,
1199
(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1200
1201
return result;
1202
}
1203
1204
static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1205
struct phm_uvd_clock_voltage_dependency_table **ptable,
1206
const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1207
const UVDClockInfoArray *array)
1208
{
1209
unsigned long i;
1210
struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1211
1212
uvd_table = kzalloc(struct_size(uvd_table, entries, table->numEntries),
1213
GFP_KERNEL);
1214
if (!uvd_table)
1215
return -ENOMEM;
1216
1217
uvd_table->count = table->numEntries;
1218
1219
for (i = 0; i < table->numEntries; i++) {
1220
const UVDClockInfo *entry =
1221
&array->entries[table->entries[i].ucUVDClockInfoIndex];
1222
uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1223
uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1224
| le16_to_cpu(entry->usVClkLow);
1225
uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1226
| le16_to_cpu(entry->usDClkLow);
1227
}
1228
1229
*ptable = uvd_table;
1230
1231
return 0;
1232
}
1233
1234
static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1235
struct phm_vce_clock_voltage_dependency_table **ptable,
1236
const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1237
const VCEClockInfoArray *array)
1238
{
1239
unsigned long i;
1240
struct phm_vce_clock_voltage_dependency_table *vce_table;
1241
1242
vce_table = kzalloc(struct_size(vce_table, entries, table->numEntries),
1243
GFP_KERNEL);
1244
if (!vce_table)
1245
return -ENOMEM;
1246
1247
vce_table->count = table->numEntries;
1248
for (i = 0; i < table->numEntries; i++) {
1249
const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1250
1251
vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1252
vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1253
| le16_to_cpu(entry->usEVClkLow);
1254
vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1255
| le16_to_cpu(entry->usECClkLow);
1256
}
1257
1258
*ptable = vce_table;
1259
1260
return 0;
1261
}
1262
1263
static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1264
struct phm_samu_clock_voltage_dependency_table **ptable,
1265
const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1266
{
1267
unsigned long i;
1268
struct phm_samu_clock_voltage_dependency_table *samu_table;
1269
1270
samu_table = kzalloc(struct_size(samu_table, entries, table->numEntries),
1271
GFP_KERNEL);
1272
if (!samu_table)
1273
return -ENOMEM;
1274
1275
samu_table->count = table->numEntries;
1276
1277
for (i = 0; i < table->numEntries; i++) {
1278
samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1279
samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1280
| le16_to_cpu(table->entries[i].usSAMClockLow);
1281
}
1282
1283
*ptable = samu_table;
1284
1285
return 0;
1286
}
1287
1288
static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1289
struct phm_acp_clock_voltage_dependency_table **ptable,
1290
const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1291
{
1292
unsigned long i;
1293
struct phm_acp_clock_voltage_dependency_table *acp_table;
1294
1295
acp_table = kzalloc(struct_size(acp_table, entries, table->numEntries),
1296
GFP_KERNEL);
1297
if (!acp_table)
1298
return -ENOMEM;
1299
1300
acp_table->count = (unsigned long)table->numEntries;
1301
1302
for (i = 0; i < table->numEntries; i++) {
1303
acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1304
acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1305
| le16_to_cpu(table->entries[i].usACPClockLow);
1306
}
1307
1308
*ptable = acp_table;
1309
1310
return 0;
1311
}
1312
1313
static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1314
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1315
{
1316
ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1317
ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1318
int result = 0;
1319
1320
uint16_t vce_clock_info_array_offset;
1321
uint16_t uvd_clock_info_array_offset;
1322
uint16_t table_offset;
1323
1324
hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1325
hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1326
hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1327
hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1328
hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1329
hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1330
hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1331
hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1332
hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1333
hwmgr->dyn_state.ppm_parameter_table = NULL;
1334
hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1335
1336
vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1337
hwmgr, powerplay_table);
1338
table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1339
powerplay_table);
1340
if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1341
const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1342
(((unsigned long) powerplay_table) +
1343
vce_clock_info_array_offset);
1344
const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1345
(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1346
(((unsigned long) powerplay_table) + table_offset);
1347
result = get_vce_clock_voltage_limit_table(hwmgr,
1348
&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1349
table, array);
1350
}
1351
1352
uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1353
table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1354
1355
if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1356
const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1357
(((unsigned long) powerplay_table) +
1358
uvd_clock_info_array_offset);
1359
const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1360
(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1361
(((unsigned long) powerplay_table) + table_offset);
1362
result = get_uvd_clock_voltage_limit_table(hwmgr,
1363
&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1364
}
1365
1366
table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1367
powerplay_table);
1368
1369
if (table_offset > 0) {
1370
const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1371
(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1372
(((unsigned long) powerplay_table) + table_offset);
1373
result = get_samu_clock_voltage_limit_table(hwmgr,
1374
&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1375
}
1376
1377
table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1378
powerplay_table);
1379
1380
if (table_offset > 0) {
1381
const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1382
(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1383
(((unsigned long) powerplay_table) + table_offset);
1384
result = get_acp_clock_voltage_limit_table(hwmgr,
1385
&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1386
}
1387
1388
table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1389
if (table_offset > 0) {
1390
UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1391
1392
if (rev_id > 0) {
1393
const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1394
(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1395
(((unsigned long) powerplay_table) + table_offset);
1396
result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1397
&tune_table->power_tune_table,
1398
le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1399
hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1400
le16_to_cpu(tune_table->usTjMax);
1401
} else {
1402
const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1403
(const ATOM_PPLIB_POWERTUNE_Table *)
1404
(((unsigned long) powerplay_table) + table_offset);
1405
result = get_cac_tdp_table(hwmgr,
1406
&hwmgr->dyn_state.cac_dtp_table,
1407
&tune_table->power_tune_table, 255);
1408
}
1409
}
1410
1411
if (le16_to_cpu(powerplay_table->usTableSize) >=
1412
sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1413
const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1414
(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1415
if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1416
table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1417
(((unsigned long) powerplay_table4) +
1418
le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1419
result = get_clock_voltage_dependency_table(hwmgr,
1420
&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1421
}
1422
1423
if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1424
table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1425
(((unsigned long) powerplay_table4) +
1426
le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1427
result = get_clock_voltage_dependency_table(hwmgr,
1428
&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1429
}
1430
1431
if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1432
table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1433
(((unsigned long) powerplay_table4) +
1434
le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1435
result = get_clock_voltage_dependency_table(hwmgr,
1436
&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1437
}
1438
1439
if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1440
limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1441
(((unsigned long) powerplay_table4) +
1442
le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1443
result = get_clock_voltage_limit(hwmgr,
1444
&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1445
}
1446
1447
if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1448
(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1449
result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1450
hwmgr->dyn_state.vddc_dependency_on_mclk);
1451
1452
if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1453
(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1454
result = get_valid_clk(hwmgr,
1455
&hwmgr->dyn_state.valid_sclk_values,
1456
hwmgr->dyn_state.vddc_dependency_on_sclk);
1457
1458
if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1459
table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1460
(((unsigned long) powerplay_table4) +
1461
le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1462
result = get_clock_voltage_dependency_table(hwmgr,
1463
&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1464
}
1465
}
1466
1467
table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1468
powerplay_table);
1469
1470
if (table_offset > 0) {
1471
table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1472
(((unsigned long) powerplay_table) + table_offset);
1473
result = get_clock_voltage_dependency_table(hwmgr,
1474
&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1475
}
1476
1477
return result;
1478
}
1479
1480
static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1481
struct phm_cac_leakage_table **ptable,
1482
const ATOM_PPLIB_CAC_Leakage_Table *table)
1483
{
1484
struct phm_cac_leakage_table *cac_leakage_table;
1485
unsigned long i;
1486
1487
if (!hwmgr || !table || !ptable)
1488
return -EINVAL;
1489
1490
cac_leakage_table = kzalloc(struct_size(cac_leakage_table, entries, table->ucNumEntries),
1491
GFP_KERNEL);
1492
if (!cac_leakage_table)
1493
return -ENOMEM;
1494
1495
cac_leakage_table->count = (ULONG)table->ucNumEntries;
1496
1497
for (i = 0; i < cac_leakage_table->count; i++) {
1498
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1499
PHM_PlatformCaps_EVV)) {
1500
cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1501
cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1502
cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1503
} else {
1504
cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc);
1505
cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1506
}
1507
}
1508
1509
*ptable = cac_leakage_table;
1510
1511
return 0;
1512
}
1513
1514
static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1515
ATOM_PPLIB_PPM_Table *atom_ppm_table)
1516
{
1517
struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1518
1519
if (NULL == ptr)
1520
return -ENOMEM;
1521
1522
ptr->ppm_design = atom_ppm_table->ucPpmDesign;
1523
ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1524
ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1525
ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1526
ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1527
ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1528
ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP);
1529
ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1530
ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1531
ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax);
1532
hwmgr->dyn_state.ppm_parameter_table = ptr;
1533
1534
return 0;
1535
}
1536
1537
static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1538
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1539
{
1540
int result = 0;
1541
1542
if (le16_to_cpu(powerplay_table->usTableSize) >=
1543
sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1544
const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1545
(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1546
const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1547
(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1548
(&ptable5->basicTable4);
1549
const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1550
(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1551
(&ptable4->basicTable3);
1552
const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
1553
uint16_t table_offset;
1554
ATOM_PPLIB_PPM_Table *atom_ppm_table;
1555
1556
hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit);
1557
hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1558
1559
hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit);
1560
hwmgr->platform_descriptor.TDPAdjustment = 0;
1561
1562
hwmgr->platform_descriptor.VidAdjustment = 0;
1563
hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1564
hwmgr->platform_descriptor.VidMinLimit = 0;
1565
hwmgr->platform_descriptor.VidMaxLimit = 1500000;
1566
hwmgr->platform_descriptor.VidStep = 6250;
1567
1568
hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1569
1570
if (hwmgr->platform_descriptor.TDPODLimit != 0)
1571
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1572
PHM_PlatformCaps_PowerControl);
1573
1574
hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1575
1576
hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1577
1578
hwmgr->dyn_state.cac_leakage_table = NULL;
1579
1580
if (0 != ptable5->usCACLeakageTableOffset) {
1581
const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1582
(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1583
le16_to_cpu(ptable5->usCACLeakageTableOffset));
1584
result = get_cac_leakage_table(hwmgr,
1585
&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1586
}
1587
1588
hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1589
1590
hwmgr->dyn_state.ppm_parameter_table = NULL;
1591
1592
if (0 != ptable3->usExtendendedHeaderOffset) {
1593
extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1594
(((unsigned long)powerplay_table) +
1595
le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1596
if ((extended_header->usPPMTableOffset > 0) &&
1597
le16_to_cpu(extended_header->usSize) >=
1598
SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1599
table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1600
atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1601
(((unsigned long)powerplay_table) + table_offset);
1602
if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1603
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1604
PHM_PlatformCaps_EnablePlatformPowerManagement);
1605
}
1606
}
1607
}
1608
return result;
1609
}
1610
1611
static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1612
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1613
{
1614
if (le16_to_cpu(powerplay_table->usTableSize) >=
1615
sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1616
const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1617
(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1618
1619
if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1620
const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1621
(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1622
(((unsigned long)powerplay_table4) +
1623
le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1624
struct phm_phase_shedding_limits_table *table;
1625
unsigned long i;
1626
1627
1628
table = kzalloc(struct_size(table, entries, ptable->ucNumEntries),
1629
GFP_KERNEL);
1630
if (!table)
1631
return -ENOMEM;
1632
1633
table->count = (unsigned long)ptable->ucNumEntries;
1634
1635
for (i = 0; i < table->count; i++) {
1636
table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1637
table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1638
| le16_to_cpu(ptable->entries[i].usSclkLow);
1639
table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1640
| le16_to_cpu(ptable->entries[i].usMclkLow);
1641
}
1642
hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1643
}
1644
}
1645
1646
return 0;
1647
}
1648
1649
static int get_number_of_vce_state_table_entries(
1650
struct pp_hwmgr *hwmgr)
1651
{
1652
const ATOM_PPLIB_POWERPLAYTABLE *table =
1653
get_powerplay_table(hwmgr);
1654
const ATOM_PPLIB_VCE_State_Table *vce_table =
1655
get_vce_state_table(hwmgr, table);
1656
1657
if (vce_table)
1658
return vce_table->numEntries;
1659
1660
return 0;
1661
}
1662
1663
static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1664
unsigned long i,
1665
struct amd_vce_state *vce_state,
1666
void **clock_info,
1667
unsigned long *flag)
1668
{
1669
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1670
1671
const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1672
1673
unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1674
1675
const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1676
1677
const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1678
le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1679
1680
const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1681
1682
const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1683
1684
unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1685
1686
*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1687
1688
vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1689
vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1690
1691
*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1692
1693
return 0;
1694
}
1695
1696
1697
static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1698
{
1699
int result;
1700
const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1701
1702
if (hwmgr->chip_id == CHIP_RAVEN)
1703
return 0;
1704
1705
hwmgr->need_pp_table_upload = true;
1706
1707
powerplay_table = get_powerplay_table(hwmgr);
1708
1709
result = init_powerplay_tables(hwmgr, powerplay_table);
1710
1711
PP_ASSERT_WITH_CODE((result == 0),
1712
"init_powerplay_tables failed", return result);
1713
1714
result = set_platform_caps(hwmgr,
1715
le32_to_cpu(powerplay_table->ulPlatformCaps));
1716
1717
PP_ASSERT_WITH_CODE((result == 0),
1718
"set_platform_caps failed", return result);
1719
1720
result = init_thermal_controller(hwmgr, powerplay_table);
1721
1722
PP_ASSERT_WITH_CODE((result == 0),
1723
"init_thermal_controller failed", return result);
1724
1725
result = init_overdrive_limits(hwmgr, powerplay_table);
1726
1727
PP_ASSERT_WITH_CODE((result == 0),
1728
"init_overdrive_limits failed", return result);
1729
1730
result = init_clock_voltage_dependency(hwmgr,
1731
powerplay_table);
1732
1733
PP_ASSERT_WITH_CODE((result == 0),
1734
"init_clock_voltage_dependency failed", return result);
1735
1736
result = init_dpm2_parameters(hwmgr, powerplay_table);
1737
1738
PP_ASSERT_WITH_CODE((result == 0),
1739
"init_dpm2_parameters failed", return result);
1740
1741
result = init_phase_shedding_table(hwmgr, powerplay_table);
1742
1743
PP_ASSERT_WITH_CODE((result == 0),
1744
"init_phase_shedding_table failed", return result);
1745
1746
return result;
1747
}
1748
1749
static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1750
{
1751
if (hwmgr->chip_id == CHIP_RAVEN)
1752
return 0;
1753
1754
kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1755
hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1756
1757
kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1758
hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1759
1760
kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1761
hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1762
1763
kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1764
hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1765
1766
kfree(hwmgr->dyn_state.valid_mclk_values);
1767
hwmgr->dyn_state.valid_mclk_values = NULL;
1768
1769
kfree(hwmgr->dyn_state.valid_sclk_values);
1770
hwmgr->dyn_state.valid_sclk_values = NULL;
1771
1772
kfree(hwmgr->dyn_state.cac_leakage_table);
1773
hwmgr->dyn_state.cac_leakage_table = NULL;
1774
1775
kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1776
hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1777
1778
kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1779
hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1780
1781
kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1782
hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1783
1784
kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1785
hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1786
1787
kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1788
hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1789
1790
kfree(hwmgr->dyn_state.cac_dtp_table);
1791
hwmgr->dyn_state.cac_dtp_table = NULL;
1792
1793
kfree(hwmgr->dyn_state.ppm_parameter_table);
1794
hwmgr->dyn_state.ppm_parameter_table = NULL;
1795
1796
kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1797
hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1798
1799
return 0;
1800
}
1801
1802
const struct pp_table_func pptable_funcs = {
1803
.pptable_init = pp_tables_initialize,
1804
.pptable_fini = pp_tables_uninitialize,
1805
.pptable_get_number_of_vce_state_table_entries =
1806
get_number_of_vce_state_table_entries,
1807
.pptable_get_vce_state_table_entry =
1808
get_vce_state_table_entry,
1809
};
1810
1811
1812