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