GNU Linux-libre 4.14.324-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
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
794 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
795                                      struct pp_hwmgr *hwmgr)
796 {
797         const void *table_addr = hwmgr->soft_pp_table;
798         uint8_t frev, crev;
799         uint16_t size;
800
801         if (!table_addr) {
802                 table_addr = cgs_atom_get_data_table(hwmgr->device,
803                                 GetIndexIntoMasterTable(DATA, PowerPlayInfo),
804                                 &size, &frev, &crev);
805
806                 hwmgr->soft_pp_table = table_addr;
807                 hwmgr->soft_pp_table_size = size;
808         }
809
810         return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
811 }
812
813 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
814                                 uint32_t *vol_rep_time, uint32_t *bb_rep_time)
815 {
816         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
817
818         PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
819                             "Missing PowerPlay Table!", return -EINVAL);
820
821         *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
822         *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
823
824         return 0;
825 }
826
827 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
828                                      unsigned long *num_of_entries)
829 {
830         const StateArray *pstate_arrays;
831         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
832
833         if (powerplay_table == NULL)
834                 return -1;
835
836         if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
837                 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
838                                         le16_to_cpu(powerplay_table->usStateArrayOffset));
839
840                 *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
841         } else
842                 *num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
843
844         return 0;
845 }
846
847 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
848                                 unsigned long entry_index,
849                                 struct pp_power_state *ps,
850                          pp_tables_hw_clock_info_callback func)
851 {
852         int i;
853         const StateArray *pstate_arrays;
854         const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
855         const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
856         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
857         int result = 0;
858         int res = 0;
859
860         const ClockInfoArray *pclock_arrays;
861
862         const NonClockInfoArray *pnon_clock_arrays;
863
864         const ATOM_PPLIB_STATE *pstate_entry;
865
866         if (powerplay_table == NULL)
867                 return -1;
868
869         ps->classification.bios_index = entry_index;
870
871         if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
872                 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
873                                         le16_to_cpu(powerplay_table->usStateArrayOffset));
874
875                 if (entry_index > pstate_arrays->ucNumEntries)
876                         return -1;
877
878                 pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
879                 pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
880                                         le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
881
882                 pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
883                                                 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
884
885                 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
886                                         (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
887
888                 result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
889
890                 for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
891                         const void *pclock_info = (const void *)(
892                                                         (unsigned long)(pclock_arrays->clockInfo) +
893                                                         (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
894                         res = func(hwmgr, &ps->hardware, i, pclock_info);
895                         if ((0 == result) && (0 != res))
896                                 result = res;
897                 }
898         } else {
899                 if (entry_index > powerplay_table->ucNumStates)
900                         return -1;
901
902                 pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + powerplay_table->usStateArrayOffset +
903                                 entry_index * powerplay_table->ucStateEntrySize);
904
905                 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
906                                                 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
907                                                 pstate_entry->ucNonClockStateIndex *
908                                                 powerplay_table->ucNonClockSize);
909
910                 result = init_non_clock_fields(hwmgr, ps,
911                                                         powerplay_table->ucNonClockSize,
912                                                         pnon_clock_info);
913
914                 for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
915                         const void *pclock_info = (const void *)((unsigned long)powerplay_table +
916                                                 le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
917                                                 pstate_entry->ucClockStateIndices[i] *
918                                                 powerplay_table->ucClockInfoSize);
919
920                         int res = func(hwmgr, &ps->hardware, i, pclock_info);
921
922                         if ((0 == result) && (0 != res))
923                                         result = res;
924                 }
925         }
926
927         if ((0 == result) &&
928                 (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot)))
929                 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
930
931         return result;
932 }
933
934
935
936 static int init_powerplay_tables(
937                         struct pp_hwmgr *hwmgr,
938                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
939 )
940 {
941         return 0;
942 }
943
944
945 static int init_thermal_controller(
946                         struct pp_hwmgr *hwmgr,
947                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
948 {
949         return 0;
950 }
951
952 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
953                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
954                         const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
955 {
956         hwmgr->platform_descriptor.overdriveLimit.engineClock =
957                                 le32_to_cpu(fw_info->ulASICMaxEngineClock);
958
959         hwmgr->platform_descriptor.overdriveLimit.memoryClock =
960                                 le32_to_cpu(fw_info->ulASICMaxMemoryClock);
961
962         hwmgr->platform_descriptor.maxOverdriveVDDC =
963                 le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
964
965         hwmgr->platform_descriptor.minOverdriveVDDC =
966                            le16_to_cpu(fw_info->usBootUpVDDCVoltage);
967
968         hwmgr->platform_descriptor.maxOverdriveVDDC =
969                            le16_to_cpu(fw_info->usBootUpVDDCVoltage);
970
971         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
972         return 0;
973 }
974
975 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
976                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
977                         const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
978 {
979         const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
980         const ATOM_PPLIB_EXTENDEDHEADER *header;
981
982         if (le16_to_cpu(powerplay_table->usTableSize) <
983             sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
984                 return 0;
985
986         powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
987
988         if (0 == powerplay_table3->usExtendendedHeaderOffset)
989                 return 0;
990
991         header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
992                         le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
993
994         hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
995         hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
996
997
998         hwmgr->platform_descriptor.minOverdriveVDDC = 0;
999         hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1000         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1001
1002         return 0;
1003 }
1004
1005 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1006                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1007 {
1008         int result;
1009         uint8_t frev, crev;
1010         uint16_t size;
1011
1012         const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1013
1014         hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1015         hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1016         hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1017         hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1018         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1019
1020         if (hwmgr->chip_id == CHIP_RAVEN)
1021                 return 0;
1022
1023         /* We assume here that fw_info is unchanged if this call fails.*/
1024         fw_info = cgs_atom_get_data_table(hwmgr->device,
1025                          GetIndexIntoMasterTable(DATA, FirmwareInfo),
1026                          &size, &frev, &crev);
1027
1028         if ((fw_info->ucTableFormatRevision == 1)
1029                 && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1030                 result = init_overdrive_limits_V1_4(hwmgr,
1031                                 powerplay_table,
1032                                 (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1033
1034         else if ((fw_info->ucTableFormatRevision == 2)
1035                 && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1036                 result = init_overdrive_limits_V2_1(hwmgr,
1037                                 powerplay_table,
1038                                 (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1039
1040         if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0
1041                 && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0
1042                 && !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1043                         PHM_PlatformCaps_OverdriveDisabledByPowerBudget))
1044                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1045                                 PHM_PlatformCaps_ACOverdriveSupport);
1046
1047         return result;
1048 }
1049
1050 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1051                 struct phm_uvd_clock_voltage_dependency_table **ptable,
1052                 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1053                 const UVDClockInfoArray *array)
1054 {
1055         unsigned long table_size, i;
1056         struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1057
1058         table_size = sizeof(unsigned long) +
1059                  sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1060                  table->numEntries;
1061
1062         uvd_table = kzalloc(table_size, GFP_KERNEL);
1063         if (NULL == uvd_table)
1064                 return -ENOMEM;
1065
1066         uvd_table->count = table->numEntries;
1067
1068         for (i = 0; i < table->numEntries; i++) {
1069                 const UVDClockInfo *entry =
1070                         &array->entries[table->entries[i].ucUVDClockInfoIndex];
1071                 uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1072                 uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1073                                          | le16_to_cpu(entry->usVClkLow);
1074                 uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1075                                          | le16_to_cpu(entry->usDClkLow);
1076         }
1077
1078         *ptable = uvd_table;
1079
1080         return 0;
1081 }
1082
1083 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1084                 struct phm_vce_clock_voltage_dependency_table **ptable,
1085                 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1086                 const VCEClockInfoArray    *array)
1087 {
1088         unsigned long table_size, i;
1089         struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1090
1091         table_size = sizeof(unsigned long) +
1092                         sizeof(struct phm_vce_clock_voltage_dependency_table)
1093                         * table->numEntries;
1094
1095         vce_table = kzalloc(table_size, GFP_KERNEL);
1096         if (NULL == vce_table)
1097                 return -ENOMEM;
1098
1099         vce_table->count = table->numEntries;
1100         for (i = 0; i < table->numEntries; i++) {
1101                 const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1102
1103                 vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1104                 vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1105                                         | le16_to_cpu(entry->usEVClkLow);
1106                 vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1107                                         | le16_to_cpu(entry->usECClkLow);
1108         }
1109
1110         *ptable = vce_table;
1111
1112         return 0;
1113 }
1114
1115 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1116                  struct phm_samu_clock_voltage_dependency_table **ptable,
1117                  const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1118 {
1119         unsigned long table_size, i;
1120         struct phm_samu_clock_voltage_dependency_table *samu_table;
1121
1122         table_size = sizeof(unsigned long) +
1123                 sizeof(struct phm_samu_clock_voltage_dependency_table) *
1124                 table->numEntries;
1125
1126         samu_table = kzalloc(table_size, GFP_KERNEL);
1127         if (NULL == samu_table)
1128                 return -ENOMEM;
1129
1130         samu_table->count = table->numEntries;
1131
1132         for (i = 0; i < table->numEntries; i++) {
1133                 samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1134                 samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1135                                          | le16_to_cpu(table->entries[i].usSAMClockLow);
1136         }
1137
1138         *ptable = samu_table;
1139
1140         return 0;
1141 }
1142
1143 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1144                 struct phm_acp_clock_voltage_dependency_table **ptable,
1145                 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1146 {
1147         unsigned table_size, i;
1148         struct phm_acp_clock_voltage_dependency_table *acp_table;
1149
1150         table_size = sizeof(unsigned long) +
1151                 sizeof(struct phm_acp_clock_voltage_dependency_table) *
1152                 table->numEntries;
1153
1154         acp_table = kzalloc(table_size, GFP_KERNEL);
1155         if (NULL == acp_table)
1156                 return -ENOMEM;
1157
1158         acp_table->count = (unsigned long)table->numEntries;
1159
1160         for (i = 0; i < table->numEntries; i++) {
1161                 acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1162                 acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1163                                          | le16_to_cpu(table->entries[i].usACPClockLow);
1164         }
1165
1166         *ptable = acp_table;
1167
1168         return 0;
1169 }
1170
1171 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1172                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1173 {
1174         ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1175         ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1176         int result = 0;
1177
1178         uint16_t vce_clock_info_array_offset;
1179         uint16_t uvd_clock_info_array_offset;
1180         uint16_t table_offset;
1181
1182         hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1183         hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1184         hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1185         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1186         hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1187         hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1188         hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1189         hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1190         hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1191         hwmgr->dyn_state.ppm_parameter_table = NULL;
1192         hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1193
1194         vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1195                                                 hwmgr, powerplay_table);
1196         table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1197                                                 powerplay_table);
1198         if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1199                 const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1200                                 (((unsigned long) powerplay_table) +
1201                                 vce_clock_info_array_offset);
1202                 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1203                                 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1204                                 (((unsigned long) powerplay_table) + table_offset);
1205                 result = get_vce_clock_voltage_limit_table(hwmgr,
1206                                 &hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1207                                 table, array);
1208         }
1209
1210         uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1211         table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1212
1213         if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1214                 const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1215                                 (((unsigned long) powerplay_table) +
1216                                 uvd_clock_info_array_offset);
1217                 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1218                                 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1219                                 (((unsigned long) powerplay_table) + table_offset);
1220                 result = get_uvd_clock_voltage_limit_table(hwmgr,
1221                                 &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1222         }
1223
1224         table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1225                                                             powerplay_table);
1226
1227         if (table_offset > 0) {
1228                 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1229                                 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1230                                 (((unsigned long) powerplay_table) + table_offset);
1231                 result = get_samu_clock_voltage_limit_table(hwmgr,
1232                                 &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1233         }
1234
1235         table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1236                                                              powerplay_table);
1237
1238         if (table_offset > 0) {
1239                 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1240                                 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1241                                 (((unsigned long) powerplay_table) + table_offset);
1242                 result = get_acp_clock_voltage_limit_table(hwmgr,
1243                                 &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1244         }
1245
1246         table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1247         if (table_offset > 0) {
1248                 UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1249
1250                 if (rev_id > 0) {
1251                         const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1252                                 (const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1253                                 (((unsigned long) powerplay_table) + table_offset);
1254                         result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1255                                 &tune_table->power_tune_table,
1256                                 le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1257                         hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1258                                 le16_to_cpu(tune_table->usTjMax);
1259                 } else {
1260                         const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1261                                 (const ATOM_PPLIB_POWERTUNE_Table *)
1262                                 (((unsigned long) powerplay_table) + table_offset);
1263                         result = get_cac_tdp_table(hwmgr,
1264                                 &hwmgr->dyn_state.cac_dtp_table,
1265                                 &tune_table->power_tune_table, 255);
1266                 }
1267         }
1268
1269         if (le16_to_cpu(powerplay_table->usTableSize) >=
1270                 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1271                 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1272                                 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1273                 if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1274                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1275                                 (((unsigned long) powerplay_table4) +
1276                                 powerplay_table4->usVddcDependencyOnSCLKOffset);
1277                         result = get_clock_voltage_dependency_table(hwmgr,
1278                                 &hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1279                 }
1280
1281                 if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1282                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1283                                 (((unsigned long) powerplay_table4) +
1284                                 powerplay_table4->usVddciDependencyOnMCLKOffset);
1285                         result = get_clock_voltage_dependency_table(hwmgr,
1286                                 &hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1287                 }
1288
1289                 if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1290                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1291                                 (((unsigned long) powerplay_table4) +
1292                                 powerplay_table4->usVddcDependencyOnMCLKOffset);
1293                         result = get_clock_voltage_dependency_table(hwmgr,
1294                                 &hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1295                 }
1296
1297                 if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1298                         limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1299                                 (((unsigned long) powerplay_table4) +
1300                                 powerplay_table4->usMaxClockVoltageOnDCOffset);
1301                         result = get_clock_voltage_limit(hwmgr,
1302                                 &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1303                 }
1304
1305                 if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1306                         (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1307                         result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1308                                         hwmgr->dyn_state.vddc_dependency_on_mclk);
1309
1310                 if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1311                         (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1312                         result = get_valid_clk(hwmgr,
1313                                 &hwmgr->dyn_state.valid_sclk_values,
1314                                 hwmgr->dyn_state.vddc_dependency_on_sclk);
1315
1316                 if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1317                         table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1318                                 (((unsigned long) powerplay_table4) +
1319                                 powerplay_table4->usMvddDependencyOnMCLKOffset);
1320                         result = get_clock_voltage_dependency_table(hwmgr,
1321                                 &hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1322                 }
1323         }
1324
1325         table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1326                                                                 powerplay_table);
1327
1328         if (table_offset > 0) {
1329                 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1330                         (((unsigned long) powerplay_table) + table_offset);
1331                 result = get_clock_voltage_dependency_table(hwmgr,
1332                         &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1333         }
1334
1335         return result;
1336 }
1337
1338 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1339                                  struct phm_cac_leakage_table **ptable,
1340                                 const ATOM_PPLIB_CAC_Leakage_Table *table)
1341 {
1342         struct phm_cac_leakage_table  *cac_leakage_table;
1343         unsigned long            table_size, i;
1344
1345         if (hwmgr == NULL || table == NULL || ptable == NULL)
1346                 return -EINVAL;
1347
1348         table_size = sizeof(ULONG) +
1349                 (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1350
1351         cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1352
1353         if (cac_leakage_table == NULL)
1354                 return -ENOMEM;
1355
1356         cac_leakage_table->count = (ULONG)table->ucNumEntries;
1357
1358         for (i = 0; i < cac_leakage_table->count; i++) {
1359                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1360                                 PHM_PlatformCaps_EVV)) {
1361                         cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1362                         cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1363                         cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1364                 } else {
1365                         cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1366                         cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1367                 }
1368         }
1369
1370         *ptable = cac_leakage_table;
1371
1372         return 0;
1373 }
1374
1375 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1376                         ATOM_PPLIB_PPM_Table *atom_ppm_table)
1377 {
1378         struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1379
1380         if (NULL == ptr)
1381                 return -ENOMEM;
1382
1383         ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1384         ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1385         ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1386         ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1387         ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1388         ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1389         ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1390         ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1391         ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1392         ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1393         hwmgr->dyn_state.ppm_parameter_table = ptr;
1394
1395         return 0;
1396 }
1397
1398 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1399                         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1400 {
1401         int result = 0;
1402
1403         if (le16_to_cpu(powerplay_table->usTableSize) >=
1404             sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1405                 const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1406                                 (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1407                 const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1408                                 (const ATOM_PPLIB_POWERPLAYTABLE4 *)
1409                                 (&ptable5->basicTable4);
1410                 const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1411                                 (const ATOM_PPLIB_POWERPLAYTABLE3 *)
1412                                 (&ptable4->basicTable3);
1413                 const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1414                 uint16_t table_offset;
1415                 ATOM_PPLIB_PPM_Table *atom_ppm_table;
1416
1417                 hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1418                 hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1419
1420                 hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1421                 hwmgr->platform_descriptor.TDPAdjustment = 0;
1422
1423                 hwmgr->platform_descriptor.VidAdjustment = 0;
1424                 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1425                 hwmgr->platform_descriptor.VidMinLimit     = 0;
1426                 hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1427                 hwmgr->platform_descriptor.VidStep         = 6250;
1428
1429                 hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1430
1431                 if (hwmgr->platform_descriptor.TDPODLimit != 0)
1432                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1433                                         PHM_PlatformCaps_PowerControl);
1434
1435                 hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1436
1437                 hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1438
1439                 hwmgr->dyn_state.cac_leakage_table = NULL;
1440
1441                 if (0 != ptable5->usCACLeakageTableOffset) {
1442                         const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1443                                 (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1444                                 le16_to_cpu(ptable5->usCACLeakageTableOffset));
1445                         result = get_cac_leakage_table(hwmgr,
1446                                 &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1447                 }
1448
1449                 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1450
1451                 hwmgr->dyn_state.ppm_parameter_table = NULL;
1452
1453                 if (0 != ptable3->usExtendendedHeaderOffset) {
1454                         extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1455                                         (((unsigned long)powerplay_table) +
1456                                         le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1457                         if ((extended_header->usPPMTableOffset > 0) &&
1458                                 le16_to_cpu(extended_header->usSize) >=
1459                                     SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1460                                 table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1461                                 atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1462                                         (((unsigned long)powerplay_table) + table_offset);
1463                                 if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1464                                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1465                                                 PHM_PlatformCaps_EnablePlatformPowerManagement);
1466                         }
1467                 }
1468         }
1469         return result;
1470 }
1471
1472 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1473                 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1474 {
1475         if (le16_to_cpu(powerplay_table->usTableSize) >=
1476             sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1477                 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1478                                 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1479
1480                 if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1481                         const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1482                                 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
1483                                 (((unsigned long)powerplay_table4) +
1484                                 le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1485                         struct phm_phase_shedding_limits_table *table;
1486                         unsigned long size, i;
1487
1488
1489                         size = sizeof(unsigned long) +
1490                                 (sizeof(struct phm_phase_shedding_limits_table) *
1491                                 ptable->ucNumEntries);
1492
1493                         table = kzalloc(size, GFP_KERNEL);
1494
1495                         if (table == NULL)
1496                                 return -ENOMEM;
1497
1498                         table->count = (unsigned long)ptable->ucNumEntries;
1499
1500                         for (i = 0; i < table->count; i++) {
1501                                 table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1502                                 table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1503                                                         | le16_to_cpu(ptable->entries[i].usSclkLow);
1504                                 table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1505                                                         | le16_to_cpu(ptable->entries[i].usMclkLow);
1506                         }
1507                         hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1508                 }
1509         }
1510
1511         return 0;
1512 }
1513
1514 static int get_number_of_vce_state_table_entries(
1515                                                   struct pp_hwmgr *hwmgr)
1516 {
1517         const ATOM_PPLIB_POWERPLAYTABLE *table =
1518                                              get_powerplay_table(hwmgr);
1519         const ATOM_PPLIB_VCE_State_Table *vce_table =
1520                                     get_vce_state_table(hwmgr, table);
1521
1522         if (vce_table)
1523                 return vce_table->numEntries;
1524
1525         return 0;
1526 }
1527
1528 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1529                                                         unsigned long i,
1530                                                         struct amd_vce_state *vce_state,
1531                                                         void **clock_info,
1532                                                         unsigned long *flag)
1533 {
1534         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1535
1536         const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1537
1538         unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1539
1540         const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1541
1542         const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset);
1543
1544         const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1545
1546         const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1547
1548         unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1549
1550         *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1551
1552         vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow;
1553         vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow;
1554
1555         *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1556
1557         return 0;
1558 }
1559
1560
1561 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1562 {
1563         int result;
1564         const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1565
1566         if (hwmgr->chip_id == CHIP_RAVEN)
1567                 return 0;
1568
1569         hwmgr->need_pp_table_upload = true;
1570
1571         powerplay_table = get_powerplay_table(hwmgr);
1572
1573         result = init_powerplay_tables(hwmgr, powerplay_table);
1574
1575         PP_ASSERT_WITH_CODE((result == 0),
1576                             "init_powerplay_tables failed", return result);
1577
1578         result = set_platform_caps(hwmgr,
1579                                 le32_to_cpu(powerplay_table->ulPlatformCaps));
1580
1581         PP_ASSERT_WITH_CODE((result == 0),
1582                             "set_platform_caps failed", return result);
1583
1584         result = init_thermal_controller(hwmgr, powerplay_table);
1585
1586         PP_ASSERT_WITH_CODE((result == 0),
1587                             "init_thermal_controller failed", return result);
1588
1589         result = init_overdrive_limits(hwmgr, powerplay_table);
1590
1591         PP_ASSERT_WITH_CODE((result == 0),
1592                             "init_overdrive_limits failed", return result);
1593
1594         result = init_clock_voltage_dependency(hwmgr,
1595                                                powerplay_table);
1596
1597         PP_ASSERT_WITH_CODE((result == 0),
1598                             "init_clock_voltage_dependency failed", return result);
1599
1600         result = init_dpm2_parameters(hwmgr, powerplay_table);
1601
1602         PP_ASSERT_WITH_CODE((result == 0),
1603                             "init_dpm2_parameters failed", return result);
1604
1605         result = init_phase_shedding_table(hwmgr, powerplay_table);
1606
1607         PP_ASSERT_WITH_CODE((result == 0),
1608                             "init_phase_shedding_table failed", return result);
1609
1610         return result;
1611 }
1612
1613 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1614 {
1615         if (hwmgr->chip_id == CHIP_RAVEN)
1616                 return 0;
1617
1618         if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) {
1619                 kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1620                 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1621         }
1622
1623         if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) {
1624                 kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1625                 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1626         }
1627
1628         if (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) {
1629                 kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1630                 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1631         }
1632
1633         if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) {
1634                 kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1635                 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1636         }
1637
1638         if (NULL != hwmgr->dyn_state.valid_mclk_values) {
1639                 kfree(hwmgr->dyn_state.valid_mclk_values);
1640                 hwmgr->dyn_state.valid_mclk_values = NULL;
1641         }
1642
1643         if (NULL != hwmgr->dyn_state.valid_sclk_values) {
1644                 kfree(hwmgr->dyn_state.valid_sclk_values);
1645                 hwmgr->dyn_state.valid_sclk_values = NULL;
1646         }
1647
1648         if (NULL != hwmgr->dyn_state.cac_leakage_table) {
1649                 kfree(hwmgr->dyn_state.cac_leakage_table);
1650                 hwmgr->dyn_state.cac_leakage_table = NULL;
1651         }
1652
1653         if (NULL != hwmgr->dyn_state.vddc_phase_shed_limits_table) {
1654                 kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1655                 hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1656         }
1657
1658         if (NULL != hwmgr->dyn_state.vce_clock_voltage_dependency_table) {
1659                 kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1660                 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1661         }
1662
1663         if (NULL != hwmgr->dyn_state.uvd_clock_voltage_dependency_table) {
1664                 kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1665                 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1666         }
1667
1668         if (NULL != hwmgr->dyn_state.samu_clock_voltage_dependency_table) {
1669                 kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1670                 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1671         }
1672
1673         if (NULL != hwmgr->dyn_state.acp_clock_voltage_dependency_table) {
1674                 kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1675                 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1676         }
1677
1678         if (NULL != hwmgr->dyn_state.cac_dtp_table) {
1679                 kfree(hwmgr->dyn_state.cac_dtp_table);
1680                 hwmgr->dyn_state.cac_dtp_table = NULL;
1681         }
1682
1683         if (NULL != hwmgr->dyn_state.ppm_parameter_table) {
1684                 kfree(hwmgr->dyn_state.ppm_parameter_table);
1685                 hwmgr->dyn_state.ppm_parameter_table = NULL;
1686         }
1687
1688         if (NULL != hwmgr->dyn_state.vdd_gfx_dependency_on_sclk) {
1689                 kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1690                 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1691         }
1692
1693         if (NULL != hwmgr->dyn_state.vq_budgeting_table) {
1694                 kfree(hwmgr->dyn_state.vq_budgeting_table);
1695                 hwmgr->dyn_state.vq_budgeting_table = NULL;
1696         }
1697
1698         return 0;
1699 }
1700
1701 const struct pp_table_func pptable_funcs = {
1702         .pptable_init = pp_tables_initialize,
1703         .pptable_fini = pp_tables_uninitialize,
1704         .pptable_get_number_of_vce_state_table_entries =
1705                                 get_number_of_vce_state_table_entries,
1706         .pptable_get_vce_state_table_entry =
1707                                                 get_vce_state_table_entry,
1708 };
1709