root/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_vce_table_offset
  2. get_vce_clock_info_array_offset
  3. get_vce_clock_info_array_size
  4. get_vce_clock_voltage_limit_table_offset
  5. get_vce_clock_voltage_limit_table_size
  6. get_vce_state_table_offset
  7. get_vce_state_table
  8. get_uvd_table_offset
  9. get_uvd_clock_info_array_offset
  10. get_uvd_clock_info_array_size
  11. get_uvd_clock_voltage_limit_table_offset
  12. get_samu_table_offset
  13. get_samu_clock_voltage_limit_table_offset
  14. get_acp_table_offset
  15. get_acp_clock_voltage_limit_table_offset
  16. get_cacp_tdp_table_offset
  17. get_cac_tdp_table
  18. get_sclk_vdd_gfx_table_offset
  19. get_sclk_vdd_gfx_clock_voltage_dependency_table_offset
  20. get_clock_voltage_dependency_table
  21. get_valid_clk
  22. get_clock_voltage_limit
  23. set_hw_cap
  24. set_platform_caps
  25. make_classification_flags
  26. init_non_clock_fields
  27. size_of_entry_v2
  28. get_state_entry_v2
  29. get_powerplay_table
  30. pp_tables_get_response_times
  31. pp_tables_get_num_of_entries
  32. pp_tables_get_entry
  33. init_powerplay_tables
  34. init_thermal_controller
  35. init_overdrive_limits_V1_4
  36. init_overdrive_limits_V2_1
  37. init_overdrive_limits
  38. get_uvd_clock_voltage_limit_table
  39. get_vce_clock_voltage_limit_table
  40. get_samu_clock_voltage_limit_table
  41. get_acp_clock_voltage_limit_table
  42. init_clock_voltage_dependency
  43. get_cac_leakage_table
  44. get_platform_power_management_table
  45. init_dpm2_parameters
  46. init_phase_shedding_table
  47. get_number_of_vce_state_table_entries
  48. get_vce_state_table_entry
  49. pp_tables_initialize
  50. pp_tables_uninitialize

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

/* [<][>][^][v][top][bottom][index][help] */