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