root/drivers/gpu/drm/amd/powerplay/navi10_ppt.c

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

DEFINITIONS

This source file includes following definitions.
  1. navi10_get_smu_msg_index
  2. navi10_get_smu_clk_index
  3. navi10_get_smu_feature_index
  4. navi10_get_smu_table_index
  5. navi10_get_pwr_src_index
  6. navi10_get_workload_type
  7. is_asic_secure
  8. navi10_get_allowed_feature_mask
  9. navi10_check_powerplay_table
  10. navi10_append_powerplay_table
  11. navi10_store_powerplay_table
  12. navi10_tables_init
  13. navi10_get_metrics_table
  14. navi10_allocate_dpm_context
  15. navi10_set_default_dpm_table
  16. navi10_dpm_set_uvd_enable
  17. navi10_get_current_clk_freq_by_table
  18. navi10_is_support_fine_grained_dpm
  19. navi10_print_clk_levels
  20. navi10_force_clk_levels
  21. navi10_populate_umd_state_clk
  22. navi10_get_clock_by_type_with_latency
  23. navi10_pre_display_config_changed
  24. navi10_display_config_changed
  25. navi10_force_dpm_limit_value
  26. navi10_unforce_dpm_levels
  27. navi10_get_gpu_power
  28. navi10_get_current_activity_percent
  29. navi10_is_dpm_running
  30. navi10_get_fan_speed_rpm
  31. navi10_get_fan_speed_percent
  32. navi10_get_power_profile_mode
  33. navi10_set_power_profile_mode
  34. navi10_get_profiling_clk_mask
  35. navi10_notify_smc_dispaly_config
  36. navi10_set_watermarks_table
  37. navi10_thermal_get_temperature
  38. navi10_read_sensor
  39. navi10_get_uclk_dpm_states
  40. navi10_set_peak_clock_by_device
  41. navi10_set_performance_level
  42. navi10_get_thermal_temperature_range
  43. navi10_display_disable_memory_clock_switch
  44. navi10_get_power_limit
  45. navi10_set_ppt_funcs

   1 /*
   2  * Copyright 2019 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 
  24 #include "pp_debug.h"
  25 #include <linux/firmware.h>
  26 #include <linux/pci.h>
  27 #include "amdgpu.h"
  28 #include "amdgpu_smu.h"
  29 #include "atomfirmware.h"
  30 #include "amdgpu_atomfirmware.h"
  31 #include "smu_v11_0.h"
  32 #include "smu11_driver_if_navi10.h"
  33 #include "soc15_common.h"
  34 #include "atom.h"
  35 #include "navi10_ppt.h"
  36 #include "smu_v11_0_pptable.h"
  37 #include "smu_v11_0_ppsmc.h"
  38 
  39 #include "asic_reg/mp/mp_11_0_sh_mask.h"
  40 
  41 #define FEATURE_MASK(feature) (1ULL << feature)
  42 #define SMC_DPM_FEATURE ( \
  43         FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
  44         FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)     | \
  45         FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT)   | \
  46         FEATURE_MASK(FEATURE_DPM_UCLK_BIT)       | \
  47         FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)     | \
  48         FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)     | \
  49         FEATURE_MASK(FEATURE_DPM_LINK_BIT)       | \
  50         FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT))
  51 
  52 #define MSG_MAP(msg, index) \
  53         [SMU_MSG_##msg] = {1, (index)}
  54 
  55 static struct smu_11_0_cmn2aisc_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = {
  56         MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage),
  57         MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion),
  58         MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion),
  59         MSG_MAP(SetAllowedFeaturesMaskLow,      PPSMC_MSG_SetAllowedFeaturesMaskLow),
  60         MSG_MAP(SetAllowedFeaturesMaskHigh,     PPSMC_MSG_SetAllowedFeaturesMaskHigh),
  61         MSG_MAP(EnableAllSmuFeatures,           PPSMC_MSG_EnableAllSmuFeatures),
  62         MSG_MAP(DisableAllSmuFeatures,          PPSMC_MSG_DisableAllSmuFeatures),
  63         MSG_MAP(EnableSmuFeaturesLow,           PPSMC_MSG_EnableSmuFeaturesLow),
  64         MSG_MAP(EnableSmuFeaturesHigh,          PPSMC_MSG_EnableSmuFeaturesHigh),
  65         MSG_MAP(DisableSmuFeaturesLow,          PPSMC_MSG_DisableSmuFeaturesLow),
  66         MSG_MAP(DisableSmuFeaturesHigh,         PPSMC_MSG_DisableSmuFeaturesHigh),
  67         MSG_MAP(GetEnabledSmuFeaturesLow,       PPSMC_MSG_GetEnabledSmuFeaturesLow),
  68         MSG_MAP(GetEnabledSmuFeaturesHigh,      PPSMC_MSG_GetEnabledSmuFeaturesHigh),
  69         MSG_MAP(SetWorkloadMask,                PPSMC_MSG_SetWorkloadMask),
  70         MSG_MAP(SetPptLimit,                    PPSMC_MSG_SetPptLimit),
  71         MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh),
  72         MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow),
  73         MSG_MAP(SetToolsDramAddrHigh,           PPSMC_MSG_SetToolsDramAddrHigh),
  74         MSG_MAP(SetToolsDramAddrLow,            PPSMC_MSG_SetToolsDramAddrLow),
  75         MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram),
  76         MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu),
  77         MSG_MAP(UseDefaultPPTable,              PPSMC_MSG_UseDefaultPPTable),
  78         MSG_MAP(UseBackupPPTable,               PPSMC_MSG_UseBackupPPTable),
  79         MSG_MAP(RunBtc,                         PPSMC_MSG_RunBtc),
  80         MSG_MAP(EnterBaco,                      PPSMC_MSG_EnterBaco),
  81         MSG_MAP(SetSoftMinByFreq,               PPSMC_MSG_SetSoftMinByFreq),
  82         MSG_MAP(SetSoftMaxByFreq,               PPSMC_MSG_SetSoftMaxByFreq),
  83         MSG_MAP(SetHardMinByFreq,               PPSMC_MSG_SetHardMinByFreq),
  84         MSG_MAP(SetHardMaxByFreq,               PPSMC_MSG_SetHardMaxByFreq),
  85         MSG_MAP(GetMinDpmFreq,                  PPSMC_MSG_GetMinDpmFreq),
  86         MSG_MAP(GetMaxDpmFreq,                  PPSMC_MSG_GetMaxDpmFreq),
  87         MSG_MAP(GetDpmFreqByIndex,              PPSMC_MSG_GetDpmFreqByIndex),
  88         MSG_MAP(SetMemoryChannelConfig,         PPSMC_MSG_SetMemoryChannelConfig),
  89         MSG_MAP(SetGeminiMode,                  PPSMC_MSG_SetGeminiMode),
  90         MSG_MAP(SetGeminiApertureHigh,          PPSMC_MSG_SetGeminiApertureHigh),
  91         MSG_MAP(SetGeminiApertureLow,           PPSMC_MSG_SetGeminiApertureLow),
  92         MSG_MAP(OverridePcieParameters,         PPSMC_MSG_OverridePcieParameters),
  93         MSG_MAP(SetMinDeepSleepDcefclk,         PPSMC_MSG_SetMinDeepSleepDcefclk),
  94         MSG_MAP(ReenableAcDcInterrupt,          PPSMC_MSG_ReenableAcDcInterrupt),
  95         MSG_MAP(NotifyPowerSource,              PPSMC_MSG_NotifyPowerSource),
  96         MSG_MAP(SetUclkFastSwitch,              PPSMC_MSG_SetUclkFastSwitch),
  97         MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps),
  98         MSG_MAP(PrepareMp1ForUnload,            PPSMC_MSG_PrepareMp1ForUnload),
  99         MSG_MAP(DramLogSetDramAddrHigh,         PPSMC_MSG_DramLogSetDramAddrHigh),
 100         MSG_MAP(DramLogSetDramAddrLow,          PPSMC_MSG_DramLogSetDramAddrLow),
 101         MSG_MAP(DramLogSetDramSize,             PPSMC_MSG_DramLogSetDramSize),
 102         MSG_MAP(ConfigureGfxDidt,               PPSMC_MSG_ConfigureGfxDidt),
 103         MSG_MAP(NumOfDisplays,                  PPSMC_MSG_NumOfDisplays),
 104         MSG_MAP(SetSystemVirtualDramAddrHigh,   PPSMC_MSG_SetSystemVirtualDramAddrHigh),
 105         MSG_MAP(SetSystemVirtualDramAddrLow,    PPSMC_MSG_SetSystemVirtualDramAddrLow),
 106         MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff),
 107         MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff),
 108         MSG_MAP(GetPptLimit,                    PPSMC_MSG_GetPptLimit),
 109         MSG_MAP(GetDcModeMaxDpmFreq,            PPSMC_MSG_GetDcModeMaxDpmFreq),
 110         MSG_MAP(GetDebugData,                   PPSMC_MSG_GetDebugData),
 111         MSG_MAP(ExitBaco,                       PPSMC_MSG_ExitBaco),
 112         MSG_MAP(PrepareMp1ForReset,             PPSMC_MSG_PrepareMp1ForReset),
 113         MSG_MAP(PrepareMp1ForShutdown,          PPSMC_MSG_PrepareMp1ForShutdown),
 114         MSG_MAP(PowerUpVcn,             PPSMC_MSG_PowerUpVcn),
 115         MSG_MAP(PowerDownVcn,           PPSMC_MSG_PowerDownVcn),
 116         MSG_MAP(PowerUpJpeg,            PPSMC_MSG_PowerUpJpeg),
 117         MSG_MAP(PowerDownJpeg,          PPSMC_MSG_PowerDownJpeg),
 118         MSG_MAP(BacoAudioD3PME,         PPSMC_MSG_BacoAudioD3PME),
 119         MSG_MAP(ArmD3,                  PPSMC_MSG_ArmD3),
 120 };
 121 
 122 static struct smu_11_0_cmn2aisc_mapping navi10_clk_map[SMU_CLK_COUNT] = {
 123         CLK_MAP(GFXCLK, PPCLK_GFXCLK),
 124         CLK_MAP(SCLK,   PPCLK_GFXCLK),
 125         CLK_MAP(SOCCLK, PPCLK_SOCCLK),
 126         CLK_MAP(FCLK, PPCLK_SOCCLK),
 127         CLK_MAP(UCLK, PPCLK_UCLK),
 128         CLK_MAP(MCLK, PPCLK_UCLK),
 129         CLK_MAP(DCLK, PPCLK_DCLK),
 130         CLK_MAP(VCLK, PPCLK_VCLK),
 131         CLK_MAP(DCEFCLK, PPCLK_DCEFCLK),
 132         CLK_MAP(DISPCLK, PPCLK_DISPCLK),
 133         CLK_MAP(PIXCLK, PPCLK_PIXCLK),
 134         CLK_MAP(PHYCLK, PPCLK_PHYCLK),
 135 };
 136 
 137 static struct smu_11_0_cmn2aisc_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = {
 138         FEA_MAP(DPM_PREFETCHER),
 139         FEA_MAP(DPM_GFXCLK),
 140         FEA_MAP(DPM_GFX_PACE),
 141         FEA_MAP(DPM_UCLK),
 142         FEA_MAP(DPM_SOCCLK),
 143         FEA_MAP(DPM_MP0CLK),
 144         FEA_MAP(DPM_LINK),
 145         FEA_MAP(DPM_DCEFCLK),
 146         FEA_MAP(MEM_VDDCI_SCALING),
 147         FEA_MAP(MEM_MVDD_SCALING),
 148         FEA_MAP(DS_GFXCLK),
 149         FEA_MAP(DS_SOCCLK),
 150         FEA_MAP(DS_LCLK),
 151         FEA_MAP(DS_DCEFCLK),
 152         FEA_MAP(DS_UCLK),
 153         FEA_MAP(GFX_ULV),
 154         FEA_MAP(FW_DSTATE),
 155         FEA_MAP(GFXOFF),
 156         FEA_MAP(BACO),
 157         FEA_MAP(VCN_PG),
 158         FEA_MAP(JPEG_PG),
 159         FEA_MAP(USB_PG),
 160         FEA_MAP(RSMU_SMN_CG),
 161         FEA_MAP(PPT),
 162         FEA_MAP(TDC),
 163         FEA_MAP(GFX_EDC),
 164         FEA_MAP(APCC_PLUS),
 165         FEA_MAP(GTHR),
 166         FEA_MAP(ACDC),
 167         FEA_MAP(VR0HOT),
 168         FEA_MAP(VR1HOT),
 169         FEA_MAP(FW_CTF),
 170         FEA_MAP(FAN_CONTROL),
 171         FEA_MAP(THERMAL),
 172         FEA_MAP(GFX_DCS),
 173         FEA_MAP(RM),
 174         FEA_MAP(LED_DISPLAY),
 175         FEA_MAP(GFX_SS),
 176         FEA_MAP(OUT_OF_BAND_MONITOR),
 177         FEA_MAP(TEMP_DEPENDENT_VMIN),
 178         FEA_MAP(MMHUB_PG),
 179         FEA_MAP(ATHUB_PG),
 180 };
 181 
 182 static struct smu_11_0_cmn2aisc_mapping navi10_table_map[SMU_TABLE_COUNT] = {
 183         TAB_MAP(PPTABLE),
 184         TAB_MAP(WATERMARKS),
 185         TAB_MAP(AVFS),
 186         TAB_MAP(AVFS_PSM_DEBUG),
 187         TAB_MAP(AVFS_FUSE_OVERRIDE),
 188         TAB_MAP(PMSTATUSLOG),
 189         TAB_MAP(SMU_METRICS),
 190         TAB_MAP(DRIVER_SMU_CONFIG),
 191         TAB_MAP(ACTIVITY_MONITOR_COEFF),
 192         TAB_MAP(OVERDRIVE),
 193         TAB_MAP(I2C_COMMANDS),
 194         TAB_MAP(PACE),
 195 };
 196 
 197 static struct smu_11_0_cmn2aisc_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
 198         PWR_MAP(AC),
 199         PWR_MAP(DC),
 200 };
 201 
 202 static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
 203         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT,       WORKLOAD_PPLIB_DEFAULT_BIT),
 204         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,         WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
 205         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
 206         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
 207         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
 208         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
 209         WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
 210 };
 211 
 212 static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t index)
 213 {
 214         struct smu_11_0_cmn2aisc_mapping mapping;
 215 
 216         if (index >= SMU_MSG_MAX_COUNT)
 217                 return -EINVAL;
 218 
 219         mapping = navi10_message_map[index];
 220         if (!(mapping.valid_mapping)) {
 221                 return -EINVAL;
 222         }
 223 
 224         return mapping.map_to;
 225 }
 226 
 227 static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index)
 228 {
 229         struct smu_11_0_cmn2aisc_mapping mapping;
 230 
 231         if (index >= SMU_CLK_COUNT)
 232                 return -EINVAL;
 233 
 234         mapping = navi10_clk_map[index];
 235         if (!(mapping.valid_mapping)) {
 236                 return -EINVAL;
 237         }
 238 
 239         return mapping.map_to;
 240 }
 241 
 242 static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index)
 243 {
 244         struct smu_11_0_cmn2aisc_mapping mapping;
 245 
 246         if (index >= SMU_FEATURE_COUNT)
 247                 return -EINVAL;
 248 
 249         mapping = navi10_feature_mask_map[index];
 250         if (!(mapping.valid_mapping)) {
 251                 return -EINVAL;
 252         }
 253 
 254         return mapping.map_to;
 255 }
 256 
 257 static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index)
 258 {
 259         struct smu_11_0_cmn2aisc_mapping mapping;
 260 
 261         if (index >= SMU_TABLE_COUNT)
 262                 return -EINVAL;
 263 
 264         mapping = navi10_table_map[index];
 265         if (!(mapping.valid_mapping)) {
 266                 return -EINVAL;
 267         }
 268 
 269         return mapping.map_to;
 270 }
 271 
 272 static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index)
 273 {
 274         struct smu_11_0_cmn2aisc_mapping mapping;
 275 
 276         if (index >= SMU_POWER_SOURCE_COUNT)
 277                 return -EINVAL;
 278 
 279         mapping = navi10_pwr_src_map[index];
 280         if (!(mapping.valid_mapping)) {
 281                 return -EINVAL;
 282         }
 283 
 284         return mapping.map_to;
 285 }
 286 
 287 
 288 static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile)
 289 {
 290         struct smu_11_0_cmn2aisc_mapping mapping;
 291 
 292         if (profile > PP_SMC_POWER_PROFILE_CUSTOM)
 293                 return -EINVAL;
 294 
 295         mapping = navi10_workload_map[profile];
 296         if (!(mapping.valid_mapping)) {
 297                 return -EINVAL;
 298         }
 299 
 300         return mapping.map_to;
 301 }
 302 
 303 static bool is_asic_secure(struct smu_context *smu)
 304 {
 305         struct amdgpu_device *adev = smu->adev;
 306         bool is_secure = true;
 307         uint32_t mp0_fw_intf;
 308 
 309         mp0_fw_intf = RREG32_PCIE(MP0_Public |
 310                                    (smnMP0_FW_INTF & 0xffffffff));
 311 
 312         if (!(mp0_fw_intf & (1 << 19)))
 313                 is_secure = false;
 314 
 315         return is_secure;
 316 }
 317 
 318 static int
 319 navi10_get_allowed_feature_mask(struct smu_context *smu,
 320                                   uint32_t *feature_mask, uint32_t num)
 321 {
 322         struct amdgpu_device *adev = smu->adev;
 323 
 324         if (num > 2)
 325                 return -EINVAL;
 326 
 327         memset(feature_mask, 0, sizeof(uint32_t) * num);
 328 
 329         *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT)
 330                                 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT)
 331                                 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT)
 332                                 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)
 333                                 | FEATURE_MASK(FEATURE_DPM_LINK_BIT)
 334                                 | FEATURE_MASK(FEATURE_GFX_ULV_BIT)
 335                                 | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT)
 336                                 | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
 337                                 | FEATURE_MASK(FEATURE_PPT_BIT)
 338                                 | FEATURE_MASK(FEATURE_TDC_BIT)
 339                                 | FEATURE_MASK(FEATURE_GFX_EDC_BIT)
 340                                 | FEATURE_MASK(FEATURE_VR0HOT_BIT)
 341                                 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT)
 342                                 | FEATURE_MASK(FEATURE_THERMAL_BIT)
 343                                 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT)
 344                                 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)
 345                                 | FEATURE_MASK(FEATURE_DS_GFXCLK_BIT)
 346                                 | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT)
 347                                 | FEATURE_MASK(FEATURE_FW_DSTATE_BIT)
 348                                 | FEATURE_MASK(FEATURE_BACO_BIT)
 349                                 | FEATURE_MASK(FEATURE_ACDC_BIT)
 350                                 | FEATURE_MASK(FEATURE_GFX_SS_BIT)
 351                                 | FEATURE_MASK(FEATURE_APCC_DFLL_BIT)
 352                                 | FEATURE_MASK(FEATURE_FW_CTF_BIT);
 353 
 354         if (adev->pm.pp_feature & PP_MCLK_DPM_MASK)
 355                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
 356                                 | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
 357                                 | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT);
 358 
 359         if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
 360                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
 361                 /* TODO: remove it once fw fix the bug */
 362                 *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
 363         }
 364 
 365         if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB)
 366                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT);
 367 
 368         if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
 369                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
 370 
 371         if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN)
 372                 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT)
 373                                 | FEATURE_MASK(FEATURE_JPEG_PG_BIT);
 374 
 375         /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */
 376         if (is_asic_secure(smu)) {
 377                 /* only for navi10 A0 */
 378                 if ((adev->asic_type == CHIP_NAVI10) &&
 379                         (adev->rev_id == 0)) {
 380                         *(uint64_t *)feature_mask &=
 381                                         ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT)
 382                                           | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT)
 383                                           | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT));
 384                         *(uint64_t *)feature_mask &=
 385                                         ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
 386                 }
 387         }
 388 
 389         return 0;
 390 }
 391 
 392 static int navi10_check_powerplay_table(struct smu_context *smu)
 393 {
 394         return 0;
 395 }
 396 
 397 static int navi10_append_powerplay_table(struct smu_context *smu)
 398 {
 399         struct amdgpu_device *adev = smu->adev;
 400         struct smu_table_context *table_context = &smu->smu_table;
 401         PPTable_t *smc_pptable = table_context->driver_pptable;
 402         struct atom_smc_dpm_info_v4_5 *smc_dpm_table;
 403         int index, ret;
 404 
 405         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
 406                                            smc_dpm_info);
 407 
 408         ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL,
 409                                       (uint8_t **)&smc_dpm_table);
 410         if (ret)
 411                 return ret;
 412 
 413         memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers,
 414                sizeof(I2cControllerConfig_t) * NUM_I2C_CONTROLLERS);
 415 
 416         /* SVI2 Board Parameters */
 417         smc_pptable->MaxVoltageStepGfx = smc_dpm_table->MaxVoltageStepGfx;
 418         smc_pptable->MaxVoltageStepSoc = smc_dpm_table->MaxVoltageStepSoc;
 419         smc_pptable->VddGfxVrMapping = smc_dpm_table->VddGfxVrMapping;
 420         smc_pptable->VddSocVrMapping = smc_dpm_table->VddSocVrMapping;
 421         smc_pptable->VddMem0VrMapping = smc_dpm_table->VddMem0VrMapping;
 422         smc_pptable->VddMem1VrMapping = smc_dpm_table->VddMem1VrMapping;
 423         smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->GfxUlvPhaseSheddingMask;
 424         smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->SocUlvPhaseSheddingMask;
 425         smc_pptable->ExternalSensorPresent = smc_dpm_table->ExternalSensorPresent;
 426         smc_pptable->Padding8_V = smc_dpm_table->Padding8_V;
 427 
 428         /* Telemetry Settings */
 429         smc_pptable->GfxMaxCurrent = smc_dpm_table->GfxMaxCurrent;
 430         smc_pptable->GfxOffset = smc_dpm_table->GfxOffset;
 431         smc_pptable->Padding_TelemetryGfx = smc_dpm_table->Padding_TelemetryGfx;
 432         smc_pptable->SocMaxCurrent = smc_dpm_table->SocMaxCurrent;
 433         smc_pptable->SocOffset = smc_dpm_table->SocOffset;
 434         smc_pptable->Padding_TelemetrySoc = smc_dpm_table->Padding_TelemetrySoc;
 435         smc_pptable->Mem0MaxCurrent = smc_dpm_table->Mem0MaxCurrent;
 436         smc_pptable->Mem0Offset = smc_dpm_table->Mem0Offset;
 437         smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->Padding_TelemetryMem0;
 438         smc_pptable->Mem1MaxCurrent = smc_dpm_table->Mem1MaxCurrent;
 439         smc_pptable->Mem1Offset = smc_dpm_table->Mem1Offset;
 440         smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->Padding_TelemetryMem1;
 441 
 442         /* GPIO Settings */
 443         smc_pptable->AcDcGpio = smc_dpm_table->AcDcGpio;
 444         smc_pptable->AcDcPolarity = smc_dpm_table->AcDcPolarity;
 445         smc_pptable->VR0HotGpio = smc_dpm_table->VR0HotGpio;
 446         smc_pptable->VR0HotPolarity = smc_dpm_table->VR0HotPolarity;
 447         smc_pptable->VR1HotGpio = smc_dpm_table->VR1HotGpio;
 448         smc_pptable->VR1HotPolarity = smc_dpm_table->VR1HotPolarity;
 449         smc_pptable->GthrGpio = smc_dpm_table->GthrGpio;
 450         smc_pptable->GthrPolarity = smc_dpm_table->GthrPolarity;
 451 
 452         /* LED Display Settings */
 453         smc_pptable->LedPin0 = smc_dpm_table->LedPin0;
 454         smc_pptable->LedPin1 = smc_dpm_table->LedPin1;
 455         smc_pptable->LedPin2 = smc_dpm_table->LedPin2;
 456         smc_pptable->padding8_4 = smc_dpm_table->padding8_4;
 457 
 458         /* GFXCLK PLL Spread Spectrum */
 459         smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->PllGfxclkSpreadEnabled;
 460         smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->PllGfxclkSpreadPercent;
 461         smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->PllGfxclkSpreadFreq;
 462 
 463         /* GFXCLK DFLL Spread Spectrum */
 464         smc_pptable->DfllGfxclkSpreadEnabled = smc_dpm_table->DfllGfxclkSpreadEnabled;
 465         smc_pptable->DfllGfxclkSpreadPercent = smc_dpm_table->DfllGfxclkSpreadPercent;
 466         smc_pptable->DfllGfxclkSpreadFreq = smc_dpm_table->DfllGfxclkSpreadFreq;
 467 
 468         /* UCLK Spread Spectrum */
 469         smc_pptable->UclkSpreadEnabled = smc_dpm_table->UclkSpreadEnabled;
 470         smc_pptable->UclkSpreadPercent = smc_dpm_table->UclkSpreadPercent;
 471         smc_pptable->UclkSpreadFreq = smc_dpm_table->UclkSpreadFreq;
 472 
 473         /* SOCCLK Spread Spectrum */
 474         smc_pptable->SoclkSpreadEnabled = smc_dpm_table->SoclkSpreadEnabled;
 475         smc_pptable->SocclkSpreadPercent = smc_dpm_table->SocclkSpreadPercent;
 476         smc_pptable->SocclkSpreadFreq = smc_dpm_table->SocclkSpreadFreq;
 477 
 478         /* Total board power */
 479         smc_pptable->TotalBoardPower = smc_dpm_table->TotalBoardPower;
 480         smc_pptable->BoardPadding = smc_dpm_table->BoardPadding;
 481 
 482         /* Mvdd Svi2 Div Ratio Setting */
 483         smc_pptable->MvddRatio = smc_dpm_table->MvddRatio;
 484 
 485         if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
 486                 /* TODO: remove it once SMU fw fix it */
 487                 smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN;
 488         }
 489 
 490         return 0;
 491 }
 492 
 493 static int navi10_store_powerplay_table(struct smu_context *smu)
 494 {
 495         struct smu_11_0_powerplay_table *powerplay_table = NULL;
 496         struct smu_table_context *table_context = &smu->smu_table;
 497         struct smu_baco_context *smu_baco = &smu->smu_baco;
 498 
 499         if (!table_context->power_play_table)
 500                 return -EINVAL;
 501 
 502         powerplay_table = table_context->power_play_table;
 503 
 504         memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
 505                sizeof(PPTable_t));
 506 
 507         table_context->thermal_controller_type = powerplay_table->thermal_controller_type;
 508 
 509         mutex_lock(&smu_baco->mutex);
 510         if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO ||
 511             powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO)
 512                 smu_baco->platform_support = true;
 513         mutex_unlock(&smu_baco->mutex);
 514 
 515         return 0;
 516 }
 517 
 518 static int navi10_tables_init(struct smu_context *smu, struct smu_table *tables)
 519 {
 520         struct smu_table_context *smu_table = &smu->smu_table;
 521 
 522         SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
 523                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 524         SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
 525                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 526         SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
 527                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 528         SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
 529                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 530         SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
 531                        PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 532         SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
 533                        sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
 534                        AMDGPU_GEM_DOMAIN_VRAM);
 535 
 536         smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
 537         if (!smu_table->metrics_table)
 538                 return -ENOMEM;
 539         smu_table->metrics_time = 0;
 540 
 541         return 0;
 542 }
 543 
 544 static int navi10_get_metrics_table(struct smu_context *smu,
 545                                     SmuMetrics_t *metrics_table)
 546 {
 547         struct smu_table_context *smu_table= &smu->smu_table;
 548         int ret = 0;
 549 
 550         mutex_lock(&smu->metrics_lock);
 551         if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) {
 552                 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
 553                                 (void *)smu_table->metrics_table, false);
 554                 if (ret) {
 555                         pr_info("Failed to export SMU metrics table!\n");
 556                         mutex_unlock(&smu->metrics_lock);
 557                         return ret;
 558                 }
 559                 smu_table->metrics_time = jiffies;
 560         }
 561 
 562         memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
 563         mutex_unlock(&smu->metrics_lock);
 564 
 565         return ret;
 566 }
 567 
 568 static int navi10_allocate_dpm_context(struct smu_context *smu)
 569 {
 570         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
 571 
 572         if (smu_dpm->dpm_context)
 573                 return -EINVAL;
 574 
 575         smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
 576                                        GFP_KERNEL);
 577         if (!smu_dpm->dpm_context)
 578                 return -ENOMEM;
 579 
 580         smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
 581 
 582         return 0;
 583 }
 584 
 585 static int navi10_set_default_dpm_table(struct smu_context *smu)
 586 {
 587         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
 588         struct smu_table_context *table_context = &smu->smu_table;
 589         struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context;
 590         PPTable_t *driver_ppt = NULL;
 591 
 592         driver_ppt = table_context->driver_pptable;
 593 
 594         dpm_context->dpm_tables.soc_table.min = driver_ppt->FreqTableSocclk[0];
 595         dpm_context->dpm_tables.soc_table.max = driver_ppt->FreqTableSocclk[NUM_SOCCLK_DPM_LEVELS - 1];
 596 
 597         dpm_context->dpm_tables.gfx_table.min = driver_ppt->FreqTableGfx[0];
 598         dpm_context->dpm_tables.gfx_table.max = driver_ppt->FreqTableGfx[NUM_GFXCLK_DPM_LEVELS - 1];
 599 
 600         dpm_context->dpm_tables.uclk_table.min = driver_ppt->FreqTableUclk[0];
 601         dpm_context->dpm_tables.uclk_table.max = driver_ppt->FreqTableUclk[NUM_UCLK_DPM_LEVELS - 1];
 602 
 603         dpm_context->dpm_tables.vclk_table.min = driver_ppt->FreqTableVclk[0];
 604         dpm_context->dpm_tables.vclk_table.max = driver_ppt->FreqTableVclk[NUM_VCLK_DPM_LEVELS - 1];
 605 
 606         dpm_context->dpm_tables.dclk_table.min = driver_ppt->FreqTableDclk[0];
 607         dpm_context->dpm_tables.dclk_table.max = driver_ppt->FreqTableDclk[NUM_DCLK_DPM_LEVELS - 1];
 608 
 609         dpm_context->dpm_tables.dcef_table.min = driver_ppt->FreqTableDcefclk[0];
 610         dpm_context->dpm_tables.dcef_table.max = driver_ppt->FreqTableDcefclk[NUM_DCEFCLK_DPM_LEVELS - 1];
 611 
 612         dpm_context->dpm_tables.pixel_table.min = driver_ppt->FreqTablePixclk[0];
 613         dpm_context->dpm_tables.pixel_table.max = driver_ppt->FreqTablePixclk[NUM_PIXCLK_DPM_LEVELS - 1];
 614 
 615         dpm_context->dpm_tables.display_table.min = driver_ppt->FreqTableDispclk[0];
 616         dpm_context->dpm_tables.display_table.max = driver_ppt->FreqTableDispclk[NUM_DISPCLK_DPM_LEVELS - 1];
 617 
 618         dpm_context->dpm_tables.phy_table.min = driver_ppt->FreqTablePhyclk[0];
 619         dpm_context->dpm_tables.phy_table.max = driver_ppt->FreqTablePhyclk[NUM_PHYCLK_DPM_LEVELS - 1];
 620 
 621         return 0;
 622 }
 623 
 624 static int navi10_dpm_set_uvd_enable(struct smu_context *smu, bool enable)
 625 {
 626         struct smu_power_context *smu_power = &smu->smu_power;
 627         struct smu_power_gate *power_gate = &smu_power->power_gate;
 628         int ret = 0;
 629 
 630         if (enable) {
 631                 /* vcn dpm on is a prerequisite for vcn power gate messages */
 632                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
 633                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1);
 634                         if (ret)
 635                                 return ret;
 636                 }
 637                 power_gate->vcn_gated = false;
 638         } else {
 639                 if (smu_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
 640                         ret = smu_send_smc_msg(smu, SMU_MSG_PowerDownVcn);
 641                         if (ret)
 642                                 return ret;
 643                 }
 644                 power_gate->vcn_gated = true;
 645         }
 646 
 647         return ret;
 648 }
 649 
 650 static int navi10_get_current_clk_freq_by_table(struct smu_context *smu,
 651                                        enum smu_clk_type clk_type,
 652                                        uint32_t *value)
 653 {
 654         int ret = 0, clk_id = 0;
 655         SmuMetrics_t metrics;
 656 
 657         ret = navi10_get_metrics_table(smu, &metrics);
 658         if (ret)
 659                 return ret;
 660 
 661         clk_id = smu_clk_get_index(smu, clk_type);
 662         if (clk_id < 0)
 663                 return clk_id;
 664 
 665         *value = metrics.CurrClock[clk_id];
 666 
 667         return ret;
 668 }
 669 
 670 static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type)
 671 {
 672         PPTable_t *pptable = smu->smu_table.driver_pptable;
 673         DpmDescriptor_t *dpm_desc = NULL;
 674         uint32_t clk_index = 0;
 675 
 676         clk_index = smu_clk_get_index(smu, clk_type);
 677         dpm_desc = &pptable->DpmDescriptor[clk_index];
 678 
 679         /* 0 - Fine grained DPM, 1 - Discrete DPM */
 680         return dpm_desc->SnapToDiscrete == 0 ? true : false;
 681 }
 682 
 683 static int navi10_print_clk_levels(struct smu_context *smu,
 684                         enum smu_clk_type clk_type, char *buf)
 685 {
 686         int i, size = 0, ret = 0;
 687         uint32_t cur_value = 0, value = 0, count = 0;
 688         uint32_t freq_values[3] = {0};
 689         uint32_t mark_index = 0;
 690 
 691         switch (clk_type) {
 692         case SMU_GFXCLK:
 693         case SMU_SCLK:
 694         case SMU_SOCCLK:
 695         case SMU_MCLK:
 696         case SMU_UCLK:
 697         case SMU_FCLK:
 698         case SMU_DCEFCLK:
 699                 ret = smu_get_current_clk_freq(smu, clk_type, &cur_value);
 700                 if (ret)
 701                         return size;
 702 
 703                 /* 10KHz -> MHz */
 704                 cur_value = cur_value / 100;
 705 
 706                 ret = smu_get_dpm_level_count(smu, clk_type, &count);
 707                 if (ret)
 708                         return size;
 709 
 710                 if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) {
 711                         for (i = 0; i < count; i++) {
 712                                 ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &value);
 713                                 if (ret)
 714                                         return size;
 715 
 716                                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
 717                                                 cur_value == value ? "*" : "");
 718                         }
 719                 } else {
 720                         ret = smu_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]);
 721                         if (ret)
 722                                 return size;
 723                         ret = smu_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]);
 724                         if (ret)
 725                                 return size;
 726 
 727                         freq_values[1] = cur_value;
 728                         mark_index = cur_value == freq_values[0] ? 0 :
 729                                      cur_value == freq_values[2] ? 2 : 1;
 730                         if (mark_index != 1)
 731                                 freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
 732 
 733                         for (i = 0; i < 3; i++) {
 734                                 size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i],
 735                                                 i == mark_index ? "*" : "");
 736                         }
 737 
 738                 }
 739                 break;
 740         default:
 741                 break;
 742         }
 743 
 744         return size;
 745 }
 746 
 747 static int navi10_force_clk_levels(struct smu_context *smu,
 748                                    enum smu_clk_type clk_type, uint32_t mask)
 749 {
 750 
 751         int ret = 0, size = 0;
 752         uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
 753 
 754         soft_min_level = mask ? (ffs(mask) - 1) : 0;
 755         soft_max_level = mask ? (fls(mask) - 1) : 0;
 756 
 757         switch (clk_type) {
 758         case SMU_GFXCLK:
 759         case SMU_SCLK:
 760         case SMU_SOCCLK:
 761         case SMU_MCLK:
 762         case SMU_UCLK:
 763         case SMU_DCEFCLK:
 764         case SMU_FCLK:
 765                 /* There is only 2 levels for fine grained DPM */
 766                 if (navi10_is_support_fine_grained_dpm(smu, clk_type)) {
 767                         soft_max_level = (soft_max_level >= 1 ? 1 : 0);
 768                         soft_min_level = (soft_min_level >= 1 ? 1 : 0);
 769                 }
 770 
 771                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
 772                 if (ret)
 773                         return size;
 774 
 775                 ret = smu_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
 776                 if (ret)
 777                         return size;
 778 
 779                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
 780                 if (ret)
 781                         return size;
 782                 break;
 783         default:
 784                 break;
 785         }
 786 
 787         return size;
 788 }
 789 
 790 static int navi10_populate_umd_state_clk(struct smu_context *smu)
 791 {
 792         int ret = 0;
 793         uint32_t min_sclk_freq = 0, min_mclk_freq = 0;
 794 
 795         ret = smu_get_dpm_freq_range(smu, SMU_SCLK, &min_sclk_freq, NULL);
 796         if (ret)
 797                 return ret;
 798 
 799         smu->pstate_sclk = min_sclk_freq * 100;
 800 
 801         ret = smu_get_dpm_freq_range(smu, SMU_MCLK, &min_mclk_freq, NULL);
 802         if (ret)
 803                 return ret;
 804 
 805         smu->pstate_mclk = min_mclk_freq * 100;
 806 
 807         return ret;
 808 }
 809 
 810 static int navi10_get_clock_by_type_with_latency(struct smu_context *smu,
 811                                                  enum smu_clk_type clk_type,
 812                                                  struct pp_clock_levels_with_latency *clocks)
 813 {
 814         int ret = 0, i = 0;
 815         uint32_t level_count = 0, freq = 0;
 816 
 817         switch (clk_type) {
 818         case SMU_GFXCLK:
 819         case SMU_DCEFCLK:
 820         case SMU_SOCCLK:
 821                 ret = smu_get_dpm_level_count(smu, clk_type, &level_count);
 822                 if (ret)
 823                         return ret;
 824 
 825                 level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS);
 826                 clocks->num_levels = level_count;
 827 
 828                 for (i = 0; i < level_count; i++) {
 829                         ret = smu_get_dpm_freq_by_index(smu, clk_type, i, &freq);
 830                         if (ret)
 831                                 return ret;
 832 
 833                         clocks->data[i].clocks_in_khz = freq * 1000;
 834                         clocks->data[i].latency_in_us = 0;
 835                 }
 836                 break;
 837         default:
 838                 break;
 839         }
 840 
 841         return ret;
 842 }
 843 
 844 static int navi10_pre_display_config_changed(struct smu_context *smu)
 845 {
 846         int ret = 0;
 847         uint32_t max_freq = 0;
 848 
 849         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0);
 850         if (ret)
 851                 return ret;
 852 
 853         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
 854                 ret = smu_get_dpm_freq_range(smu, SMU_UCLK, NULL, &max_freq);
 855                 if (ret)
 856                         return ret;
 857                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, 0, max_freq);
 858                 if (ret)
 859                         return ret;
 860         }
 861 
 862         return ret;
 863 }
 864 
 865 static int navi10_display_config_changed(struct smu_context *smu)
 866 {
 867         int ret = 0;
 868 
 869         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
 870             !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
 871                 ret = smu_write_watermarks_table(smu);
 872                 if (ret)
 873                         return ret;
 874 
 875                 smu->watermarks_bitmap |= WATERMARKS_LOADED;
 876         }
 877 
 878         if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
 879             smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
 880             smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
 881                 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
 882                                                   smu->display_config->num_display);
 883                 if (ret)
 884                         return ret;
 885         }
 886 
 887         return ret;
 888 }
 889 
 890 static int navi10_force_dpm_limit_value(struct smu_context *smu, bool highest)
 891 {
 892         int ret = 0, i = 0;
 893         uint32_t min_freq, max_freq, force_freq;
 894         enum smu_clk_type clk_type;
 895 
 896         enum smu_clk_type clks[] = {
 897                 SMU_GFXCLK,
 898                 SMU_MCLK,
 899                 SMU_SOCCLK,
 900         };
 901 
 902         for (i = 0; i < ARRAY_SIZE(clks); i++) {
 903                 clk_type = clks[i];
 904                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
 905                 if (ret)
 906                         return ret;
 907 
 908                 force_freq = highest ? max_freq : min_freq;
 909                 ret = smu_set_soft_freq_range(smu, clk_type, force_freq, force_freq);
 910                 if (ret)
 911                         return ret;
 912         }
 913 
 914         return ret;
 915 }
 916 
 917 static int navi10_unforce_dpm_levels(struct smu_context *smu)
 918 {
 919         int ret = 0, i = 0;
 920         uint32_t min_freq, max_freq;
 921         enum smu_clk_type clk_type;
 922 
 923         enum smu_clk_type clks[] = {
 924                 SMU_GFXCLK,
 925                 SMU_MCLK,
 926                 SMU_SOCCLK,
 927         };
 928 
 929         for (i = 0; i < ARRAY_SIZE(clks); i++) {
 930                 clk_type = clks[i];
 931                 ret = smu_get_dpm_freq_range(smu, clk_type, &min_freq, &max_freq);
 932                 if (ret)
 933                         return ret;
 934 
 935                 ret = smu_set_soft_freq_range(smu, clk_type, min_freq, max_freq);
 936                 if (ret)
 937                         return ret;
 938         }
 939 
 940         return ret;
 941 }
 942 
 943 static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
 944 {
 945         int ret = 0;
 946         SmuMetrics_t metrics;
 947 
 948         if (!value)
 949                 return -EINVAL;
 950 
 951         ret = navi10_get_metrics_table(smu, &metrics);
 952         if (ret)
 953                 return ret;
 954 
 955         *value = metrics.AverageSocketPower << 8;
 956 
 957         return 0;
 958 }
 959 
 960 static int navi10_get_current_activity_percent(struct smu_context *smu,
 961                                                enum amd_pp_sensors sensor,
 962                                                uint32_t *value)
 963 {
 964         int ret = 0;
 965         SmuMetrics_t metrics;
 966 
 967         if (!value)
 968                 return -EINVAL;
 969 
 970         ret = navi10_get_metrics_table(smu, &metrics);
 971         if (ret)
 972                 return ret;
 973 
 974         switch (sensor) {
 975         case AMDGPU_PP_SENSOR_GPU_LOAD:
 976                 *value = metrics.AverageGfxActivity;
 977                 break;
 978         case AMDGPU_PP_SENSOR_MEM_LOAD:
 979                 *value = metrics.AverageUclkActivity;
 980                 break;
 981         default:
 982                 pr_err("Invalid sensor for retrieving clock activity\n");
 983                 return -EINVAL;
 984         }
 985 
 986         return 0;
 987 }
 988 
 989 static bool navi10_is_dpm_running(struct smu_context *smu)
 990 {
 991         int ret = 0;
 992         uint32_t feature_mask[2];
 993         unsigned long feature_enabled;
 994         ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
 995         feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
 996                            ((uint64_t)feature_mask[1] << 32));
 997         return !!(feature_enabled & SMC_DPM_FEATURE);
 998 }
 999 
