GNU Linux-libre 4.19.211-gnu1
[releases.git] / drivers / gpu / drm / amd / powerplay / hwmgr / processpptables.c
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 <drm/amdgpu_drm.h>
28 #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
48 static 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
72 static 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
84 static 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
100 static 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
113 static 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
128 static 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
138 static 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
150 static 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
172 static 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
183 static 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
201 static 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
215 static 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
238 static 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
251 static 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
274 static 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
286 static 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
310 static 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
338 static 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
362 static 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
375 static 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
406 static 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
428 static 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
443 static 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
452 static 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
620 static 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
678 static 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
738         ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
739                             ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
740
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
770 static ULONG size_of_entry_v2(ULONG num_dpm_levels)
771 {
772         return (sizeof(UCHAR) + sizeof(UCHAR) +
773                         (num_dpm_levels * sizeof(UCHAR)));
774 }
775
776 static 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
793 static const 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 };
826
827 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
828                                      struct pp_hwmgr *hwmgr)
829 {
830         const void *table_addr = hwmgr->soft_pp_table;
831         uint8_t frev, crev;
832         uint16_t size;
833
834         if (!table_addr) {
835                 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 = smu_atom_get_data_table(hwmgr->adev,
841                                         GetIndexIntoMasterTable(DATA, PowerPlayInfo),
842                                         &size, &frev, &crev);
843                         hwmgr->soft_pp_table = table_addr;
844                         hwmgr->soft_pp_table_size = size;
845                 }
846         }
847
848         return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
849 }
850
851 int 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 }
864
865 int 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
885 int 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
965         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         }
969
970         return result;
971 }
972
973 static int init_powerplay_tables(
974                         struct pp_hwmgr *hwmgr,
975                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
976 )
977 {
978         return 0;
979 }
980
981
982 static int init_thermal_controller(
983                         struct pp_hwmgr *hwmgr,
984                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
985 {
986         hwmgr->thermal_controller.ucType =
987                         powerplay_table->sThermalController.ucType;
988         hwmgr->thermal_controller.ucI2cLine =
989                         powerplay_table->sThermalController.ucI2cLine;
990         hwmgr->thermal_controller.ucI2cAddress =
991                         powerplay_table->sThermalController.ucI2cAddress;
992
993         hwmgr->thermal_controller.fanInfo.bNoFan =
994                 (0 != (powerplay_table->sThermalController.ucFanParameters &
995                         ATOM_PP_FANPARAMETERS_NOFAN));
996
997         hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
998                 powerplay_table->sThermalController.ucFanParameters &
999                 ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
1000
1001         hwmgr->thermal_controller.fanInfo.ulMinRPM
1002                 = powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1003         hwmgr->thermal_controller.fanInfo.ulMaxRPM
1004                 = powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1005
1006         set_hw_cap(hwmgr,
1007                    ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1008                    PHM_PlatformCaps_ThermalController);
1009
1010         hwmgr->thermal_controller.use_hw_fan_control = 1;
1011
1012         return 0;
1013 }
1014
1015 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
1016                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1017                         const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
1018 {
1019         hwmgr->platform_descriptor.overdriveLimit.engineClock =
1020                                 le32_to_cpu(fw_info->ulASICMaxEngineClock);
1021
1022         hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1023                                 le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1024
1025         hwmgr->platform_descriptor.maxOverdriveVDDC =
1026                 le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1027
1028         hwmgr->platform_descriptor.minOverdriveVDDC =
1029                            le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1030
1031         hwmgr->platform_descriptor.maxOverdriveVDDC =
1032                            le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1033
1034         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1035         return 0;
1036 }
1037
1038 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1039                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1040                         const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1041 {
1042         const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1043         const ATOM_PPLIB_EXTENDEDHEADER *header;
1044
1045         if (le16_to_cpu(powerplay_table->usTableSize) <
1046             sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1047                 return 0;
1048
1049         powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1050
1051         if (0 == powerplay_table3->usExtendendedHeaderOffset)
1052                 return 0;
1053
1054         header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1055                         le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1056
1057         hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1058         hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1059
1060
1061         hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1062         hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1063         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1064
1065         return 0;
1066 }
1067
1068 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1069                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1070 {
1071         int result = 0;
1072         uint8_t frev, crev;
1073         uint16_t size;
1074
1075         const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1076
1077         hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1078         hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1079         hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1080         hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1081         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1082
1083         if (hwmgr->chip_id == CHIP_RAVEN)
1084                 return 0;
1085
1086         /* We assume here that fw_info is unchanged if this call fails.*/
1087         fw_info = smu_atom_get_data_table(hwmgr->adev,
1088                          GetIndexIntoMasterTable(DATA, FirmwareInfo),
1089                          &size, &frev, &crev);
1090
1091         if ((fw_info->ucTableFormatRevision == 1)
1092                 && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1093                 result = init_overdrive_limits_V1_4(hwmgr,
1094                                 powerplay_table,
1095                                 (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1096
1097         else if ((fw_info->ucTableFormatRevision == 2)
1098                 && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1099                 result = init_overdrive_limits_V2_1(hwmgr,
1100                                 powerplay_table,
1101                                 (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1102
1103         return result;
1104 }
1105
1106 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1107                 struct phm_uvd_clock_voltage_dependency_table **ptable,
1108                 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1109                 const UVDClockInfoArray *array)
1110 {
1111         unsigned long table_size, i;
1112         struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1113
1114         table_size = sizeof(unsigned long) +
1115                  sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1116                  table->numEntries;
1117
1118         uvd_table = kzalloc(table_size, GFP_KERNEL);
1119         if (NULL == uvd_table)
1120                 return -ENOMEM;
1121
1122         uvd_table->count = table->numEntries;
1123
1124         for (i = 0; i < table->numEntries; i++) {
1125                 const UVDClockInfo *entry =
1126                         &array->entries[table->entries[i].ucUVDClockInfoIndex];
1127                 uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1128                 uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1129                                          | le16_to_cpu(entry->usVClkLow);
1130                 uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1131                                          | le16_to_cpu(entry->usDClkLow);
1132         }
1133
1134         *ptable = uvd_table;
1135
1136         return 0;
1137 }
1138
1139 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1140                 struct phm_vce_clock_voltage_dependency_table **ptable,
1141                 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1142                 const VCEClockInfoArray    *array)
1143 {
1144         unsigned long table_size, i;
1145         struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1146
1147         table_size = sizeof(unsigned long) +
1148                         sizeof(struct phm_vce_clock_voltage_dependency_table)
1149                         * table->numEntries;
1150
1151         vce_table = kzalloc(table_size, GFP_KERNEL);
1152         if (NULL == vce_table)
1153                 return -ENOMEM;
1154
1155         vce_table->count = table->numEntries;
1156         for (i = 0; i < table->numEntries; i++) {
1157                 const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1158
1159                 vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1160                 vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1161                                         | le16_to_cpu(entry->usEVClkLow);
1162                 vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1163                                         | le16_to_cpu(entry->usECClkLow);
1164         }
1165
1166         *ptable = vce_table;
1167
1168         return 0;
1169 }
1170
1171 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1172                  struct phm_samu_clock_voltage_dependency_table **ptable,
1173                  const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1174 {
1175         unsigned long table_size, i;
1176         struct phm_samu_clock_voltage_dependency_table *samu_table;
1177
1178         table_size = sizeof(unsigned long) +
1179                 sizeof(struct phm_samu_clock_voltage_dependency_table) *
1180                 table->numEntries;
1181
1182         samu_table = kzalloc(table_size, GFP_KERNEL);
1183         if (NULL == samu_table)
1184                 return -ENOMEM;
1185
1186         samu_table->count = table->numEntries;
1187
1188         for (i = 0; i < table->numEntries; i++) {
1189                 samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1190                 samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1191                                          | le16_to_cpu(table->entries[i].usSAMClockLow);
1192         }
1193
1194         *ptable = samu_table;
1195
1196         return 0;
1197 }
1198
1199 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1200                 struct phm_acp_clock_voltage_dependency_table **ptable,
1201                 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1202 {
1203         unsigned table_size, i;
1204         struct phm_acp_clock_voltage_dependency_table *acp_table;
1205
1206         table_size = sizeof(unsigned long) +
1207                 sizeof(struct phm_acp_clock_voltage_dependency_table) *
1208                 table->numEntries;
1209
1210         acp_table = kzalloc(table_size, GFP_KERNEL);
1211         if (NULL == acp_table)
1212                 return -ENOMEM;
1213
1214         acp_table->count = (unsigned long)table->numEntries;
1215
1216         for (i = 0; i < table->numEntries; i++) {
1217                 acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1218                 acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1219                                          | le16_to_cpu(table->entries[i].usACPClockLow);
1220         }
1221
1222         *ptable = acp_table;
1223
1224         return 0;
1225 }
1226
1227 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1228                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1229 {
1230         ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1231         ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1232         int result = 0;
1233
1234         uint16_t vce_clock_info_array_offset;
1235         uint16_t uvd_clock_info_array_offset;
1236         uint16_t table_offset;
1237
1238         hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1239         hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1240         hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1241         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1242         hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1243         hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1244         hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1245         hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1246         hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1247         hwmgr->dyn_state.ppm_parameter_table = NULL;
1248         hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1249
1250         vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1251                                                 hwmgr, powerplay_table);
1252         table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1253                                                 powerplay_table);
1254         if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1255                 const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1256                                 (((unsigned long) powerplay_table) +
1257                                 vce_clock_info_array_offset);
1258                 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1259                                 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1260                                 (((unsigned long) powerplay_table) + table_offset);
1261                 result = get_vce_clock_voltage_limit_table(hwmgr,
1262                                 &hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1263                                 table, array);
1264         }
1265
1266         uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1267         table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1268
1269         if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1270                 const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1271                                 (((unsigned long) powerplay_table) +
1272                                 uvd_clock_info_array_offset);
1273                 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1274                                 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1275                                 (((unsigned long) powerplay_table) + table_offset);
1276                 result = get_uvd_clock_voltage_limit_table(hwmgr,
1277                                 &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1278         }
1279
1280         table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1281                                                             powerplay_table);
1282
1283         if (table_offset > 0) {
1284                 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1285                                 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1286                                 (((unsigned long) powerplay_table) + table_offset);
1287                 result = get_samu_clock_voltage_limit_table(hwmgr,
1288                                 &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1289         }
1290
1291         table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1292                                                              powerplay_table);
1293
1294         if (table_offset > 0) {
1295                 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1296                                 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1297                                 (((unsigned long) powerplay_table) + table_offset);
1298                 result = get_acp_clock_voltage_limit_table(hwmgr,
1299                                 &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1300         }
1301
1302         table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1303         if (table_offset > 0) {
1304                 UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1305
1306                 if (rev_id > 0) {
1307                         const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1308                                 (const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1309                                 (((unsigned long) powerplay_table) + table_offset);
1310                         result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1311                                 &tune_table->power_tune_table,
1312                                 le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1313                         hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1314                                 le16_to_cpu(tune_table->usTjMax);
1315                 } else {
1316                         const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1317                                 (const ATOM_PPLIB_POWERTUNE_Table *)
1318                                 (((unsigned long) powerplay_table) + table_offset);
1319                         result = get_cac_tdp_table(hwmgr,
1320                                 &hwmgr->dyn_state.cac_dtp_table,
1321                                 &tune_table->power_tune_table, 255);
1322                 }
1323         }
1324
1325         if (le16_to_cpu(powerplay_table->usTableSize) >=
1326                 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1327                 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1328                                 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1329                 if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1330                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1331                                 (((unsigned long) powerplay_table4) +
1332                                 powerplay_table4->usVddcDependencyOnSCLKOffset);
1333                         result = get_clock_voltage_dependency_table(hwmgr,
1334                                 &hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1335                 }
1336
1337                 if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1338                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1339                                 (((unsigned long) powerplay_table4) +
1340                                 powerplay_table4->usVddciDependencyOnMCLKOffset);
1341                         result = get_clock_voltage_dependency_table(hwmgr,
1342                                 &hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1343                 }
1344
1345                 if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1346                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1347                                 (((unsigned long) powerplay_table4) +
1348                                 powerplay_table4->usVddcDependencyOnMCLKOffset);
1349                         result = get_clock_voltage_dependency_table(hwmgr,
1350                                 &hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1351                 }
1352
1353                 if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1354                         limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1355                                 (((unsigned long) powerplay_table4) +
1356                                 powerplay_table4->usMaxClockVoltageOnDCOffset);
1357                         result = get_clock_voltage_limit(hwmgr,
1358                                 &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1359                 }
1360
1361                 if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1362                         (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1363                         result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1364                                         hwmgr->dyn_state.vddc_dependency_on_mclk);
1365
1366                 if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1367                         (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1368                         result = get_valid_clk(hwmgr,
1369                                 &hwmgr->dyn_state.valid_sclk_values,
1370                                 hwmgr->dyn_state.vddc_dependency_on_sclk);
1371
1372                 if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1373                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1374                                 (((unsigned long) powerplay_table4) +
1375                                 powerplay_table4->usMvddDependencyOnMCLKOffset);
1376                         result = get_clock_voltage_dependency_table(hwmgr,
1377                                 &hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1378                 }
1379         }
1380
1381         table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1382                                                                 powerplay_table);
1383
1384         if (table_offset > 0) {
1385                 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1386                         (((unsigned long) powerplay_table) + table_offset);
1387                 result = get_clock_voltage_dependency_table(hwmgr,
1388                         &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1389         }
1390
1391         return result;
1392 }
1393
1394 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1395                                  struct phm_cac_leakage_table **ptable,
1396                                 const ATOM_PPLIB_CAC_Leakage_Table *table)
1397 {
1398         struct phm_cac_leakage_table  *cac_leakage_table;
1399         unsigned long            table_size, i;
1400
1401         if (hwmgr == NULL || table == NULL || ptable == NULL)
1402                 return -EINVAL;
1403
1404         table_size = sizeof(ULONG) +
1405                 (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1406
1407         cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1408
1409         if (cac_leakage_table == NULL)
1410                 return -ENOMEM;
1411
1412         cac_leakage_table->count = (ULONG)table->ucNumEntries;
1413
1414         for (i = 0; i < cac_leakage_table->count; i++) {
1415                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1416                                 PHM_PlatformCaps_EVV)) {
1417                         cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1418                         cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1419                         cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1420                 } else {
1421                         cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1422                         cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1423                 }
1424         }
1425
1426         *ptable = cac_leakage_table;
1427
1428         return 0;
1429 }
1430
1431 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1432                         ATOM_PPLIB_PPM_Table *atom_ppm_table)
1433 {
1434         struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1435
1436         if (NULL == ptr)
1437                 return -ENOMEM;
1438
1439         ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1440         ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1441         ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1442         ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1443         ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1444         ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1445         ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1446         ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1447         ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1448         ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1449         hwmgr->dyn_state.ppm_parameter_table = ptr;
1450
1451         return 0;
1452 }
1453
1454 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1455                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1456 {
1457         int result = 0;
1458
1459         if (le16_to_cpu(powerplay_table->usTableSize) >=
1460             sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1461                 const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1462                                 (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1463                 const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1464                                 (const ATOM_PPLIB_POWERPLAYTABLE4 *)
1465                                 (&ptable5->basicTable4);
1466                 const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1467                                 (const ATOM_PPLIB_POWERPLAYTABLE3 *)
1468                                 (&ptable4->basicTable3);
1469                 const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1470                 uint16_t table_offset;
1471                 ATOM_PPLIB_PPM_Table *atom_ppm_table;
1472
1473                 hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1474                 hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1475
1476                 hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1477                 hwmgr->platform_descriptor.TDPAdjustment = 0;
1478
1479                 hwmgr->platform_descriptor.VidAdjustment = 0;
1480                 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1481                 hwmgr->platform_descriptor.VidMinLimit     = 0;
1482                 hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1483                 hwmgr->platform_descriptor.VidStep         = 6250;
1484
1485                 hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1486
1487                 if (hwmgr->platform_descriptor.TDPODLimit != 0)
1488                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1489                                         PHM_PlatformCaps_PowerControl);
1490
1491                 hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1492
1493                 hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1494
1495                 hwmgr->dyn_state.cac_leakage_table = NULL;
1496
1497                 if (0 != ptable5->usCACLeakageTableOffset) {
1498                         const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1499                                 (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1500                                 le16_to_cpu(ptable5->usCACLeakageTableOffset));
1501                         result = get_cac_leakage_table(hwmgr,
1502                                 &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1503                 }
1504
1505                 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1506
1507                 hwmgr->dyn_state.ppm_parameter_table = NULL;
1508
1509                 if (0 != ptable3->usExtendendedHeaderOffset) {
1510                         extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1511                                         (((unsigned long)powerplay_table) +
1512                                         le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1513                         if ((extended_header->usPPMTableOffset > 0) &&
1514                                 le16_to_cpu(extended_header->usSize) >=
1515                                     SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1516                                 table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1517                                 atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1518                                         (((unsigned long)powerplay_table) + table_offset);
1519                                 if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1520                                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1521                                                 PHM_PlatformCaps_EnablePlatformPowerManagement);
1522                         }
1523                 }
1524         }
1525         return result;
1526 }
1527
1528 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1529                 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1530 {
1531         if (le16_to_cpu(powerplay_table->usTableSize) >=
1532             sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1533                 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1534                                 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1535
1536                 if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1537                         const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1538                                 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
1539                                 (((unsigned long)powerplay_table4) +
1540                                 le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1541                         struct phm_phase_shedding_limits_table *table;
1542                         unsigned long size, i;
1543
1544
1545                         size = sizeof(unsigned long) +
1546                                 (sizeof(struct phm_phase_shedding_limits_table) *
1547                                 ptable->ucNumEntries);
1548
1549                         table = kzalloc(size, GFP_KERNEL);
1550
1551                         if (table == NULL)
1552                                 return -ENOMEM;
1553
1554                         table->count = (unsigned long)ptable->ucNumEntries;
1555
1556                         for (i = 0; i < table->count; i++) {
1557                                 table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1558                                 table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1559                                                         | le16_to_cpu(ptable->entries[i].usSclkLow);
1560                                 table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1561                                                         | le16_to_cpu(ptable->entries[i].usMclkLow);
1562                         }
1563                         hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1564                 }
1565         }
1566
1567         return 0;
1568 }
1569
1570 static int get_number_of_vce_state_table_entries(
1571                                                   struct pp_hwmgr *hwmgr)
1572 {
1573         const ATOM_PPLIB_POWERPLAYTABLE *table =
1574                                              get_powerplay_table(hwmgr);
1575         const ATOM_PPLIB_VCE_State_Table *vce_table =
1576                                     get_vce_state_table(hwmgr, table);
1577
1578         if (vce_table)
1579                 return vce_table->numEntries;
1580
1581         return 0;
1582 }
1583
1584 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1585                                                         unsigned long i,
1586                                                         struct amd_vce_state *vce_state,
1587                                                         void **clock_info,
1588                                                         unsigned long *flag)
1589 {
1590         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1591
1592         const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1593
1594         unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1595
1596         const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1597
1598         const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset);
1599
1600         const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1601
1602         const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1603
1604         unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1605
1606         *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1607
1608         vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow;
1609         vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow;
1610
1611         *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1612
1613         return 0;
1614 }
1615
1616
1617 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1618 {
1619         int result;
1620         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1621
1622         if (hwmgr->chip_id == CHIP_RAVEN)
1623                 return 0;
1624
1625         hwmgr->need_pp_table_upload = true;
1626
1627         powerplay_table = get_powerplay_table(hwmgr);
1628
1629         result = init_powerplay_tables(hwmgr, powerplay_table);
1630
1631         PP_ASSERT_WITH_CODE((result == 0),
1632                             "init_powerplay_tables failed", return result);
1633
1634         result = set_platform_caps(hwmgr,
1635                                 le32_to_cpu(powerplay_table->ulPlatformCaps));
1636
1637         PP_ASSERT_WITH_CODE((result == 0),
1638                             "set_platform_caps failed", return result);
1639
1640         result = init_thermal_controller(hwmgr, powerplay_table);
1641
1642         PP_ASSERT_WITH_CODE((result == 0),
1643                             "init_thermal_controller failed", return result);
1644
1645         result = init_overdrive_limits(hwmgr, powerplay_table);
1646
1647         PP_ASSERT_WITH_CODE((result == 0),
1648                             "init_overdrive_limits failed", return result);
1649
1650         result = init_clock_voltage_dependency(hwmgr,
1651                                                powerplay_table);
1652
1653         PP_ASSERT_WITH_CODE((result == 0),
1654                             "init_clock_voltage_dependency failed", return result);
1655
1656         result = init_dpm2_parameters(hwmgr, powerplay_table);
1657
1658         PP_ASSERT_WITH_CODE((result == 0),
1659                             "init_dpm2_parameters failed", return result);
1660
1661         result = init_phase_shedding_table(hwmgr, powerplay_table);
1662
1663         PP_ASSERT_WITH_CODE((result == 0),
1664                             "init_phase_shedding_table failed", return result);
1665
1666         return result;
1667 }
1668
1669 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1670 {
1671         if (hwmgr->chip_id == CHIP_RAVEN)
1672                 return 0;
1673
1674         kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1675         hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1676
1677         kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1678         hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1679
1680         kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1681         hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1682
1683         kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1684         hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1685
1686         kfree(hwmgr->dyn_state.valid_mclk_values);
1687         hwmgr->dyn_state.valid_mclk_values = NULL;
1688
1689         kfree(hwmgr->dyn_state.valid_sclk_values);
1690         hwmgr->dyn_state.valid_sclk_values = NULL;
1691
1692         kfree(hwmgr->dyn_state.cac_leakage_table);
1693         hwmgr->dyn_state.cac_leakage_table = NULL;
1694
1695         kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1696         hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1697
1698         kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1699         hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1700
1701         kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1702         hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1703
1704         kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1705         hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1706
1707         kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1708         hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1709
1710         kfree(hwmgr->dyn_state.cac_dtp_table);
1711         hwmgr->dyn_state.cac_dtp_table = NULL;
1712
1713         kfree(hwmgr->dyn_state.ppm_parameter_table);
1714         hwmgr->dyn_state.ppm_parameter_table = NULL;
1715
1716         kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1717         hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1718
1719         return 0;
1720 }
1721
1722 const struct pp_table_func pptable_funcs = {
1723         .pptable_init = pp_tables_initialize,
1724         .pptable_fini = pp_tables_uninitialize,
1725         .pptable_get_number_of_vce_state_table_entries =
1726                                 get_number_of_vce_state_table_entries,
1727         .pptable_get_vce_state_table_entry =
1728                                                 get_vce_state_table_entry,
1729 };
1730