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