1000 static int navi10_get_fan_speed_rpm(struct smu_context *smu,
1001                                     uint32_t *speed)
1002 {
1003         SmuMetrics_t metrics;
1004         int ret = 0;
1005 
1006         if (!speed)
1007                 return -EINVAL;
1008 
1009         ret = navi10_get_metrics_table(smu, &metrics);
1010         if (ret)
1011                 return ret;
1012 
1013         *speed = metrics.CurrFanSpeed;
1014 
1015         return ret;
1016 }
1017 
1018 static int navi10_get_fan_speed_percent(struct smu_context *smu,
1019                                         uint32_t *speed)
1020 {
1021         int ret = 0;
1022         uint32_t percent = 0;
1023         uint32_t current_rpm;
1024         PPTable_t *pptable = smu->smu_table.driver_pptable;
1025 
1026         ret = navi10_get_fan_speed_rpm(smu, &current_rpm);
1027         if (ret)
1028                 return ret;
1029 
1030         percent = current_rpm * 100 / pptable->FanMaximumRpm;
1031         *speed = percent > 100 ? 100 : percent;
1032 
1033         return ret;
1034 }
1035 
1036 static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
1037 {
1038         DpmActivityMonitorCoeffInt_t activity_monitor;
1039         uint32_t i, size = 0;
1040         int16_t workload_type = 0;
1041         static const char *profile_name[] = {
1042                                         "BOOTUP_DEFAULT",
1043                                         "3D_FULL_SCREEN",
1044                                         "POWER_SAVING",
1045                                         "VIDEO",
1046                                         "VR",
1047                                         "COMPUTE",
1048                                         "CUSTOM"};
1049         static const char *title[] = {
1050                         "PROFILE_INDEX(NAME)",
1051                         "CLOCK_TYPE(NAME)",
1052                         "FPS",
1053                         "MinFreqType",
1054                         "MinActiveFreqType",
1055                         "MinActiveFreq",
1056                         "BoosterFreqType",
1057                         "BoosterFreq",
1058                         "PD_Data_limit_c",
1059                         "PD_Data_error_coeff",
1060                         "PD_Data_error_rate_coeff"};
1061         int result = 0;
1062 
1063         if (!buf)
1064                 return -EINVAL;
1065 
1066         size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
1067                         title[0], title[1], title[2], title[3], title[4], title[5],
1068                         title[6], title[7], title[8], title[9], title[10]);
1069 
1070         for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1071                 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1072                 workload_type = smu_workload_get_type(smu, i);
1073                 if (workload_type < 0)
1074                         return -EINVAL;
1075 
1076                 result = smu_update_table(smu,
1077                                           SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
1078                                           (void *)(&activity_monitor), false);
1079                 if (result) {
1080                         pr_err("[%s] Failed to get activity monitor!", __func__);
1081                         return result;
1082                 }
1083 
1084                 size += sprintf(buf + size, "%2d %14s%s:\n",
1085                         i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1086 
1087                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1088                         " ",
1089                         0,
1090                         "GFXCLK",
1091                         activity_monitor.Gfx_FPS,
1092                         activity_monitor.Gfx_MinFreqStep,
1093                         activity_monitor.Gfx_MinActiveFreqType,
1094                         activity_monitor.Gfx_MinActiveFreq,
1095                         activity_monitor.Gfx_BoosterFreqType,
1096                         activity_monitor.Gfx_BoosterFreq,
1097                         activity_monitor.Gfx_PD_Data_limit_c,
1098                         activity_monitor.Gfx_PD_Data_error_coeff,
1099                         activity_monitor.Gfx_PD_Data_error_rate_coeff);
1100 
1101                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1102                         " ",
1103                         1,
1104                         "SOCCLK",
1105                         activity_monitor.Soc_FPS,
1106                         activity_monitor.Soc_MinFreqStep,
1107                         activity_monitor.Soc_MinActiveFreqType,
1108                         activity_monitor.Soc_MinActiveFreq,
1109                         activity_monitor.Soc_BoosterFreqType,
1110                         activity_monitor.Soc_BoosterFreq,
1111                         activity_monitor.Soc_PD_Data_limit_c,
1112                         activity_monitor.Soc_PD_Data_error_coeff,
1113                         activity_monitor.Soc_PD_Data_error_rate_coeff);
1114 
1115                 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
1116                         " ",
1117                         2,
1118                         "MEMLK",
1119                         activity_monitor.Mem_FPS,
1120                         activity_monitor.Mem_MinFreqStep,
1121                         activity_monitor.Mem_MinActiveFreqType,
1122                         activity_monitor.Mem_MinActiveFreq,
1123                         activity_monitor.Mem_BoosterFreqType,
1124                         activity_monitor.Mem_BoosterFreq,
1125                         activity_monitor.Mem_PD_Data_limit_c,
1126                         activity_monitor.Mem_PD_Data_error_coeff,
1127                         activity_monitor.Mem_PD_Data_error_rate_coeff);
1128         }
1129 
1130         return size;
1131 }
1132 
1133 static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
1134 {
1135         DpmActivityMonitorCoeffInt_t activity_monitor;
1136         int workload_type, ret = 0;
1137 
1138         smu->power_profile_mode = input[size];
1139 
1140         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
1141                 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode);
1142                 return -EINVAL;
1143         }
1144 
1145         if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
1146                 if (size < 0)
1147                         return -EINVAL;
1148 
1149                 ret = smu_update_table(smu,
1150                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1151                                        (void *)(&activity_monitor), false);
1152                 if (ret) {
1153                         pr_err("[%s] Failed to get activity monitor!", __func__);
1154                         return ret;
1155                 }
1156 
1157                 switch (input[0]) {
1158                 case 0: /* Gfxclk */
1159                         activity_monitor.Gfx_FPS = input[1];
1160                         activity_monitor.Gfx_MinFreqStep = input[2];
1161                         activity_monitor.Gfx_MinActiveFreqType = input[3];
1162                         activity_monitor.Gfx_MinActiveFreq = input[4];
1163                         activity_monitor.Gfx_BoosterFreqType = input[5];
1164                         activity_monitor.Gfx_BoosterFreq = input[6];
1165                         activity_monitor.Gfx_PD_Data_limit_c = input[7];
1166                         activity_monitor.Gfx_PD_Data_error_coeff = input[8];
1167                         activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
1168                         break;
1169                 case 1: /* Socclk */
1170                         activity_monitor.Soc_FPS = input[1];
1171                         activity_monitor.Soc_MinFreqStep = input[2];
1172                         activity_monitor.Soc_MinActiveFreqType = input[3];
1173                         activity_monitor.Soc_MinActiveFreq = input[4];
1174                         activity_monitor.Soc_BoosterFreqType = input[5];
1175                         activity_monitor.Soc_BoosterFreq = input[6];
1176                         activity_monitor.Soc_PD_Data_limit_c = input[7];
1177                         activity_monitor.Soc_PD_Data_error_coeff = input[8];
1178                         activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
1179                         break;
1180                 case 2: /* Memlk */
1181                         activity_monitor.Mem_FPS = input[1];
1182                         activity_monitor.Mem_MinFreqStep = input[2];
1183                         activity_monitor.Mem_MinActiveFreqType = input[3];
1184                         activity_monitor.Mem_MinActiveFreq = input[4];
1185                         activity_monitor.Mem_BoosterFreqType = input[5];
1186                         activity_monitor.Mem_BoosterFreq = input[6];
1187                         activity_monitor.Mem_PD_Data_limit_c = input[7];
1188                         activity_monitor.Mem_PD_Data_error_coeff = input[8];
1189                         activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
1190                         break;
1191                 }
1192 
1193                 ret = smu_update_table(smu,
1194                                        SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
1195                                        (void *)(&activity_monitor), true);
1196                 if (ret) {
1197                         pr_err("[%s] Failed to set activity monitor!", __func__);
1198                         return ret;
1199                 }
1200         }
1201 
1202         /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1203         workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
1204         if (workload_type < 0)
1205                 return -EINVAL;
1206         smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
1207                                     1 << workload_type);
1208 
1209         return ret;
1210 }
1211 
1212 static int navi10_get_profiling_clk_mask(struct smu_context *smu,
1213                                          enum amd_dpm_forced_level level,
1214                                          uint32_t *sclk_mask,
1215                                          uint32_t *mclk_mask,
1216                                          uint32_t *soc_mask)
1217 {
1218         int ret = 0;
1219         uint32_t level_count = 0;
1220 
1221         if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
1222                 if (sclk_mask)
1223                         *sclk_mask = 0;
1224         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
1225                 if (mclk_mask)
1226                         *mclk_mask = 0;
1227         } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
1228                 if(sclk_mask) {
1229                         ret = smu_get_dpm_level_count(smu, SMU_SCLK, &level_count);
1230                         if (ret)
1231                                 return ret;
1232                         *sclk_mask = level_count - 1;
1233                 }
1234 
1235                 if(mclk_mask) {
1236                         ret = smu_get_dpm_level_count(smu, SMU_MCLK, &level_count);
1237                         if (ret)
1238                                 return ret;
1239                         *mclk_mask = level_count - 1;
1240                 }
1241 
1242                 if(soc_mask) {
1243                         ret = smu_get_dpm_level_count(smu, SMU_SOCCLK, &level_count);
1244                         if (ret)
1245                                 return ret;
1246                         *soc_mask = level_count - 1;
1247                 }
1248         }
1249 
1250         return ret;
1251 }
1252 
1253 static int navi10_notify_smc_dispaly_config(struct smu_context *smu)
1254 {
1255         struct smu_clocks min_clocks = {0};
1256         struct pp_display_clock_request clock_req;
1257         int ret = 0;
1258 
1259         min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk;
1260         min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk;
1261         min_clocks.memory_clock = smu->display_config->min_mem_set_clock;
1262 
1263         if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
1264                 clock_req.clock_type = amd_pp_dcef_clock;
1265                 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10;
1266                 if (!smu_display_clock_voltage_request(smu, &clock_req)) {
1267                         if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) {
1268                                 ret = smu_send_smc_msg_with_param(smu,
1269                                                                   SMU_MSG_SetMinDeepSleepDcefclk,
1270                                                                   min_clocks.dcef_clock_in_sr/100);
1271                                 if (ret) {
1272                                         pr_err("Attempt to set divider for DCEFCLK Failed!");
1273                                         return ret;
1274                                 }
1275                         }
1276                 } else {
1277                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
1278                 }
1279         }
1280 
1281         if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
1282                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0);
1283                 if (ret) {
1284                         pr_err("[%s] Set hard min uclk failed!", __func__);
1285                         return ret;
1286                 }
1287         }
1288 
1289         return 0;
1290 }
1291 
1292 static int navi10_set_watermarks_table(struct smu_context *smu,
1293                                        void *watermarks, struct
1294                                        dm_pp_wm_sets_with_clock_ranges_soc15
1295                                        *clock_ranges)
1296 {
1297         int i;
1298         Watermarks_t *table = watermarks;
1299 
1300         if (!table || !clock_ranges)
1301                 return -EINVAL;
1302 
1303         if (clock_ranges->num_wm_dmif_sets > 4 ||
1304             clock_ranges->num_wm_mcif_sets > 4)
1305                 return -EINVAL;
1306 
1307         for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) {
1308                 table->WatermarkRow[1][i].MinClock =
1309                         cpu_to_le16((uint16_t)
1310                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
1311                         1000));
1312                 table->WatermarkRow[1][i].MaxClock =
1313                         cpu_to_le16((uint16_t)
1314                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
1315                         1000));
1316                 table->WatermarkRow[1][i].MinUclk =
1317                         cpu_to_le16((uint16_t)
1318                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1319                         1000));
1320                 table->WatermarkRow[1][i].MaxUclk =
1321                         cpu_to_le16((uint16_t)
1322                         (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1323                         1000));
1324                 table->WatermarkRow[1][i].WmSetting = (uint8_t)
1325                                 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
1326         }
1327 
1328         for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) {
1329                 table->WatermarkRow[0][i].MinClock =
1330                         cpu_to_le16((uint16_t)
1331                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
1332                         1000));
1333                 table->WatermarkRow[0][i].MaxClock =
1334                         cpu_to_le16((uint16_t)
1335                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
1336                         1000));
1337                 table->WatermarkRow[0][i].MinUclk =
1338                         cpu_to_le16((uint16_t)
1339                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1340                         1000));
1341                 table->WatermarkRow[0][i].MaxUclk =
1342                         cpu_to_le16((uint16_t)
1343                         (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1344                         1000));
1345                 table->WatermarkRow[0][i].WmSetting = (uint8_t)
1346                                 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
1347         }
1348 
1349         return 0;
1350 }
1351 
1352 static int navi10_thermal_get_temperature(struct smu_context *smu,
1353                                              enum amd_pp_sensors sensor,
1354                                              uint32_t *value)
1355 {
1356         SmuMetrics_t metrics;
1357         int ret = 0;
1358 
1359         if (!value)
1360                 return -EINVAL;
1361 
1362         ret = navi10_get_metrics_table(smu, &metrics);
1363         if (ret)
1364                 return ret;
1365 
1366         switch (sensor) {
1367         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1368                 *value = metrics.TemperatureHotspot *
1369                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1370                 break;
1371         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1372                 *value = metrics.TemperatureEdge *
1373                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1374                 break;
1375         case AMDGPU_PP_SENSOR_MEM_TEMP:
1376                 *value = metrics.TemperatureMem *
1377                         SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1378                 break;
1379         default:
1380                 pr_err("Invalid sensor for retrieving temp\n");
1381                 return -EINVAL;
1382         }
1383 
1384         return 0;
1385 }
1386 
1387 static int navi10_read_sensor(struct smu_context *smu,
1388                                  enum amd_pp_sensors sensor,
1389                                  void *data, uint32_t *size)
1390 {
1391         int ret = 0;
1392         struct smu_table_context *table_context = &smu->smu_table;
1393         PPTable_t *pptable = table_context->driver_pptable;
1394 
1395         if(!data || !size)
1396                 return -EINVAL;
1397 
1398         mutex_lock(&smu->sensor_lock);
1399         switch (sensor) {
1400         case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
1401                 *(uint32_t *)data = pptable->FanMaximumRpm;
1402                 *size = 4;
1403                 break;
1404         case AMDGPU_PP_SENSOR_MEM_LOAD:
1405         case AMDGPU_PP_SENSOR_GPU_LOAD:
1406                 ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
1407                 *size = 4;
1408                 break;
1409         case AMDGPU_PP_SENSOR_GPU_POWER:
1410                 ret = navi10_get_gpu_power(smu, (uint32_t *)data);
1411                 *size = 4;
1412                 break;
1413         case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1414         case AMDGPU_PP_SENSOR_EDGE_TEMP:
1415         case AMDGPU_PP_SENSOR_MEM_TEMP:
1416                 ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
1417                 *size = 4;
1418                 break;
1419         default:
1420                 ret = smu_smc_read_sensor(smu, sensor, data, size);
1421         }
1422         mutex_unlock(&smu->sensor_lock);
1423 
1424         return ret;
1425 }
1426 
1427 static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states)
1428 {
1429         uint32_t num_discrete_levels = 0;
1430         uint16_t *dpm_levels = NULL;
1431         uint16_t i = 0;
1432         struct smu_table_context *table_context = &smu->smu_table;
1433         PPTable_t *driver_ppt = NULL;
1434 
1435         if (!clocks_in_khz || !num_states || !table_context->driver_pptable)
1436                 return -EINVAL;
1437 
1438         driver_ppt = table_context->driver_pptable;
1439         num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels;
1440         dpm_levels = driver_ppt->FreqTableUclk;
1441 
1442         if (num_discrete_levels == 0 || dpm_levels == NULL)
1443                 return -EINVAL;
1444 
1445         *num_states = num_discrete_levels;
1446         for (i = 0; i < num_discrete_levels; i++) {
1447                 /* convert to khz */
1448                 *clocks_in_khz = (*dpm_levels) * 1000;
1449                 clocks_in_khz++;
1450                 dpm_levels++;
1451         }
1452 
1453         return 0;
1454 }
1455 
1456 static int navi10_set_peak_clock_by_device(struct smu_context *smu)
1457 {
1458         struct amdgpu_device *adev = smu->adev;
1459         int ret = 0;
1460         uint32_t sclk_freq = 0, uclk_freq = 0;
1461         uint32_t uclk_level = 0;
1462 
1463         switch (adev->pdev->revision) {
1464         case 0xf0: /* XTX */
1465         case 0xc0:
1466                 sclk_freq = NAVI10_PEAK_SCLK_XTX;
1467                 break;
1468         case 0xf1: /* XT */
1469         case 0xc1:
1470                 sclk_freq = NAVI10_PEAK_SCLK_XT;
1471                 break;
1472         default: /* XL */
1473                 sclk_freq = NAVI10_PEAK_SCLK_XL;
1474                 break;
1475         }
1476 
1477         ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
1478         if (ret)
1479                 return ret;
1480         ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, uclk_level - 1, &uclk_freq);
1481         if (ret)
1482                 return ret;
1483 
1484         ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
1485         if (ret)
1486                 return ret;
1487         ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
1488         if (ret)
1489                 return ret;
1490 
1491         return ret;
1492 }
1493 
1494 static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
1495 {
1496         int ret = 0;
1497         struct amdgpu_device *adev = smu->adev;
1498 
1499         if (adev->asic_type != CHIP_NAVI10)
1500                 return -EINVAL;
1501 
1502         switch (level) {
1503         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1504                 ret = navi10_set_peak_clock_by_device(smu);
1505                 break;
1506         default:
1507                 ret = -EINVAL;
1508                 break;
1509         }
1510 
1511         return ret;
1512 }
1513 
1514 static int navi10_get_thermal_temperature_range(struct smu_context *smu,
1515                                                 struct smu_temperature_range *range)
1516 {
1517         struct smu_table_context *table_context = &smu->smu_table;
1518         struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
1519 
1520         if (!range || !powerplay_table)
1521                 return -EINVAL;
1522 
1523         range->max = powerplay_table->software_shutdown_temp *
1524                 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1525 
1526         return 0;
1527 }
1528 
1529 static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
1530                                                 bool disable_memory_clock_switch)
1531 {
1532         int ret = 0;
1533         struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
1534                 (struct smu_11_0_max_sustainable_clocks *)
1535                         smu->smu_table.max_sustainable_clocks;
1536         uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
1537         uint32_t max_memory_clock = max_sustainable_clocks->uclock;
1538 
1539         if(smu->disable_uclk_switch == disable_memory_clock_switch)
1540                 return 0;
1541 
1542         if(disable_memory_clock_switch)
1543                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0);
1544         else
1545                 ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0);
1546 
1547         if(!ret)
1548                 smu->disable_uclk_switch = disable_memory_clock_switch;
1549 
1550         return ret;
1551 }
1552 
1553 static int navi10_get_power_limit(struct smu_context *smu,
1554                                      uint32_t *limit,
1555                                      bool asic_default)
1556 {
1557         PPTable_t *pptable = smu->smu_table.driver_pptable;
1558         uint32_t asic_default_power_limit = 0;
1559         int ret = 0;
1560         int power_src;
1561 
1562         if (!smu->default_power_limit ||
1563             !smu->power_limit) {
1564                 if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
1565                         power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
1566                         if (power_src < 0)
1567                                 return -EINVAL;
1568 
1569                         ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
1570                                 power_src << 16);
1571                         if (ret) {
1572                                 pr_err("[%s] get PPT limit failed!", __func__);
1573                                 return ret;
1574                         }
1575                         smu_read_smc_arg(smu, &asic_default_power_limit);
1576                 } else {
1577                         /* the last hope to figure out the ppt limit */
1578                         if (!pptable) {
1579                                 pr_err("Cannot get PPT limit due to pptable missing!");
1580                                 return -EINVAL;
1581                         }
1582                         asic_default_power_limit =
1583                                 pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
1584                 }
1585 
1586                 if (smu->od_enabled) {
1587                         asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit);
1588                         asic_default_power_limit /= 100;
1589                 }
1590 
1591                 smu->default_power_limit = asic_default_power_limit;
1592                 smu->power_limit = asic_default_power_limit;
1593         }
1594 
1595         if (asic_default)
1596                 *limit = smu->default_power_limit;
1597         else
1598                 *limit = smu->power_limit;
1599 
1600         return 0;
1601 }
1602 
1603 static const struct pptable_funcs navi10_ppt_funcs = {
1604         .tables_init = navi10_tables_init,
1605         .alloc_dpm_context = navi10_allocate_dpm_context,
1606         .store_powerplay_table = navi10_store_powerplay_table,
1607         .check_powerplay_table = navi10_check_powerplay_table,
1608         .append_powerplay_table = navi10_append_powerplay_table,
1609         .get_smu_msg_index = navi10_get_smu_msg_index,
1610         .get_smu_clk_index = navi10_get_smu_clk_index,
1611         .get_smu_feature_index = navi10_get_smu_feature_index,
1612         .get_smu_table_index = navi10_get_smu_table_index,
1613         .get_smu_power_index = navi10_get_pwr_src_index,
1614         .get_workload_type = navi10_get_workload_type,
1615         .get_allowed_feature_mask = navi10_get_allowed_feature_mask,
1616         .set_default_dpm_table = navi10_set_default_dpm_table,
1617         .dpm_set_uvd_enable = navi10_dpm_set_uvd_enable,
1618         .get_current_clk_freq_by_table = navi10_get_current_clk_freq_by_table,
1619         .print_clk_levels = navi10_print_clk_levels,
1620         .force_clk_levels = navi10_force_clk_levels,
1621         .populate_umd_state_clk = navi10_populate_umd_state_clk,
1622         .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency,
1623         .pre_display_config_changed = navi10_pre_display_config_changed,
1624         .display_config_changed = navi10_display_config_changed,
1625         .notify_smc_dispaly_config = navi10_notify_smc_dispaly_config,
1626         .force_dpm_limit_value = navi10_force_dpm_limit_value,
1627         .unforce_dpm_levels = navi10_unforce_dpm_levels,
1628         .is_dpm_running = navi10_is_dpm_running,
1629         .get_fan_speed_percent = navi10_get_fan_speed_percent,
1630         .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
1631         .get_power_profile_mode = navi10_get_power_profile_mode,
1632         .set_power_profile_mode = navi10_set_power_profile_mode,
1633         .get_profiling_clk_mask = navi10_get_profiling_clk_mask,
1634         .set_watermarks_table = navi10_set_watermarks_table,
1635         .read_sensor = navi10_read_sensor,
1636         .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
1637         .set_performance_level = navi10_set_performance_level,
1638         .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
1639         .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
1640         .get_power_limit = navi10_get_power_limit,
1641 };
1642 
1643 void navi10_set_ppt_funcs(struct smu_context *smu)
1644 {
1645         struct smu_table_context *smu_table = &smu->smu_table;
1646 
1647         smu->ppt_funcs = &navi10_ppt_funcs;
1648         smu_table->table_count = TABLE_COUNT;
1649 }

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