drm/ttm: remove cpu_address member from ttm_tt
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / hwmgr / process_pptables_v1_0.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/module.h>
24 #include <linux/slab.h>
25 #include <linux/fb.h>
26
27 #include "process_pptables_v1_0.h"
28 #include "ppatomctrl.h"
29 #include "atombios.h"
30 #include "pp_debug.h"
31 #include "hwmgr.h"
32 #include "cgs_common.h"
33 #include "pptable_v1_0.h"
34
35 /**
36  * Private Function used during initialization.
37  * @param hwmgr Pointer to the hardware manager.
38  * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE).
39  * @param cap Which capability to set/reset.
40  */
41 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap)
42 {
43         if (setIt)
44                 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
45         else
46                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
47 }
48
49
50 /**
51  * Private Function used during initialization.
52  * @param hwmgr Pointer to the hardware manager.
53  * @param powerplay_caps the bit array (from BIOS) of capability bits.
54  * @exception the current implementation always returns 1.
55  */
56 static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
57 {
58         PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____),
59                 "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue);
60         PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____),
61                 "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue);
62         PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____),
63                 "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue);
64         PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____),
65                 "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue);
66         PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____),
67                 "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue);
68
69         set_hw_cap(
70                         hwmgr,
71                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY),
72                         PHM_PlatformCaps_PowerPlaySupport
73                   );
74
75         set_hw_cap(
76                         hwmgr,
77                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
78                         PHM_PlatformCaps_BiosPowerSourceControl
79                   );
80
81         set_hw_cap(
82                         hwmgr,
83                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC),
84                         PHM_PlatformCaps_AutomaticDCTransition
85                   );
86
87         set_hw_cap(
88                         hwmgr,
89                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL),
90                         PHM_PlatformCaps_EnableMVDDControl
91                   );
92
93         set_hw_cap(
94                         hwmgr,
95                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL),
96                         PHM_PlatformCaps_ControlVDDCI
97                   );
98
99         set_hw_cap(
100                         hwmgr,
101                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL),
102                         PHM_PlatformCaps_ControlVDDGFX
103                   );
104
105         set_hw_cap(
106                         hwmgr,
107                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO),
108                         PHM_PlatformCaps_BACO
109                   );
110
111         set_hw_cap(
112                         hwmgr,
113                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND),
114                         PHM_PlatformCaps_DisableVoltageIsland
115                   );
116
117         set_hw_cap(
118                         hwmgr,
119                         0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
120                         PHM_PlatformCaps_CombinePCCWithThermalSignal
121                   );
122
123         set_hw_cap(
124                         hwmgr,
125                         0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
126                         PHM_PlatformCaps_LoadPostProductionFirmware
127                   );
128
129         return 0;
130 }
131
132 /**
133  * Private Function to get the PowerPlay Table Address.
134  */
135 const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
136 {
137         int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
138
139         u16 size;
140         u8 frev, crev;
141         void *table_address = (void *)hwmgr->soft_pp_table;
142
143         if (!table_address) {
144                 table_address = (ATOM_Tonga_POWERPLAYTABLE *)
145                                 cgs_atom_get_data_table(hwmgr->device,
146                                                 index, &size, &frev, &crev);
147                 hwmgr->soft_pp_table = table_address;   /*Cache the result in RAM.*/
148                 hwmgr->soft_pp_table_size = size;
149         }
150
151         return table_address;
152 }
153
154 static int get_vddc_lookup_table(
155                 struct pp_hwmgr *hwmgr,
156                 phm_ppt_v1_voltage_lookup_table **lookup_table,
157                 const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables,
158                 uint32_t max_levels
159                 )
160 {
161         uint32_t table_size, i;
162         phm_ppt_v1_voltage_lookup_table *table;
163         phm_ppt_v1_voltage_lookup_record *record;
164         ATOM_Tonga_Voltage_Lookup_Record *atom_record;
165
166         PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries),
167                 "Invalid CAC Leakage PowerPlay Table!", return 1);
168
169         table_size = sizeof(uint32_t) +
170                 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels;
171
172         table = kzalloc(table_size, GFP_KERNEL);
173
174         if (NULL == table)
175                 return -ENOMEM;
176
177         memset(table, 0x00, table_size);
178
179         table->count = vddc_lookup_pp_tables->ucNumEntries;
180
181         for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) {
182                 record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
183                                         phm_ppt_v1_voltage_lookup_record,
184                                         entries, table, i);
185                 atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
186                                         ATOM_Tonga_Voltage_Lookup_Record,
187                                         entries, vddc_lookup_pp_tables, i);
188                 record->us_calculated = 0;
189                 record->us_vdd = atom_record->usVdd;
190                 record->us_cac_low = atom_record->usCACLow;
191                 record->us_cac_mid = atom_record->usCACMid;
192                 record->us_cac_high = atom_record->usCACHigh;
193         }
194
195         *lookup_table = table;
196
197         return 0;
198 }
199
200 /**
201  * Private Function used during initialization.
202  * Initialize Platform Power Management Parameter table
203  * @param hwmgr Pointer to the hardware manager.
204  * @param atom_ppm_table Pointer to PPM table in VBIOS
205  */
206 static int get_platform_power_management_table(
207                 struct pp_hwmgr *hwmgr,
208                 ATOM_Tonga_PPM_Table *atom_ppm_table)
209 {
210         struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL);
211         struct phm_ppt_v1_information *pp_table_information =
212                 (struct phm_ppt_v1_information *)(hwmgr->pptable);
213
214         if (NULL == ptr)
215                 return -ENOMEM;
216
217         ptr->ppm_design
218                 = atom_ppm_table->ucPpmDesign;
219         ptr->cpu_core_number
220                 = atom_ppm_table->usCpuCoreNumber;
221         ptr->platform_tdp
222                 = atom_ppm_table->ulPlatformTDP;
223         ptr->small_ac_platform_tdp
224                 = atom_ppm_table->ulSmallACPlatformTDP;
225         ptr->platform_tdc
226                 = atom_ppm_table->ulPlatformTDC;
227         ptr->small_ac_platform_tdc
228                 = atom_ppm_table->ulSmallACPlatformTDC;
229         ptr->apu_tdp
230                 = atom_ppm_table->ulApuTDP;
231         ptr->dgpu_tdp
232                 = atom_ppm_table->ulDGpuTDP;
233         ptr->dgpu_ulv_power
234                 = atom_ppm_table->ulDGpuUlvPower;
235         ptr->tj_max
236                 = atom_ppm_table->ulTjmax;
237
238         pp_table_information->ppm_parameter_table = ptr;
239
240         return 0;
241 }
242
243 /**
244  * Private Function used during initialization.
245  * Initialize TDP limits for DPM2
246  * @param hwmgr Pointer to the hardware manager.
247  * @param powerplay_table Pointer to the PowerPlay Table.
248  */
249 static int init_dpm_2_parameters(
250                 struct pp_hwmgr *hwmgr,
251                 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
252                 )
253 {
254         int result = 0;
255         struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
256         ATOM_Tonga_PPM_Table *atom_ppm_table;
257         uint32_t disable_ppm = 0;
258         uint32_t disable_power_control = 0;
259
260         pp_table_information->us_ulv_voltage_offset =
261                 le16_to_cpu(powerplay_table->usUlvVoltageOffset);
262
263         pp_table_information->ppm_parameter_table = NULL;
264         pp_table_information->vddc_lookup_table = NULL;
265         pp_table_information->vddgfx_lookup_table = NULL;
266         /* TDP limits */
267         hwmgr->platform_descriptor.TDPODLimit =
268                 le16_to_cpu(powerplay_table->usPowerControlLimit);
269         hwmgr->platform_descriptor.TDPAdjustment = 0;
270         hwmgr->platform_descriptor.VidAdjustment = 0;
271         hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
272         hwmgr->platform_descriptor.VidMinLimit = 0;
273         hwmgr->platform_descriptor.VidMaxLimit = 1500000;
274         hwmgr->platform_descriptor.VidStep = 6250;
275
276         disable_power_control = 0;
277         if (0 == disable_power_control) {
278                 /* enable TDP overdrive (PowerControl) feature as well if supported */
279                 if (hwmgr->platform_descriptor.TDPODLimit != 0)
280                         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
281                         PHM_PlatformCaps_PowerControl);
282         }
283
284         if (0 != powerplay_table->usVddcLookupTableOffset) {
285                 const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable =
286                         (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
287                         le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
288
289                 result = get_vddc_lookup_table(hwmgr,
290                         &pp_table_information->vddc_lookup_table, pVddcCACTable, 16);
291         }
292
293         if (0 != powerplay_table->usVddgfxLookupTableOffset) {
294                 const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable =
295                         (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
296                         le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset));
297
298                 result = get_vddc_lookup_table(hwmgr,
299                         &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16);
300         }
301
302         disable_ppm = 0;
303         if (0 == disable_ppm) {
304                 atom_ppm_table = (ATOM_Tonga_PPM_Table *)
305                         (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset));
306
307                 if (0 != powerplay_table->usPPMTableOffset) {
308                         if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) {
309                                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
310                                         PHM_PlatformCaps_EnablePlatformPowerManagement);
311                         }
312                 }
313         }
314
315         return result;
316 }
317
318 static int get_valid_clk(
319                 struct pp_hwmgr *hwmgr,
320                 struct phm_clock_array **clk_table,
321                 phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table
322                 )
323 {
324         uint32_t table_size, i;
325         struct phm_clock_array *table;
326         phm_ppt_v1_clock_voltage_dependency_record *dep_record;
327
328         PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count),
329                 "Invalid PowerPlay Table!", return -1);
330
331         table_size = sizeof(uint32_t) +
332                 sizeof(uint32_t) * clk_volt_pp_table->count;
333
334         table = kzalloc(table_size, GFP_KERNEL);
335
336         if (NULL == table)
337                 return -ENOMEM;
338
339         memset(table, 0x00, table_size);
340
341         table->count = (uint32_t)clk_volt_pp_table->count;
342
343         for (i = 0; i < table->count; i++) {
344                 dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
345                                 phm_ppt_v1_clock_voltage_dependency_record,
346                                 entries, clk_volt_pp_table, i);
347                 table->values[i] = (uint32_t)dep_record->clk;
348         }
349         *clk_table = table;
350
351         return 0;
352 }
353
354 static int get_hard_limits(
355                 struct pp_hwmgr *hwmgr,
356                 struct phm_clock_and_voltage_limits *limits,
357                 ATOM_Tonga_Hard_Limit_Table const *limitable
358                 )
359 {
360         PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1);
361
362         /* currently we always take entries[0] parameters */
363         limits->sclk = (uint32_t)limitable->entries[0].ulSCLKLimit;
364         limits->mclk = (uint32_t)limitable->entries[0].ulMCLKLimit;
365         limits->vddc = (uint16_t)limitable->entries[0].usVddcLimit;
366         limits->vddci = (uint16_t)limitable->entries[0].usVddciLimit;
367         limits->vddgfx = (uint16_t)limitable->entries[0].usVddgfxLimit;
368
369         return 0;
370 }
371
372 static int get_mclk_voltage_dependency_table(
373                 struct pp_hwmgr *hwmgr,
374                 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table,
375                 ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table
376                 )
377 {
378         uint32_t table_size, i;
379         phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
380         phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record;
381         ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
382
383         PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries),
384                 "Invalid PowerPlay Table!", return -1);
385
386         table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
387                 * mclk_dep_table->ucNumEntries;
388
389         mclk_table = kzalloc(table_size, GFP_KERNEL);
390
391         if (NULL == mclk_table)
392                 return -ENOMEM;
393
394         memset(mclk_table, 0x00, table_size);
395
396         mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
397
398         for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
399                 mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
400                                         phm_ppt_v1_clock_voltage_dependency_record,
401                                                 entries, mclk_table, i);
402                 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
403                                         ATOM_Tonga_MCLK_Dependency_Record,
404                                                 entries, mclk_dep_table, i);
405                 mclk_table_record->vddInd = mclk_dep_record->ucVddcInd;
406                 mclk_table_record->vdd_offset = mclk_dep_record->usVddgfxOffset;
407                 mclk_table_record->vddci = mclk_dep_record->usVddci;
408                 mclk_table_record->mvdd = mclk_dep_record->usMvdd;
409                 mclk_table_record->clk = mclk_dep_record->ulMclk;
410         }
411
412         *pp_tonga_mclk_dep_table = mclk_table;
413
414         return 0;
415 }
416
417 static int get_sclk_voltage_dependency_table(
418                 struct pp_hwmgr *hwmgr,
419                 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
420                 PPTable_Generic_SubTable_Header const  *sclk_dep_table
421                 )
422 {
423         uint32_t table_size, i;
424         phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
425         phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record;
426
427         if (sclk_dep_table->ucRevId < 1) {
428                 const ATOM_Tonga_SCLK_Dependency_Table *tonga_table =
429                             (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table;
430                 ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
431
432                 PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
433                         "Invalid PowerPlay Table!", return -1);
434
435                 table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
436                         * tonga_table->ucNumEntries;
437
438                 sclk_table = kzalloc(table_size, GFP_KERNEL);
439
440                 if (NULL == sclk_table)
441                         return -ENOMEM;
442
443                 memset(sclk_table, 0x00, table_size);
444
445                 sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
446
447                 for (i = 0; i < tonga_table->ucNumEntries; i++) {
448                         sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
449                                                 ATOM_Tonga_SCLK_Dependency_Record,
450                                                 entries, tonga_table, i);
451                         sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
452                                                 phm_ppt_v1_clock_voltage_dependency_record,
453                                                 entries, sclk_table, i);
454                         sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
455                         sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset;
456                         sclk_table_record->clk = sclk_dep_record->ulSclk;
457                         sclk_table_record->cks_enable =
458                                 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
459                         sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
460                 }
461         } else {
462                 const ATOM_Polaris_SCLK_Dependency_Table *polaris_table =
463                             (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table;
464                 ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record;
465
466                 PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
467                         "Invalid PowerPlay Table!", return -1);
468
469                 table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
470                         * polaris_table->ucNumEntries;
471
472                 sclk_table = kzalloc(table_size, GFP_KERNEL);
473
474                 if (NULL == sclk_table)
475                         return -ENOMEM;
476
477                 memset(sclk_table, 0x00, table_size);
478
479                 sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
480
481                 for (i = 0; i < polaris_table->ucNumEntries; i++) {
482                         sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
483                                                 ATOM_Polaris_SCLK_Dependency_Record,
484                                                 entries, polaris_table, i);
485                         sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
486                                                 phm_ppt_v1_clock_voltage_dependency_record,
487                                                 entries, sclk_table, i);
488                         sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
489                         sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset;
490                         sclk_table_record->clk = sclk_dep_record->ulSclk;
491                         sclk_table_record->cks_enable =
492                                 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
493                         sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
494                         sclk_table_record->sclk_offset = sclk_dep_record->ulSclkOffset;
495                 }
496         }
497         *pp_tonga_sclk_dep_table = sclk_table;
498
499         return 0;
500 }
501
502 static int get_pcie_table(
503                 struct pp_hwmgr *hwmgr,
504                 phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
505                 PPTable_Generic_SubTable_Header const *ptable
506                 )
507 {
508         uint32_t table_size, i, pcie_count;
509         phm_ppt_v1_pcie_table *pcie_table;
510         struct phm_ppt_v1_information *pp_table_information =
511                 (struct phm_ppt_v1_information *)(hwmgr->pptable);
512         phm_ppt_v1_pcie_record *pcie_record;
513
514         if (ptable->ucRevId < 1) {
515                 const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable;
516                 ATOM_Tonga_PCIE_Record *atom_pcie_record;
517
518                 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
519                         "Invalid PowerPlay Table!", return -1);
520
521                 table_size = sizeof(uint32_t) +
522                         sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
523
524                 pcie_table = kzalloc(table_size, GFP_KERNEL);
525
526                 if (pcie_table == NULL)
527                         return -ENOMEM;
528
529                 memset(pcie_table, 0x00, table_size);
530
531                 /*
532                 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
533                 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
534                 */
535                 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
536                 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
537                         pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
538                 else
539                         printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
540                         Disregarding the excess entries... \n");
541
542                 pcie_table->count = pcie_count;
543                 for (i = 0; i < pcie_count; i++) {
544                         pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
545                                                 phm_ppt_v1_pcie_record,
546                                                 entries, pcie_table, i);
547                         atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
548                                                 ATOM_Tonga_PCIE_Record,
549                                                 entries, atom_pcie_table, i);
550                         pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
551                         pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth;
552                 }
553
554                 *pp_tonga_pcie_table = pcie_table;
555         } else {
556                 /* Polaris10/Polaris11 and newer. */
557                 const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable;
558                 ATOM_Polaris10_PCIE_Record *atom_pcie_record;
559
560                 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
561                         "Invalid PowerPlay Table!", return -1);
562
563                 table_size = sizeof(uint32_t) +
564                         sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
565
566                 pcie_table = kzalloc(table_size, GFP_KERNEL);
567
568                 if (pcie_table == NULL)
569                         return -ENOMEM;
570
571                 memset(pcie_table, 0x00, table_size);
572
573                 /*
574                 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
575                 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
576                 */
577                 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
578                 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
579                         pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
580                 else
581                         printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
582                         Disregarding the excess entries... \n");
583
584                 pcie_table->count = pcie_count;
585
586                 for (i = 0; i < pcie_count; i++) {
587                         pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
588                                                 phm_ppt_v1_pcie_record,
589                                                 entries, pcie_table, i);
590                         atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
591                                                 ATOM_Polaris10_PCIE_Record,
592                                                 entries, atom_pcie_table, i);
593                         pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
594                         pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth;
595                         pcie_record->pcie_sclk = atom_pcie_record->ulPCIE_Sclk;
596                 }
597
598                 *pp_tonga_pcie_table = pcie_table;
599         }
600
601         return 0;
602 }
603
604 static int get_cac_tdp_table(
605                 struct pp_hwmgr *hwmgr,
606                 struct phm_cac_tdp_table **cac_tdp_table,
607                 const PPTable_Generic_SubTable_Header * table
608                 )
609 {
610         uint32_t table_size;
611         struct phm_cac_tdp_table *tdp_table;
612
613         table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table);
614         tdp_table = kzalloc(table_size, GFP_KERNEL);
615
616         if (NULL == tdp_table)
617                 return -ENOMEM;
618
619         memset(tdp_table, 0x00, table_size);
620
621         hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
622
623         if (NULL == hwmgr->dyn_state.cac_dtp_table) {
624                 kfree(tdp_table);
625                 return -ENOMEM;
626         }
627
628         memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size);
629
630         if (table->ucRevId < 3) {
631                 const ATOM_Tonga_PowerTune_Table *tonga_table =
632                         (ATOM_Tonga_PowerTune_Table *)table;
633                 tdp_table->usTDP = tonga_table->usTDP;
634                 tdp_table->usConfigurableTDP =
635                         tonga_table->usConfigurableTDP;
636                 tdp_table->usTDC = tonga_table->usTDC;
637                 tdp_table->usBatteryPowerLimit =
638                         tonga_table->usBatteryPowerLimit;
639                 tdp_table->usSmallPowerLimit =
640                         tonga_table->usSmallPowerLimit;
641                 tdp_table->usLowCACLeakage =
642                         tonga_table->usLowCACLeakage;
643                 tdp_table->usHighCACLeakage =
644                         tonga_table->usHighCACLeakage;
645                 tdp_table->usMaximumPowerDeliveryLimit =
646                         tonga_table->usMaximumPowerDeliveryLimit;
647                 tdp_table->usDefaultTargetOperatingTemp =
648                         tonga_table->usTjMax;
649                 tdp_table->usTargetOperatingTemp =
650                         tonga_table->usTjMax; /*Set the initial temp to the same as default */
651                 tdp_table->usPowerTuneDataSetID =
652                         tonga_table->usPowerTuneDataSetID;
653                 tdp_table->usSoftwareShutdownTemp =
654                         tonga_table->usSoftwareShutdownTemp;
655                 tdp_table->usClockStretchAmount =
656                         tonga_table->usClockStretchAmount;
657         } else {   /* Fiji and newer */
658                 const ATOM_Fiji_PowerTune_Table *fijitable =
659                         (ATOM_Fiji_PowerTune_Table *)table;
660                 tdp_table->usTDP = fijitable->usTDP;
661                 tdp_table->usConfigurableTDP = fijitable->usConfigurableTDP;
662                 tdp_table->usTDC = fijitable->usTDC;
663                 tdp_table->usBatteryPowerLimit = fijitable->usBatteryPowerLimit;
664                 tdp_table->usSmallPowerLimit = fijitable->usSmallPowerLimit;
665                 tdp_table->usLowCACLeakage = fijitable->usLowCACLeakage;
666                 tdp_table->usHighCACLeakage = fijitable->usHighCACLeakage;
667                 tdp_table->usMaximumPowerDeliveryLimit =
668                         fijitable->usMaximumPowerDeliveryLimit;
669                 tdp_table->usDefaultTargetOperatingTemp =
670                         fijitable->usTjMax;
671                 tdp_table->usTargetOperatingTemp =
672                         fijitable->usTjMax; /*Set the initial temp to the same as default */
673                 tdp_table->usPowerTuneDataSetID =
674                         fijitable->usPowerTuneDataSetID;
675                 tdp_table->usSoftwareShutdownTemp =
676                         fijitable->usSoftwareShutdownTemp;
677                 tdp_table->usClockStretchAmount =
678                         fijitable->usClockStretchAmount;
679                 tdp_table->usTemperatureLimitHotspot =
680                         fijitable->usTemperatureLimitHotspot;
681                 tdp_table->usTemperatureLimitLiquid1 =
682                         fijitable->usTemperatureLimitLiquid1;
683                 tdp_table->usTemperatureLimitLiquid2 =
684                         fijitable->usTemperatureLimitLiquid2;
685                 tdp_table->usTemperatureLimitVrVddc =
686                         fijitable->usTemperatureLimitVrVddc;
687                 tdp_table->usTemperatureLimitVrMvdd =
688                         fijitable->usTemperatureLimitVrMvdd;
689                 tdp_table->usTemperatureLimitPlx =
690                         fijitable->usTemperatureLimitPlx;
691                 tdp_table->ucLiquid1_I2C_address =
692                         fijitable->ucLiquid1_I2C_address;
693                 tdp_table->ucLiquid2_I2C_address =
694                         fijitable->ucLiquid2_I2C_address;
695                 tdp_table->ucLiquid_I2C_Line =
696                         fijitable->ucLiquid_I2C_Line;
697                 tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address;
698                 tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line;
699                 tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address;
700                 tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line;
701         }
702
703         *cac_tdp_table = tdp_table;
704
705         return 0;
706 }
707
708 static int get_mm_clock_voltage_table(
709                 struct pp_hwmgr *hwmgr,
710                 phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table,
711                 const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table
712                 )
713 {
714         uint32_t table_size, i;
715         const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record;
716         phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
717         phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record;
718
719         PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries),
720                 "Invalid PowerPlay Table!", return -1);
721         table_size = sizeof(uint32_t) +
722                 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record)
723                 * mm_dependency_table->ucNumEntries;
724         mm_table = kzalloc(table_size, GFP_KERNEL);
725
726         if (NULL == mm_table)
727                 return -ENOMEM;
728
729         memset(mm_table, 0x00, table_size);
730
731         mm_table->count = mm_dependency_table->ucNumEntries;
732
733         for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
734                 mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
735                                                 ATOM_Tonga_MM_Dependency_Record,
736                                                 entries, mm_dependency_table, i);
737                 mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
738                                         phm_ppt_v1_mm_clock_voltage_dependency_record,
739                                         entries, mm_table, i);
740                 mm_table_record->vddcInd = mm_dependency_record->ucVddcInd;
741                 mm_table_record->vddgfx_offset = mm_dependency_record->usVddgfxOffset;
742                 mm_table_record->aclk = mm_dependency_record->ulAClk;
743                 mm_table_record->samclock = mm_dependency_record->ulSAMUClk;
744                 mm_table_record->eclk = mm_dependency_record->ulEClk;
745                 mm_table_record->vclk = mm_dependency_record->ulVClk;
746                 mm_table_record->dclk = mm_dependency_record->ulDClk;
747         }
748
749         *tonga_mm_table = mm_table;
750
751         return 0;
752 }
753
754 /**
755  * Private Function used during initialization.
756  * Initialize clock voltage dependency
757  * @param hwmgr Pointer to the hardware manager.
758  * @param powerplay_table Pointer to the PowerPlay Table.
759  */
760 static int init_clock_voltage_dependency(
761                 struct pp_hwmgr *hwmgr,
762                 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
763                 )
764 {
765         int result = 0;
766         struct phm_ppt_v1_information *pp_table_information =
767                 (struct phm_ppt_v1_information *)(hwmgr->pptable);
768
769         const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table =
770                 (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) +
771                 le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
772         const PPTable_Generic_SubTable_Header *pPowerTuneTable =
773                 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
774                 le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
775         const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
776                 (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
777                 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
778         const PPTable_Generic_SubTable_Header *sclk_dep_table =
779                 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
780                 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
781         const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
782                 (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
783                 le16_to_cpu(powerplay_table->usHardLimitTableOffset));
784         const PPTable_Generic_SubTable_Header *pcie_table =
785                 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
786                 le16_to_cpu(powerplay_table->usPCIETableOffset));
787
788         pp_table_information->vdd_dep_on_sclk = NULL;
789         pp_table_information->vdd_dep_on_mclk = NULL;
790         pp_table_information->mm_dep_table = NULL;
791         pp_table_information->pcie_table = NULL;
792
793         if (powerplay_table->usMMDependencyTableOffset != 0)
794                 result = get_mm_clock_voltage_table(hwmgr,
795                 &pp_table_information->mm_dep_table, mm_dependency_table);
796
797         if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0)
798                 result = get_cac_tdp_table(hwmgr,
799                 &pp_table_information->cac_dtp_table, pPowerTuneTable);
800
801         if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0)
802                 result = get_sclk_voltage_dependency_table(hwmgr,
803                 &pp_table_information->vdd_dep_on_sclk, sclk_dep_table);
804
805         if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
806                 result = get_mclk_voltage_dependency_table(hwmgr,
807                 &pp_table_information->vdd_dep_on_mclk, mclk_dep_table);
808
809         if (result == 0 && powerplay_table->usPCIETableOffset != 0)
810                 result = get_pcie_table(hwmgr,
811                 &pp_table_information->pcie_table, pcie_table);
812
813         if (result == 0 && powerplay_table->usHardLimitTableOffset != 0)
814                 result = get_hard_limits(hwmgr,
815                 &pp_table_information->max_clock_voltage_on_dc, pHardLimits);
816
817         hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
818                 pp_table_information->max_clock_voltage_on_dc.sclk;
819         hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
820                 pp_table_information->max_clock_voltage_on_dc.mclk;
821         hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
822                 pp_table_information->max_clock_voltage_on_dc.vddc;
823         hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
824                 pp_table_information->max_clock_voltage_on_dc.vddci;
825
826         if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk)
827                 && (0 != pp_table_information->vdd_dep_on_mclk->count))
828                 result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values,
829                 pp_table_information->vdd_dep_on_mclk);
830
831         if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk)
832                 && (0 != pp_table_information->vdd_dep_on_sclk->count))
833                 result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values,
834                 pp_table_information->vdd_dep_on_sclk);
835
836         return result;
837 }
838
839 /** Retrieves the (signed) Overdrive limits from VBIOS.
840  * The max engine clock, memory clock and max temperature come from the firmware info table.
841  *
842  * The information is placed into the platform descriptor.
843  *
844  * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated.
845  * @param powerplay_table the address of the PowerPlay table.
846  *
847  * @return 1 as long as the firmware info table was present and of a supported version.
848  */
849 static int init_over_drive_limits(
850                 struct pp_hwmgr *hwmgr,
851                 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table)
852 {
853         hwmgr->platform_descriptor.overdriveLimit.engineClock =
854                 le16_to_cpu(powerplay_table->ulMaxODEngineClock);
855         hwmgr->platform_descriptor.overdriveLimit.memoryClock =
856                 le16_to_cpu(powerplay_table->ulMaxODMemoryClock);
857
858         hwmgr->platform_descriptor.minOverdriveVDDC = 0;
859         hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
860         hwmgr->platform_descriptor.overdriveVDDCStep = 0;
861
862         if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 \
863                 && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) {
864                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
865                         PHM_PlatformCaps_ACOverdriveSupport);
866         }
867
868         return 0;
869 }
870
871 /**
872  * Private Function used during initialization.
873  * Inspect the PowerPlay table for obvious signs of corruption.
874  * @param hwmgr Pointer to the hardware manager.
875  * @param powerplay_table Pointer to the PowerPlay Table.
876  * @exception This implementation always returns 1.
877  */
878 static int init_thermal_controller(
879                 struct pp_hwmgr *hwmgr,
880                 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
881                 )
882 {
883         const PPTable_Generic_SubTable_Header *fan_table;
884         ATOM_Tonga_Thermal_Controller *thermal_controller;
885
886         thermal_controller = (ATOM_Tonga_Thermal_Controller *)
887                 (((unsigned long)powerplay_table) +
888                 le16_to_cpu(powerplay_table->usThermalControllerOffset));
889         PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset),
890                 "Thermal controller table not set!", return -1);
891
892         hwmgr->thermal_controller.ucType = thermal_controller->ucType;
893         hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
894         hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
895
896         hwmgr->thermal_controller.fanInfo.bNoFan =
897                 (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN));
898
899         hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
900                 thermal_controller->ucFanParameters &
901                 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
902
903         hwmgr->thermal_controller.fanInfo.ulMinRPM
904                 = thermal_controller->ucFanMinRPM * 100UL;
905         hwmgr->thermal_controller.fanInfo.ulMaxRPM
906                 = thermal_controller->ucFanMaxRPM * 100UL;
907
908         set_hw_cap(
909                         hwmgr,
910                         ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
911                         PHM_PlatformCaps_ThermalController
912                   );
913
914         if (0 == powerplay_table->usFanTableOffset)
915                 return 0;
916
917         fan_table = (const PPTable_Generic_SubTable_Header *)
918                 (((unsigned long)powerplay_table) +
919                 le16_to_cpu(powerplay_table->usFanTableOffset));
920
921         PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset),
922                 "Fan table not set!", return -1);
923         PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId),
924                 "Unsupported fan table format!", return -1);
925
926         hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
927                 = 100000;
928         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
929                 PHM_PlatformCaps_MicrocodeFanControl);
930
931         if (fan_table->ucRevId < 8) {
932                 const ATOM_Tonga_Fan_Table *tonga_fan_table =
933                         (ATOM_Tonga_Fan_Table *)fan_table;
934                 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
935                         = tonga_fan_table->ucTHyst;
936                 hwmgr->thermal_controller.advanceFanControlParameters.usTMin
937                         = tonga_fan_table->usTMin;
938                 hwmgr->thermal_controller.advanceFanControlParameters.usTMed
939                         = tonga_fan_table->usTMed;
940                 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
941                         = tonga_fan_table->usTHigh;
942                 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
943                         = tonga_fan_table->usPWMMin;
944                 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
945                         = tonga_fan_table->usPWMMed;
946                 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
947                         = tonga_fan_table->usPWMHigh;
948                 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
949                         = 10900;                  /* hard coded */
950                 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
951                         = tonga_fan_table->usTMax;
952                 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
953                         = tonga_fan_table->ucFanControlMode;
954                 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
955                         = tonga_fan_table->usFanPWMMax;
956                 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
957                         = 4836;
958                 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
959                         = tonga_fan_table->usFanOutputSensitivity;
960                 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
961                         = tonga_fan_table->usFanRPMMax;
962                 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
963                         = (tonga_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
964                 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
965                         = tonga_fan_table->ucTargetTemperature;
966                 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
967                         = tonga_fan_table->ucMinimumPWMLimit;
968         } else {
969                 const ATOM_Fiji_Fan_Table *fiji_fan_table =
970                         (ATOM_Fiji_Fan_Table *)fan_table;
971                 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
972                         = fiji_fan_table->ucTHyst;
973                 hwmgr->thermal_controller.advanceFanControlParameters.usTMin
974                         = fiji_fan_table->usTMin;
975                 hwmgr->thermal_controller.advanceFanControlParameters.usTMed
976                         = fiji_fan_table->usTMed;
977                 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
978                         = fiji_fan_table->usTHigh;
979                 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
980                         = fiji_fan_table->usPWMMin;
981                 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
982                         = fiji_fan_table->usPWMMed;
983                 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
984                         = fiji_fan_table->usPWMHigh;
985                 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
986                         = fiji_fan_table->usTMax;
987                 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
988                         = fiji_fan_table->ucFanControlMode;
989                 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
990                         = fiji_fan_table->usFanPWMMax;
991                 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
992                         = 4836;
993                 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
994                         = fiji_fan_table->usFanOutputSensitivity;
995                 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
996                         = fiji_fan_table->usFanRPMMax;
997                 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
998                         = (fiji_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
999                 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
1000                         = fiji_fan_table->ucTargetTemperature;
1001                 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
1002                         = fiji_fan_table->ucMinimumPWMLimit;
1003
1004                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge
1005                         = fiji_fan_table->usFanGainEdge;
1006                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot
1007                         = fiji_fan_table->usFanGainHotspot;
1008                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid
1009                         = fiji_fan_table->usFanGainLiquid;
1010                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc
1011                         = fiji_fan_table->usFanGainVrVddc;
1012                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd
1013                         = fiji_fan_table->usFanGainVrMvdd;
1014                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx
1015                         = fiji_fan_table->usFanGainPlx;
1016                 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm
1017                         = fiji_fan_table->usFanGainHbm;
1018         }
1019
1020         return 0;
1021 }
1022
1023 /**
1024  * Private Function used during initialization.
1025  * Inspect the PowerPlay table for obvious signs of corruption.
1026  * @param hwmgr Pointer to the hardware manager.
1027  * @param powerplay_table Pointer to the PowerPlay Table.
1028  * @exception 2 if the powerplay table is incorrect.
1029  */
1030 static int check_powerplay_tables(
1031                 struct pp_hwmgr *hwmgr,
1032                 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
1033                 )
1034 {
1035         const ATOM_Tonga_State_Array *state_arrays;
1036
1037         state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) +
1038                 le16_to_cpu(powerplay_table->usStateArrayOffset));
1039
1040         PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <=
1041                 powerplay_table->sHeader.ucTableFormatRevision),
1042                 "Unsupported PPTable format!", return -1);
1043         PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset),
1044                 "State table is not set!", return -1);
1045         PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize),
1046                 "Invalid PowerPlay Table!", return -1);
1047         PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
1048                 "Invalid PowerPlay Table!", return -1);
1049
1050         return 0;
1051 }
1052
1053 int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
1054 {
1055         int result = 0;
1056         const ATOM_Tonga_POWERPLAYTABLE *powerplay_table;
1057
1058         hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL);
1059
1060         PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
1061                             "Failed to allocate hwmgr->pptable!", return -ENOMEM);
1062
1063         memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information));
1064
1065         powerplay_table = get_powerplay_table(hwmgr);
1066
1067         PP_ASSERT_WITH_CODE((NULL != powerplay_table),
1068                 "Missing PowerPlay Table!", return -1);
1069
1070         result = check_powerplay_tables(hwmgr, powerplay_table);
1071
1072         PP_ASSERT_WITH_CODE((result == 0),
1073                             "check_powerplay_tables failed", return result);
1074
1075         result = set_platform_caps(hwmgr,
1076                                    le32_to_cpu(powerplay_table->ulPlatformCaps));
1077
1078         PP_ASSERT_WITH_CODE((result == 0),
1079                             "set_platform_caps failed", return result);
1080
1081         result = init_thermal_controller(hwmgr, powerplay_table);
1082
1083         PP_ASSERT_WITH_CODE((result == 0),
1084                             "init_thermal_controller failed", return result);
1085
1086         result = init_over_drive_limits(hwmgr, powerplay_table);
1087
1088         PP_ASSERT_WITH_CODE((result == 0),
1089                             "init_over_drive_limits failed", return result);
1090
1091         result = init_clock_voltage_dependency(hwmgr, powerplay_table);
1092
1093         PP_ASSERT_WITH_CODE((result == 0),
1094                             "init_clock_voltage_dependency failed", return result);
1095
1096         result = init_dpm_2_parameters(hwmgr, powerplay_table);
1097
1098         PP_ASSERT_WITH_CODE((result == 0),
1099                             "init_dpm_2_parameters failed", return result);
1100
1101         return result;
1102 }
1103
1104 int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
1105 {
1106         struct phm_ppt_v1_information *pp_table_information =
1107                 (struct phm_ppt_v1_information *)(hwmgr->pptable);
1108
1109         kfree(pp_table_information->vdd_dep_on_sclk);
1110         pp_table_information->vdd_dep_on_sclk = NULL;
1111
1112         kfree(pp_table_information->vdd_dep_on_mclk);
1113         pp_table_information->vdd_dep_on_mclk = NULL;
1114
1115         kfree(pp_table_information->valid_mclk_values);
1116         pp_table_information->valid_mclk_values = NULL;
1117
1118         kfree(pp_table_information->valid_sclk_values);
1119         pp_table_information->valid_sclk_values = NULL;
1120
1121         kfree(pp_table_information->vddc_lookup_table);
1122         pp_table_information->vddc_lookup_table = NULL;
1123
1124         kfree(pp_table_information->vddgfx_lookup_table);
1125         pp_table_information->vddgfx_lookup_table = NULL;
1126
1127         kfree(pp_table_information->mm_dep_table);
1128         pp_table_information->mm_dep_table = NULL;
1129
1130         kfree(pp_table_information->cac_dtp_table);
1131         pp_table_information->cac_dtp_table = NULL;
1132
1133         kfree(hwmgr->dyn_state.cac_dtp_table);
1134         hwmgr->dyn_state.cac_dtp_table = NULL;
1135
1136         kfree(pp_table_information->ppm_parameter_table);
1137         pp_table_information->ppm_parameter_table = NULL;
1138
1139         kfree(pp_table_information->pcie_table);
1140         pp_table_information->pcie_table = NULL;
1141
1142         kfree(hwmgr->pptable);
1143         hwmgr->pptable = NULL;
1144
1145         return 0;
1146 }
1147
1148 const struct pp_table_func pptable_v1_0_funcs = {
1149         .pptable_init = pp_tables_v1_0_initialize,
1150         .pptable_fini = pp_tables_v1_0_uninitialize,
1151 };
1152
1153 int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr)
1154 {
1155         ATOM_Tonga_State_Array const *state_arrays;
1156         const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1157
1158         PP_ASSERT_WITH_CODE((NULL != pp_table),
1159                         "Missing PowerPlay Table!", return -1);
1160         PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >=
1161                         ATOM_Tonga_TABLE_REVISION_TONGA),
1162                         "Incorrect PowerPlay table revision!", return -1);
1163
1164         state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
1165                         le16_to_cpu(pp_table->usStateArrayOffset));
1166
1167         return (uint32_t)(state_arrays->ucNumEntries);
1168 }
1169
1170 /**
1171 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
1172 */
1173 static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
1174                 uint16_t classification, uint16_t classification2)
1175 {
1176         uint32_t result = 0;
1177
1178         if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
1179                 result |= PP_StateClassificationFlag_Boot;
1180
1181         if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1182                 result |= PP_StateClassificationFlag_Thermal;
1183
1184         if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
1185                 result |= PP_StateClassificationFlag_LimitedPowerSource;
1186
1187         if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
1188                 result |= PP_StateClassificationFlag_Rest;
1189
1190         if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
1191                 result |= PP_StateClassificationFlag_Forced;
1192
1193         if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
1194                 result |= PP_StateClassificationFlag_ACPI;
1195
1196         if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
1197                 result |= PP_StateClassificationFlag_LimitedPowerSource_2;
1198
1199         return result;
1200 }
1201
1202 static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)
1203 {
1204         const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1205         const ATOM_Tonga_VCE_State_Table *vce_state_table =
1206                                 (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pp_table) + le16_to_cpu(pp_table->usVCEStateTableOffset));
1207
1208         if (vce_state_table == NULL)
1209                 return 0;
1210
1211         return vce_state_table->ucNumEntries;
1212 }
1213
1214 static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i,
1215                 struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag)
1216 {
1217         const ATOM_Tonga_VCE_State_Record *vce_state_record;
1218         ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
1219         ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
1220         ATOM_Tonga_MM_Dependency_Record *mm_dep_record;
1221         const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr);
1222         const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable)
1223                                                           + le16_to_cpu(pptable->usVCEStateTableOffset));
1224         const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable)
1225                                                           + le16_to_cpu(pptable->usSclkDependencyTableOffset));
1226         const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable)
1227                                                           + le16_to_cpu(pptable->usMclkDependencyTableOffset));
1228         const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable)
1229                                                           + le16_to_cpu(pptable->usMMDependencyTableOffset));
1230
1231         PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries),
1232                          "Requested state entry ID is out of range!",
1233                          return -EINVAL);
1234
1235         vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1236                                         ATOM_Tonga_VCE_State_Record,
1237                                         entries, vce_state_table, i);
1238         sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1239                                         ATOM_Tonga_SCLK_Dependency_Record,
1240                                         entries, sclk_dep_table,
1241                                         vce_state_record->ucSCLKIndex);
1242         mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1243                                         ATOM_Tonga_MM_Dependency_Record,
1244                                         entries, mm_dep_table,
1245                                         vce_state_record->ucVCEClockIndex);
1246         *flag = vce_state_record->ucFlag;
1247
1248         vce_state->evclk = mm_dep_record->ulEClk;
1249         vce_state->ecclk = mm_dep_record->ulEClk;
1250         vce_state->sclk = sclk_dep_record->ulSclk;
1251
1252         if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries)
1253                 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1254                                         ATOM_Tonga_MCLK_Dependency_Record,
1255                                         entries, mclk_dep_table,
1256                                         mclk_dep_table->ucNumEntries - 1);
1257         else
1258                 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1259                                         ATOM_Tonga_MCLK_Dependency_Record,
1260                                         entries, mclk_dep_table,
1261                                         vce_state_record->ucMCLKIndex);
1262
1263         vce_state->mclk = mclk_dep_record->ulMclk;
1264         return 0;
1265 }
1266
1267 /**
1268 * Create a Power State out of an entry in the PowerPlay table.
1269 * This function is called by the hardware back-end.
1270 * @param hwmgr Pointer to the hardware manager.
1271 * @param entry_index The index of the entry to be extracted from the table.
1272 * @param power_state The address of the PowerState instance being created.
1273 * @return -1 if the entry cannot be retrieved.
1274 */
1275 int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr,
1276                 uint32_t entry_index, struct pp_power_state *power_state,
1277                 int (*call_back_func)(struct pp_hwmgr *, void *,
1278                                 struct pp_power_state *, void *, uint32_t))
1279 {
1280         int result = 0;
1281         const ATOM_Tonga_State_Array *state_arrays;
1282         const ATOM_Tonga_State *state_entry;
1283         const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
1284         int i, j;
1285         uint32_t flags = 0;
1286
1287         PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;);
1288         power_state->classification.bios_index = entry_index;
1289
1290         if (pp_table->sHeader.ucTableFormatRevision >=
1291                         ATOM_Tonga_TABLE_REVISION_TONGA) {
1292                 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
1293                                 le16_to_cpu(pp_table->usStateArrayOffset));
1294
1295                 PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset),
1296                                 "Invalid PowerPlay Table State Array Offset.", return -1);
1297                 PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
1298                                 "Invalid PowerPlay Table State Array.", return -1);
1299                 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
1300                                 "Invalid PowerPlay Table State Array Entry.", return -1);
1301
1302                 state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1303                                                 ATOM_Tonga_State, entries,
1304                                                 state_arrays, entry_index);
1305
1306                 result = call_back_func(hwmgr, (void *)state_entry, power_state,
1307                                 (void *)pp_table,
1308                                 make_classification_flags(hwmgr,
1309                                         le16_to_cpu(state_entry->usClassification),
1310                                         le16_to_cpu(state_entry->usClassification2)));
1311         }
1312
1313         if (!result && (power_state->classification.flags &
1314                         PP_StateClassificationFlag_Boot))
1315                 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
1316
1317         hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr);
1318
1319         if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) {
1320                 for (j = 0; j < i; j++)
1321                         ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags);
1322         }
1323
1324         return result;
1325 }
1326