LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/pm/powerplay/hwmgr - processpptables.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 767 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 30 0.0 %

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

Generated by: LCOV version 1.14