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