1e098bc96SEvan Quan /* 2e098bc96SEvan Quan * Copyright 2011 Advanced Micro Devices, Inc. 3e098bc96SEvan Quan * 4e098bc96SEvan Quan * Permission is hereby granted, free of charge, to any person obtaining a 5e098bc96SEvan Quan * copy of this software and associated documentation files (the "Software"), 6e098bc96SEvan Quan * to deal in the Software without restriction, including without limitation 7e098bc96SEvan Quan * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e098bc96SEvan Quan * and/or sell copies of the Software, and to permit persons to whom the 9e098bc96SEvan Quan * Software is furnished to do so, subject to the following conditions: 10e098bc96SEvan Quan * 11e098bc96SEvan Quan * The above copyright notice and this permission notice shall be included in 12e098bc96SEvan Quan * all copies or substantial portions of the Software. 13e098bc96SEvan Quan * 14e098bc96SEvan Quan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15e098bc96SEvan Quan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16e098bc96SEvan Quan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17e098bc96SEvan Quan * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18e098bc96SEvan Quan * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19e098bc96SEvan Quan * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20e098bc96SEvan Quan * OTHER DEALINGS IN THE SOFTWARE. 21e098bc96SEvan Quan * 22e098bc96SEvan Quan * Authors: Alex Deucher 23e098bc96SEvan Quan */ 24e098bc96SEvan Quan 25e098bc96SEvan Quan #include "amdgpu.h" 26e098bc96SEvan Quan #include "amdgpu_atombios.h" 27e098bc96SEvan Quan #include "amdgpu_i2c.h" 28e098bc96SEvan Quan #include "amdgpu_dpm.h" 29e098bc96SEvan Quan #include "atom.h" 30e098bc96SEvan Quan #include "amd_pcie.h" 31e098bc96SEvan Quan #include "amdgpu_display.h" 32e098bc96SEvan Quan #include "hwmgr.h" 33e098bc96SEvan Quan #include <linux/power_supply.h> 34ebfc2533SEvan Quan #include "amdgpu_smu.h" 35e098bc96SEvan Quan 36d4481576SEvan Quan #define amdgpu_dpm_enable_bapm(adev, e) \ 37d4481576SEvan Quan ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) 38d4481576SEvan Quan 39e098bc96SEvan Quan int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) 40e098bc96SEvan Quan { 41bc7d6c12SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 423712e7a4SEvan Quan int ret = 0; 43e098bc96SEvan Quan 443712e7a4SEvan Quan if (!pp_funcs->get_sclk) 453712e7a4SEvan Quan return 0; 463712e7a4SEvan Quan 473712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 483712e7a4SEvan Quan ret = pp_funcs->get_sclk((adev)->powerplay.pp_handle, 493712e7a4SEvan Quan low); 503712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 513712e7a4SEvan Quan 523712e7a4SEvan Quan return ret; 53e098bc96SEvan Quan } 54e098bc96SEvan Quan 55e098bc96SEvan Quan int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low) 56e098bc96SEvan Quan { 57bc7d6c12SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 583712e7a4SEvan Quan int ret = 0; 59e098bc96SEvan Quan 603712e7a4SEvan Quan if (!pp_funcs->get_mclk) 613712e7a4SEvan Quan return 0; 623712e7a4SEvan Quan 633712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 643712e7a4SEvan Quan ret = pp_funcs->get_mclk((adev)->powerplay.pp_handle, 653712e7a4SEvan Quan low); 663712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 673712e7a4SEvan Quan 683712e7a4SEvan Quan return ret; 69e098bc96SEvan Quan } 70e098bc96SEvan Quan 71e098bc96SEvan Quan int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate) 72e098bc96SEvan Quan { 73e098bc96SEvan Quan int ret = 0; 74bc7d6c12SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 756ee27ee2SEvan Quan enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; 766ee27ee2SEvan Quan 776ee27ee2SEvan Quan if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) { 786ee27ee2SEvan Quan dev_dbg(adev->dev, "IP block%d already in the target %s state!", 796ee27ee2SEvan Quan block_type, gate ? "gate" : "ungate"); 806ee27ee2SEvan Quan return 0; 816ee27ee2SEvan Quan } 82e098bc96SEvan Quan 833712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 843712e7a4SEvan Quan 85e098bc96SEvan Quan switch (block_type) { 86e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_UVD: 87e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_VCE: 88e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_GFX: 89e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_VCN: 90e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_SDMA: 91e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_JPEG: 92e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_GMC: 93e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_ACP: 943712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_powergating_by_smu) 95bc7d6c12SDarren Powell ret = (pp_funcs->set_powergating_by_smu( 96e098bc96SEvan Quan (adev)->powerplay.pp_handle, block_type, gate)); 97e098bc96SEvan Quan break; 98e098bc96SEvan Quan default: 99e098bc96SEvan Quan break; 100e098bc96SEvan Quan } 101e098bc96SEvan Quan 1026ee27ee2SEvan Quan if (!ret) 1036ee27ee2SEvan Quan atomic_set(&adev->pm.pwr_state[block_type], pwr_state); 1046ee27ee2SEvan Quan 1053712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 1063712e7a4SEvan Quan 107e098bc96SEvan Quan return ret; 108e098bc96SEvan Quan } 109e098bc96SEvan Quan 1107101ab97SHuang Rui int amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev) 1117101ab97SHuang Rui { 1127101ab97SHuang Rui struct smu_context *smu = adev->powerplay.pp_handle; 1137101ab97SHuang Rui int ret = -EOPNOTSUPP; 1147101ab97SHuang Rui 1157101ab97SHuang Rui mutex_lock(&adev->pm.mutex); 1167101ab97SHuang Rui ret = smu_set_gfx_power_up_by_imu(smu); 1177101ab97SHuang Rui mutex_unlock(&adev->pm.mutex); 1187101ab97SHuang Rui 1197101ab97SHuang Rui msleep(10); 1207101ab97SHuang Rui 1217101ab97SHuang Rui return ret; 1227101ab97SHuang Rui } 1237101ab97SHuang Rui 124e098bc96SEvan Quan int amdgpu_dpm_baco_enter(struct amdgpu_device *adev) 125e098bc96SEvan Quan { 126e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 127e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 128e098bc96SEvan Quan int ret = 0; 129e098bc96SEvan Quan 130e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->set_asic_baco_state) 131e098bc96SEvan Quan return -ENOENT; 132e098bc96SEvan Quan 1333712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1343712e7a4SEvan Quan 135e098bc96SEvan Quan /* enter BACO state */ 136e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 137e098bc96SEvan Quan 1383712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 1393712e7a4SEvan Quan 140e098bc96SEvan Quan return ret; 141e098bc96SEvan Quan } 142e098bc96SEvan Quan 143e098bc96SEvan Quan int amdgpu_dpm_baco_exit(struct amdgpu_device *adev) 144e098bc96SEvan Quan { 145e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 146e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 147e098bc96SEvan Quan int ret = 0; 148e098bc96SEvan Quan 149e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->set_asic_baco_state) 150e098bc96SEvan Quan return -ENOENT; 151e098bc96SEvan Quan 1523712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1533712e7a4SEvan Quan 154e098bc96SEvan Quan /* exit BACO state */ 155e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 156e098bc96SEvan Quan 1573712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 1583712e7a4SEvan Quan 159e098bc96SEvan Quan return ret; 160e098bc96SEvan Quan } 161e098bc96SEvan Quan 162e098bc96SEvan Quan int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, 163e098bc96SEvan Quan enum pp_mp1_state mp1_state) 164e098bc96SEvan Quan { 165e098bc96SEvan Quan int ret = 0; 166bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 167e098bc96SEvan Quan 168bab0f602SDarren Powell if (pp_funcs && pp_funcs->set_mp1_state) { 1693712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1703712e7a4SEvan Quan 171bab0f602SDarren Powell ret = pp_funcs->set_mp1_state( 172e098bc96SEvan Quan adev->powerplay.pp_handle, 173e098bc96SEvan Quan mp1_state); 1743712e7a4SEvan Quan 1753712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 176e098bc96SEvan Quan } 177e098bc96SEvan Quan 178e098bc96SEvan Quan return ret; 179e098bc96SEvan Quan } 180e098bc96SEvan Quan 181e098bc96SEvan Quan bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) 182e098bc96SEvan Quan { 183e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 184e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 185e098bc96SEvan Quan bool baco_cap; 1863712e7a4SEvan Quan int ret = 0; 187e098bc96SEvan Quan 188e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->get_asic_baco_capability) 189e098bc96SEvan Quan return false; 19034452ac3SAlex Deucher /* Don't use baco for reset in S3. 19134452ac3SAlex Deucher * This is a workaround for some platforms 19234452ac3SAlex Deucher * where entering BACO during suspend 19334452ac3SAlex Deucher * seems to cause reboots or hangs. 19434452ac3SAlex Deucher * This might be related to the fact that BACO controls 19534452ac3SAlex Deucher * power to the whole GPU including devices like audio and USB. 19634452ac3SAlex Deucher * Powering down/up everything may adversely affect these other 19734452ac3SAlex Deucher * devices. Needs more investigation. 19834452ac3SAlex Deucher */ 19934452ac3SAlex Deucher if (adev->in_s3) 20034452ac3SAlex Deucher return false; 201e098bc96SEvan Quan 2023712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 203e098bc96SEvan Quan 2043712e7a4SEvan Quan ret = pp_funcs->get_asic_baco_capability(pp_handle, 2053712e7a4SEvan Quan &baco_cap); 2063712e7a4SEvan Quan 2073712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2083712e7a4SEvan Quan 2093712e7a4SEvan Quan return ret ? false : baco_cap; 210e098bc96SEvan Quan } 211e098bc96SEvan Quan 212e098bc96SEvan Quan int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) 213e098bc96SEvan Quan { 214e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 215e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 2163712e7a4SEvan Quan int ret = 0; 217e098bc96SEvan Quan 218e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->asic_reset_mode_2) 219e098bc96SEvan Quan return -ENOENT; 220e098bc96SEvan Quan 2213712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2223712e7a4SEvan Quan 2233712e7a4SEvan Quan ret = pp_funcs->asic_reset_mode_2(pp_handle); 2243712e7a4SEvan Quan 2253712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2263712e7a4SEvan Quan 2273712e7a4SEvan Quan return ret; 228e098bc96SEvan Quan } 229e098bc96SEvan Quan 230230dd6bbSKenneth Feng int amdgpu_dpm_enable_gfx_features(struct amdgpu_device *adev) 231230dd6bbSKenneth Feng { 232230dd6bbSKenneth Feng const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 233230dd6bbSKenneth Feng void *pp_handle = adev->powerplay.pp_handle; 234230dd6bbSKenneth Feng int ret = 0; 235230dd6bbSKenneth Feng 236230dd6bbSKenneth Feng if (!pp_funcs || !pp_funcs->asic_reset_enable_gfx_features) 237230dd6bbSKenneth Feng return -ENOENT; 238230dd6bbSKenneth Feng 239230dd6bbSKenneth Feng mutex_lock(&adev->pm.mutex); 240230dd6bbSKenneth Feng 241230dd6bbSKenneth Feng ret = pp_funcs->asic_reset_enable_gfx_features(pp_handle); 242230dd6bbSKenneth Feng 243230dd6bbSKenneth Feng mutex_unlock(&adev->pm.mutex); 244230dd6bbSKenneth Feng 245230dd6bbSKenneth Feng return ret; 246230dd6bbSKenneth Feng } 247230dd6bbSKenneth Feng 248e098bc96SEvan Quan int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) 249e098bc96SEvan Quan { 250e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 251e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 252e098bc96SEvan Quan int ret = 0; 253e098bc96SEvan Quan 2549ab5001aSDarren Powell if (!pp_funcs || !pp_funcs->set_asic_baco_state) 255e098bc96SEvan Quan return -ENOENT; 256e098bc96SEvan Quan 2573712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2583712e7a4SEvan Quan 259e098bc96SEvan Quan /* enter BACO state */ 260e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 261e098bc96SEvan Quan if (ret) 2623712e7a4SEvan Quan goto out; 263e098bc96SEvan Quan 264e098bc96SEvan Quan /* exit BACO state */ 265e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 266e098bc96SEvan Quan 2673712e7a4SEvan Quan out: 2683712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2693712e7a4SEvan Quan return ret; 270e098bc96SEvan Quan } 271e098bc96SEvan Quan 272e098bc96SEvan Quan bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) 273e098bc96SEvan Quan { 274ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 2753712e7a4SEvan Quan bool support_mode1_reset = false; 276e098bc96SEvan Quan 2773712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 2783712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2793712e7a4SEvan Quan support_mode1_reset = smu_mode1_reset_is_support(smu); 2803712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2813712e7a4SEvan Quan } 282e098bc96SEvan Quan 2833712e7a4SEvan Quan return support_mode1_reset; 284e098bc96SEvan Quan } 285e098bc96SEvan Quan 286e098bc96SEvan Quan int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) 287e098bc96SEvan Quan { 288ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 2893712e7a4SEvan Quan int ret = -EOPNOTSUPP; 290e098bc96SEvan Quan 2913712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 2923712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2933712e7a4SEvan Quan ret = smu_mode1_reset(smu); 2943712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2953712e7a4SEvan Quan } 296e098bc96SEvan Quan 2973712e7a4SEvan Quan return ret; 298e098bc96SEvan Quan } 299e098bc96SEvan Quan 300e098bc96SEvan Quan int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, 301e098bc96SEvan Quan enum PP_SMC_POWER_PROFILE type, 302e098bc96SEvan Quan bool en) 303e098bc96SEvan Quan { 304bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 305e098bc96SEvan Quan int ret = 0; 306e098bc96SEvan Quan 3077cf7a392SJingwen Chen if (amdgpu_sriov_vf(adev)) 3087cf7a392SJingwen Chen return 0; 3097cf7a392SJingwen Chen 3103712e7a4SEvan Quan if (pp_funcs && pp_funcs->switch_power_profile) { 3113712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 312bab0f602SDarren Powell ret = pp_funcs->switch_power_profile( 313e098bc96SEvan Quan adev->powerplay.pp_handle, type, en); 3143712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3153712e7a4SEvan Quan } 316e098bc96SEvan Quan 317e098bc96SEvan Quan return ret; 318e098bc96SEvan Quan } 319e098bc96SEvan Quan 320e098bc96SEvan Quan int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, 321e098bc96SEvan Quan uint32_t pstate) 322e098bc96SEvan Quan { 323bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 324e098bc96SEvan Quan int ret = 0; 325e098bc96SEvan Quan 3263712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_xgmi_pstate) { 3273712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 328bab0f602SDarren Powell ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, 329e098bc96SEvan Quan pstate); 3303712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3313712e7a4SEvan Quan } 332e098bc96SEvan Quan 333e098bc96SEvan Quan return ret; 334e098bc96SEvan Quan } 335e098bc96SEvan Quan 336e098bc96SEvan Quan int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, 337e098bc96SEvan Quan uint32_t cstate) 338e098bc96SEvan Quan { 339e098bc96SEvan Quan int ret = 0; 340e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 341e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 342e098bc96SEvan Quan 3433712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_df_cstate) { 3443712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 345e098bc96SEvan Quan ret = pp_funcs->set_df_cstate(pp_handle, cstate); 3463712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3473712e7a4SEvan Quan } 348e098bc96SEvan Quan 349e098bc96SEvan Quan return ret; 350e098bc96SEvan Quan } 351e098bc96SEvan Quan 352e098bc96SEvan Quan int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) 353e098bc96SEvan Quan { 354ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 3553712e7a4SEvan Quan int ret = 0; 356e098bc96SEvan Quan 3573712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 3583712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 3593712e7a4SEvan Quan ret = smu_allow_xgmi_power_down(smu, en); 3603712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3613712e7a4SEvan Quan } 362e098bc96SEvan Quan 3633712e7a4SEvan Quan return ret; 364e098bc96SEvan Quan } 365e098bc96SEvan Quan 366e098bc96SEvan Quan int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) 367e098bc96SEvan Quan { 368e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 369e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 370e098bc96SEvan Quan adev->powerplay.pp_funcs; 371e098bc96SEvan Quan int ret = 0; 372e098bc96SEvan Quan 3733712e7a4SEvan Quan if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) { 3743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 375e098bc96SEvan Quan ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); 3763712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3773712e7a4SEvan Quan } 378e098bc96SEvan Quan 379e098bc96SEvan Quan return ret; 380e098bc96SEvan Quan } 381e098bc96SEvan Quan 382e098bc96SEvan Quan int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, 383e098bc96SEvan Quan uint32_t msg_id) 384e098bc96SEvan Quan { 385e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 386e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 387e098bc96SEvan Quan adev->powerplay.pp_funcs; 388e098bc96SEvan Quan int ret = 0; 389e098bc96SEvan Quan 3903712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_clockgating_by_smu) { 3913712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 392e098bc96SEvan Quan ret = pp_funcs->set_clockgating_by_smu(pp_handle, 393e098bc96SEvan Quan msg_id); 3943712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3953712e7a4SEvan Quan } 396e098bc96SEvan Quan 397e098bc96SEvan Quan return ret; 398e098bc96SEvan Quan } 399e098bc96SEvan Quan 400e098bc96SEvan Quan int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, 401e098bc96SEvan Quan bool acquire) 402e098bc96SEvan Quan { 403e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 404e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 405e098bc96SEvan Quan adev->powerplay.pp_funcs; 406e098bc96SEvan Quan int ret = -EOPNOTSUPP; 407e098bc96SEvan Quan 4083712e7a4SEvan Quan if (pp_funcs && pp_funcs->smu_i2c_bus_access) { 4093712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 410e098bc96SEvan Quan ret = pp_funcs->smu_i2c_bus_access(pp_handle, 411e098bc96SEvan Quan acquire); 4123712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 4133712e7a4SEvan Quan } 414e098bc96SEvan Quan 415e098bc96SEvan Quan return ret; 416e098bc96SEvan Quan } 417e098bc96SEvan Quan 418e098bc96SEvan Quan void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) 419e098bc96SEvan Quan { 420e098bc96SEvan Quan if (adev->pm.dpm_enabled) { 421e098bc96SEvan Quan mutex_lock(&adev->pm.mutex); 422e098bc96SEvan Quan if (power_supply_is_system_supplied() > 0) 423e098bc96SEvan Quan adev->pm.ac_power = true; 424e098bc96SEvan Quan else 425e098bc96SEvan Quan adev->pm.ac_power = false; 4263712e7a4SEvan Quan 427e098bc96SEvan Quan if (adev->powerplay.pp_funcs && 428e098bc96SEvan Quan adev->powerplay.pp_funcs->enable_bapm) 429e098bc96SEvan Quan amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); 430e098bc96SEvan Quan 431e098bc96SEvan Quan if (is_support_sw_smu(adev)) 432ebfc2533SEvan Quan smu_set_ac_dc(adev->powerplay.pp_handle); 4333712e7a4SEvan Quan 4343712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 435e098bc96SEvan Quan } 436e098bc96SEvan Quan } 437e098bc96SEvan Quan 438e098bc96SEvan Quan int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, 439e098bc96SEvan Quan void *data, uint32_t *size) 440e098bc96SEvan Quan { 4419ab5001aSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 4423712e7a4SEvan Quan int ret = -EINVAL; 443e098bc96SEvan Quan 444e098bc96SEvan Quan if (!data || !size) 445e098bc96SEvan Quan return -EINVAL; 446e098bc96SEvan Quan 4473712e7a4SEvan Quan if (pp_funcs && pp_funcs->read_sensor) { 4483712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4493712e7a4SEvan Quan ret = pp_funcs->read_sensor(adev->powerplay.pp_handle, 4503712e7a4SEvan Quan sensor, 4513712e7a4SEvan Quan data, 4523712e7a4SEvan Quan size); 4533712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 4543712e7a4SEvan Quan } 455e098bc96SEvan Quan 456e098bc96SEvan Quan return ret; 457e098bc96SEvan Quan } 458e098bc96SEvan Quan 459*c3ed0e72SKun Liu int amdgpu_dpm_get_apu_thermal_limit(struct amdgpu_device *adev, uint32_t *limit) 460*c3ed0e72SKun Liu { 461*c3ed0e72SKun Liu const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 462*c3ed0e72SKun Liu int ret = -EINVAL; 463*c3ed0e72SKun Liu 464*c3ed0e72SKun Liu if (pp_funcs && pp_funcs->get_apu_thermal_limit) { 465*c3ed0e72SKun Liu mutex_lock(&adev->pm.mutex); 466*c3ed0e72SKun Liu ret = pp_funcs->get_apu_thermal_limit(adev->powerplay.pp_handle, limit); 467*c3ed0e72SKun Liu mutex_unlock(&adev->pm.mutex); 468*c3ed0e72SKun Liu } 469*c3ed0e72SKun Liu 470*c3ed0e72SKun Liu return ret; 471*c3ed0e72SKun Liu } 472*c3ed0e72SKun Liu 473*c3ed0e72SKun Liu int amdgpu_dpm_set_apu_thermal_limit(struct amdgpu_device *adev, uint32_t limit) 474*c3ed0e72SKun Liu { 475*c3ed0e72SKun Liu const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 476*c3ed0e72SKun Liu int ret = -EINVAL; 477*c3ed0e72SKun Liu 478*c3ed0e72SKun Liu if (pp_funcs && pp_funcs->set_apu_thermal_limit) { 479*c3ed0e72SKun Liu mutex_lock(&adev->pm.mutex); 480*c3ed0e72SKun Liu ret = pp_funcs->set_apu_thermal_limit(adev->powerplay.pp_handle, limit); 481*c3ed0e72SKun Liu mutex_unlock(&adev->pm.mutex); 482*c3ed0e72SKun Liu } 483*c3ed0e72SKun Liu 484*c3ed0e72SKun Liu return ret; 485*c3ed0e72SKun Liu } 486*c3ed0e72SKun Liu 48784176663SEvan Quan void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) 488e098bc96SEvan Quan { 4896ddbd37fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 490a71849cdSEvan Quan int i; 491e098bc96SEvan Quan 492e098bc96SEvan Quan if (!adev->pm.dpm_enabled) 493e098bc96SEvan Quan return; 494e098bc96SEvan Quan 4956ddbd37fSEvan Quan if (!pp_funcs->pm_compute_clocks) 4966ddbd37fSEvan Quan return; 497e098bc96SEvan Quan 498a71849cdSEvan Quan if (adev->mode_info.num_crtc) 499a71849cdSEvan Quan amdgpu_display_bandwidth_update(adev); 500a71849cdSEvan Quan 501a71849cdSEvan Quan for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 502a71849cdSEvan Quan struct amdgpu_ring *ring = adev->rings[i]; 503a71849cdSEvan Quan if (ring && ring->sched.ready) 504a71849cdSEvan Quan amdgpu_fence_wait_empty(ring); 505a71849cdSEvan Quan } 506a71849cdSEvan Quan 5073712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5086ddbd37fSEvan Quan pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); 5093712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 510e098bc96SEvan Quan } 511e098bc96SEvan Quan 512e098bc96SEvan Quan void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) 513e098bc96SEvan Quan { 514e098bc96SEvan Quan int ret = 0; 515e098bc96SEvan Quan 516a71849cdSEvan Quan if (adev->family == AMDGPU_FAMILY_SI) { 517a71849cdSEvan Quan mutex_lock(&adev->pm.mutex); 518a71849cdSEvan Quan if (enable) { 519a71849cdSEvan Quan adev->pm.dpm.uvd_active = true; 520a71849cdSEvan Quan adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; 521a71849cdSEvan Quan } else { 522a71849cdSEvan Quan adev->pm.dpm.uvd_active = false; 523a71849cdSEvan Quan } 524a71849cdSEvan Quan mutex_unlock(&adev->pm.mutex); 525a71849cdSEvan Quan 526a71849cdSEvan Quan amdgpu_dpm_compute_clocks(adev); 527a71849cdSEvan Quan return; 528a71849cdSEvan Quan } 529a71849cdSEvan Quan 530e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 531e098bc96SEvan Quan if (ret) 532e098bc96SEvan Quan DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", 533e098bc96SEvan Quan enable ? "enable" : "disable", ret); 534e098bc96SEvan Quan } 535e098bc96SEvan Quan 536e098bc96SEvan Quan void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) 537e098bc96SEvan Quan { 538e098bc96SEvan Quan int ret = 0; 539e098bc96SEvan Quan 540a71849cdSEvan Quan if (adev->family == AMDGPU_FAMILY_SI) { 541a71849cdSEvan Quan mutex_lock(&adev->pm.mutex); 542a71849cdSEvan Quan if (enable) { 543a71849cdSEvan Quan adev->pm.dpm.vce_active = true; 544a71849cdSEvan Quan /* XXX select vce level based on ring/task */ 545a71849cdSEvan Quan adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; 546a71849cdSEvan Quan } else { 547a71849cdSEvan Quan adev->pm.dpm.vce_active = false; 548a71849cdSEvan Quan } 549a71849cdSEvan Quan mutex_unlock(&adev->pm.mutex); 550a71849cdSEvan Quan 551a71849cdSEvan Quan amdgpu_dpm_compute_clocks(adev); 552a71849cdSEvan Quan return; 553a71849cdSEvan Quan } 554a71849cdSEvan Quan 555e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); 556e098bc96SEvan Quan if (ret) 557e098bc96SEvan Quan DRM_ERROR("Dpm %s vce failed, ret = %d. \n", 558e098bc96SEvan Quan enable ? "enable" : "disable", ret); 559e098bc96SEvan Quan } 560e098bc96SEvan Quan 561e098bc96SEvan Quan void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) 562e098bc96SEvan Quan { 563e098bc96SEvan Quan int ret = 0; 564e098bc96SEvan Quan 565e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); 566e098bc96SEvan Quan if (ret) 567e098bc96SEvan Quan DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", 568e098bc96SEvan Quan enable ? "enable" : "disable", ret); 569e098bc96SEvan Quan } 570e098bc96SEvan Quan 571e098bc96SEvan Quan int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) 572e098bc96SEvan Quan { 5733712e7a4SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 5743712e7a4SEvan Quan int r = 0; 575e098bc96SEvan Quan 5761613f346SFlora Cui if (!pp_funcs || !pp_funcs->load_firmware) 5773712e7a4SEvan Quan return 0; 5783712e7a4SEvan Quan 5793712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5803712e7a4SEvan Quan r = pp_funcs->load_firmware(adev->powerplay.pp_handle); 581e098bc96SEvan Quan if (r) { 582e098bc96SEvan Quan pr_err("smu firmware loading failed\n"); 5833712e7a4SEvan Quan goto out; 584e098bc96SEvan Quan } 5852e4b2f7bSEvan Quan 5862e4b2f7bSEvan Quan if (smu_version) 587e098bc96SEvan Quan *smu_version = adev->pm.fw_version; 5882e4b2f7bSEvan Quan 5893712e7a4SEvan Quan out: 5903712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5913712e7a4SEvan Quan return r; 592e098bc96SEvan Quan } 593bc143d8bSEvan Quan 594bc143d8bSEvan Quan int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) 595bc143d8bSEvan Quan { 5963712e7a4SEvan Quan int ret = 0; 5973712e7a4SEvan Quan 5983712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 5993712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6003712e7a4SEvan Quan ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle, 6013712e7a4SEvan Quan enable); 6023712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6033712e7a4SEvan Quan } 6043712e7a4SEvan Quan 6053712e7a4SEvan Quan return ret; 606bc143d8bSEvan Quan } 607bc143d8bSEvan Quan 608bc143d8bSEvan Quan int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) 609bc143d8bSEvan Quan { 610ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6113712e7a4SEvan Quan int ret = 0; 612ebfc2533SEvan Quan 61393dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 61493dde6ccSStanley.Yang return -EOPNOTSUPP; 61593dde6ccSStanley.Yang 6163712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6173712e7a4SEvan Quan ret = smu_send_hbm_bad_pages_num(smu, size); 6183712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6193712e7a4SEvan Quan 6203712e7a4SEvan Quan return ret; 621bc143d8bSEvan Quan } 622bc143d8bSEvan Quan 623d510eccfSStanley.Yang int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size) 624d510eccfSStanley.Yang { 625d510eccfSStanley.Yang struct smu_context *smu = adev->powerplay.pp_handle; 626d510eccfSStanley.Yang int ret = 0; 627d510eccfSStanley.Yang 62893dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 62993dde6ccSStanley.Yang return -EOPNOTSUPP; 63093dde6ccSStanley.Yang 631d510eccfSStanley.Yang mutex_lock(&adev->pm.mutex); 632d510eccfSStanley.Yang ret = smu_send_hbm_bad_channel_flag(smu, size); 633d510eccfSStanley.Yang mutex_unlock(&adev->pm.mutex); 634d510eccfSStanley.Yang 635d510eccfSStanley.Yang return ret; 636d510eccfSStanley.Yang } 637d510eccfSStanley.Yang 638bc143d8bSEvan Quan int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, 639bc143d8bSEvan Quan enum pp_clock_type type, 640bc143d8bSEvan Quan uint32_t *min, 641bc143d8bSEvan Quan uint32_t *max) 642bc143d8bSEvan Quan { 6433712e7a4SEvan Quan int ret = 0; 6443712e7a4SEvan Quan 6453712e7a4SEvan Quan if (type != PP_SCLK) 6463712e7a4SEvan Quan return -EINVAL; 6473712e7a4SEvan Quan 648bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 649bc143d8bSEvan Quan return -EOPNOTSUPP; 650bc143d8bSEvan Quan 6513712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6523712e7a4SEvan Quan ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle, 6533712e7a4SEvan Quan SMU_SCLK, 6543712e7a4SEvan Quan min, 6553712e7a4SEvan Quan max); 6563712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6573712e7a4SEvan Quan 6583712e7a4SEvan Quan return ret; 659bc143d8bSEvan Quan } 660bc143d8bSEvan Quan 661bc143d8bSEvan Quan int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, 662bc143d8bSEvan Quan enum pp_clock_type type, 663bc143d8bSEvan Quan uint32_t min, 664bc143d8bSEvan Quan uint32_t max) 665bc143d8bSEvan Quan { 666ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6673712e7a4SEvan Quan int ret = 0; 6683712e7a4SEvan Quan 6693712e7a4SEvan Quan if (type != PP_SCLK) 6703712e7a4SEvan Quan return -EINVAL; 671ebfc2533SEvan Quan 672bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 673bc143d8bSEvan Quan return -EOPNOTSUPP; 674bc143d8bSEvan Quan 6753712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6763712e7a4SEvan Quan ret = smu_set_soft_freq_range(smu, 6773712e7a4SEvan Quan SMU_SCLK, 6783712e7a4SEvan Quan min, 6793712e7a4SEvan Quan max); 6803712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6813712e7a4SEvan Quan 6823712e7a4SEvan Quan return ret; 683bc143d8bSEvan Quan } 684bc143d8bSEvan Quan 68513f5dbd6SEvan Quan int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) 68613f5dbd6SEvan Quan { 687ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6883712e7a4SEvan Quan int ret = 0; 689ebfc2533SEvan Quan 69013f5dbd6SEvan Quan if (!is_support_sw_smu(adev)) 69113f5dbd6SEvan Quan return 0; 69213f5dbd6SEvan Quan 6933712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6943712e7a4SEvan Quan ret = smu_write_watermarks_table(smu); 6953712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6963712e7a4SEvan Quan 6973712e7a4SEvan Quan return ret; 69813f5dbd6SEvan Quan } 69913f5dbd6SEvan Quan 700bc143d8bSEvan Quan int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, 701bc143d8bSEvan Quan enum smu_event_type event, 702bc143d8bSEvan Quan uint64_t event_arg) 703bc143d8bSEvan Quan { 704ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 7053712e7a4SEvan Quan int ret = 0; 706ebfc2533SEvan Quan 707bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 708bc143d8bSEvan Quan return -EOPNOTSUPP; 709bc143d8bSEvan Quan 7103712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 7113712e7a4SEvan Quan ret = smu_wait_for_event(smu, event, event_arg); 7123712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 7133712e7a4SEvan Quan 7143712e7a4SEvan Quan return ret; 715bc143d8bSEvan Quan } 716bc143d8bSEvan Quan 7170ad7347aSAndré Almeida int amdgpu_dpm_set_residency_gfxoff(struct amdgpu_device *adev, bool value) 7180ad7347aSAndré Almeida { 7190ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 7200ad7347aSAndré Almeida int ret = 0; 7210ad7347aSAndré Almeida 7220ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 7230ad7347aSAndré Almeida return -EOPNOTSUPP; 7240ad7347aSAndré Almeida 7250ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 7260ad7347aSAndré Almeida ret = smu_set_residency_gfxoff(smu, value); 7270ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 7280ad7347aSAndré Almeida 7290ad7347aSAndré Almeida return ret; 7300ad7347aSAndré Almeida } 7310ad7347aSAndré Almeida 7320ad7347aSAndré Almeida int amdgpu_dpm_get_residency_gfxoff(struct amdgpu_device *adev, u32 *value) 7330ad7347aSAndré Almeida { 7340ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 7350ad7347aSAndré Almeida int ret = 0; 7360ad7347aSAndré Almeida 7370ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 7380ad7347aSAndré Almeida return -EOPNOTSUPP; 7390ad7347aSAndré Almeida 7400ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 7410ad7347aSAndré Almeida ret = smu_get_residency_gfxoff(smu, value); 7420ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 7430ad7347aSAndré Almeida 7440ad7347aSAndré Almeida return ret; 7450ad7347aSAndré Almeida } 7460ad7347aSAndré Almeida 7470ad7347aSAndré Almeida int amdgpu_dpm_get_entrycount_gfxoff(struct amdgpu_device *adev, u64 *value) 7480ad7347aSAndré Almeida { 7490ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 7500ad7347aSAndré Almeida int ret = 0; 7510ad7347aSAndré Almeida 7520ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 7530ad7347aSAndré Almeida return -EOPNOTSUPP; 7540ad7347aSAndré Almeida 7550ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 7560ad7347aSAndré Almeida ret = smu_get_entrycount_gfxoff(smu, value); 7570ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 7580ad7347aSAndré Almeida 7590ad7347aSAndré Almeida return ret; 7600ad7347aSAndré Almeida } 7610ad7347aSAndré Almeida 762bc143d8bSEvan Quan int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) 763bc143d8bSEvan Quan { 764ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 7653712e7a4SEvan Quan int ret = 0; 766ebfc2533SEvan Quan 767bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 768bc143d8bSEvan Quan return -EOPNOTSUPP; 769bc143d8bSEvan Quan 7703712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 7713712e7a4SEvan Quan ret = smu_get_status_gfxoff(smu, value); 7723712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 7733712e7a4SEvan Quan 7743712e7a4SEvan Quan return ret; 775bc143d8bSEvan Quan } 776bc143d8bSEvan Quan 777bc143d8bSEvan Quan uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) 778bc143d8bSEvan Quan { 779ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 780ebfc2533SEvan Quan 7813712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 7823712e7a4SEvan Quan return 0; 7833712e7a4SEvan Quan 784ebfc2533SEvan Quan return atomic64_read(&smu->throttle_int_counter); 785bc143d8bSEvan Quan } 786bc143d8bSEvan Quan 787bc143d8bSEvan Quan /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set 788bc143d8bSEvan Quan * @adev: amdgpu_device pointer 789bc143d8bSEvan Quan * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) 790bc143d8bSEvan Quan * 791bc143d8bSEvan Quan */ 792bc143d8bSEvan Quan void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, 793bc143d8bSEvan Quan enum gfx_change_state state) 794bc143d8bSEvan Quan { 795bc143d8bSEvan Quan mutex_lock(&adev->pm.mutex); 796bc143d8bSEvan Quan if (adev->powerplay.pp_funcs && 797bc143d8bSEvan Quan adev->powerplay.pp_funcs->gfx_state_change_set) 798bc143d8bSEvan Quan ((adev)->powerplay.pp_funcs->gfx_state_change_set( 799bc143d8bSEvan Quan (adev)->powerplay.pp_handle, state)); 800bc143d8bSEvan Quan mutex_unlock(&adev->pm.mutex); 801bc143d8bSEvan Quan } 802bc143d8bSEvan Quan 803bc143d8bSEvan Quan int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, 804bc143d8bSEvan Quan void *umc_ecc) 805bc143d8bSEvan Quan { 806ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 807a29d44aeSStanley.Yang int ret = 0; 808ebfc2533SEvan Quan 809bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 810bc143d8bSEvan Quan return -EOPNOTSUPP; 811bc143d8bSEvan Quan 812a29d44aeSStanley.Yang mutex_lock(&adev->pm.mutex); 813a29d44aeSStanley.Yang ret = smu_get_ecc_info(smu, umc_ecc); 814a29d44aeSStanley.Yang mutex_unlock(&adev->pm.mutex); 815a29d44aeSStanley.Yang 816a29d44aeSStanley.Yang return ret; 817bc143d8bSEvan Quan } 81879c65f3fSEvan Quan 81979c65f3fSEvan Quan struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, 82079c65f3fSEvan Quan uint32_t idx) 82179c65f3fSEvan Quan { 82279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 8233712e7a4SEvan Quan struct amd_vce_state *vstate = NULL; 82479c65f3fSEvan Quan 82579c65f3fSEvan Quan if (!pp_funcs->get_vce_clock_state) 82679c65f3fSEvan Quan return NULL; 82779c65f3fSEvan Quan 8283712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8293712e7a4SEvan Quan vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, 83079c65f3fSEvan Quan idx); 8313712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8323712e7a4SEvan Quan 8333712e7a4SEvan Quan return vstate; 83479c65f3fSEvan Quan } 83579c65f3fSEvan Quan 83679c65f3fSEvan Quan void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, 83779c65f3fSEvan Quan enum amd_pm_state_type *state) 83879c65f3fSEvan Quan { 83979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 84079c65f3fSEvan Quan 8413712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8423712e7a4SEvan Quan 84379c65f3fSEvan Quan if (!pp_funcs->get_current_power_state) { 84479c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 8453712e7a4SEvan Quan goto out; 84679c65f3fSEvan Quan } 84779c65f3fSEvan Quan 84879c65f3fSEvan Quan *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); 84979c65f3fSEvan Quan if (*state < POWER_STATE_TYPE_DEFAULT || 85079c65f3fSEvan Quan *state > POWER_STATE_TYPE_INTERNAL_3DPERF) 85179c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 8523712e7a4SEvan Quan 8533712e7a4SEvan Quan out: 8543712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 85579c65f3fSEvan Quan } 85679c65f3fSEvan Quan 85779c65f3fSEvan Quan void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, 85879c65f3fSEvan Quan enum amd_pm_state_type state) 85979c65f3fSEvan Quan { 8603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 86179c65f3fSEvan Quan adev->pm.dpm.user_state = state; 8623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 86379c65f3fSEvan Quan 86479c65f3fSEvan Quan if (is_support_sw_smu(adev)) 86579c65f3fSEvan Quan return; 86679c65f3fSEvan Quan 86779c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 86879c65f3fSEvan Quan AMD_PP_TASK_ENABLE_USER_STATE, 86979c65f3fSEvan Quan &state) == -EOPNOTSUPP) 87084176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 87179c65f3fSEvan Quan } 87279c65f3fSEvan Quan 87375513bf5SEvan Quan enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) 87479c65f3fSEvan Quan { 87579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 87679c65f3fSEvan Quan enum amd_dpm_forced_level level; 87779c65f3fSEvan Quan 87839dbde65SLijo Lazar if (!pp_funcs) 87939dbde65SLijo Lazar return AMD_DPM_FORCED_LEVEL_AUTO; 88039dbde65SLijo Lazar 88175513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 88279c65f3fSEvan Quan if (pp_funcs->get_performance_level) 88379c65f3fSEvan Quan level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); 88479c65f3fSEvan Quan else 88579c65f3fSEvan Quan level = adev->pm.dpm.forced_level; 8863712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 88779c65f3fSEvan Quan 88879c65f3fSEvan Quan return level; 88979c65f3fSEvan Quan } 89079c65f3fSEvan Quan 89179c65f3fSEvan Quan int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, 89279c65f3fSEvan Quan enum amd_dpm_forced_level level) 89379c65f3fSEvan Quan { 89479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 89554c73b51SAlex Deucher enum amd_dpm_forced_level current_level; 89654c73b51SAlex Deucher uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | 89754c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | 89854c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | 89954c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; 90079c65f3fSEvan Quan 901eea5c7b3SHuang Rui if (!pp_funcs || !pp_funcs->force_performance_level) 9023712e7a4SEvan Quan return 0; 9033712e7a4SEvan Quan 90475513bf5SEvan Quan if (adev->pm.dpm.thermal_active) 90575513bf5SEvan Quan return -EINVAL; 9063712e7a4SEvan Quan 90775513bf5SEvan Quan current_level = amdgpu_dpm_get_performance_level(adev); 90875513bf5SEvan Quan if (current_level == level) 90975513bf5SEvan Quan return 0; 91054c73b51SAlex Deucher 91154c73b51SAlex Deucher if (adev->asic_type == CHIP_RAVEN) { 91254c73b51SAlex Deucher if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { 91354c73b51SAlex Deucher if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && 91454c73b51SAlex Deucher level == AMD_DPM_FORCED_LEVEL_MANUAL) 91554c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, false); 91654c73b51SAlex Deucher else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && 91754c73b51SAlex Deucher level != AMD_DPM_FORCED_LEVEL_MANUAL) 91854c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, true); 91954c73b51SAlex Deucher } 92054c73b51SAlex Deucher } 92154c73b51SAlex Deucher 92254c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 92375513bf5SEvan Quan (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 92475513bf5SEvan Quan return -EINVAL; 92554c73b51SAlex Deucher 92654c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 92754c73b51SAlex Deucher (level & profile_mode_mask)) { 92854c73b51SAlex Deucher /* enter UMD Pstate */ 92954c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 93054c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 93154c73b51SAlex Deucher AMD_PG_STATE_UNGATE); 93254c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 93354c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 93454c73b51SAlex Deucher AMD_CG_STATE_UNGATE); 93554c73b51SAlex Deucher } else if ((current_level & profile_mode_mask) && 93654c73b51SAlex Deucher !(level & profile_mode_mask)) { 93754c73b51SAlex Deucher /* exit UMD Pstate */ 93854c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 93954c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 94054c73b51SAlex Deucher AMD_CG_STATE_GATE); 94154c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 94254c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 94354c73b51SAlex Deucher AMD_PG_STATE_GATE); 94454c73b51SAlex Deucher } 94554c73b51SAlex Deucher 94675513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 94779c65f3fSEvan Quan 94875513bf5SEvan Quan if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, 94975513bf5SEvan Quan level)) { 95075513bf5SEvan Quan mutex_unlock(&adev->pm.mutex); 95175513bf5SEvan Quan return -EINVAL; 95275513bf5SEvan Quan } 95375513bf5SEvan Quan 95479c65f3fSEvan Quan adev->pm.dpm.forced_level = level; 95579c65f3fSEvan Quan 9563712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9573712e7a4SEvan Quan 95875513bf5SEvan Quan return 0; 95979c65f3fSEvan Quan } 96079c65f3fSEvan Quan 96179c65f3fSEvan Quan int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, 96279c65f3fSEvan Quan struct pp_states_info *states) 96379c65f3fSEvan Quan { 96479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9653712e7a4SEvan Quan int ret = 0; 96679c65f3fSEvan Quan 96779c65f3fSEvan Quan if (!pp_funcs->get_pp_num_states) 96879c65f3fSEvan Quan return -EOPNOTSUPP; 96979c65f3fSEvan Quan 9703712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9713712e7a4SEvan Quan ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, 9723712e7a4SEvan Quan states); 9733712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9743712e7a4SEvan Quan 9753712e7a4SEvan Quan return ret; 97679c65f3fSEvan Quan } 97779c65f3fSEvan Quan 97879c65f3fSEvan Quan int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, 97979c65f3fSEvan Quan enum amd_pp_task task_id, 98079c65f3fSEvan Quan enum amd_pm_state_type *user_state) 98179c65f3fSEvan Quan { 98279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9833712e7a4SEvan Quan int ret = 0; 98479c65f3fSEvan Quan 98579c65f3fSEvan Quan if (!pp_funcs->dispatch_tasks) 98679c65f3fSEvan Quan return -EOPNOTSUPP; 98779c65f3fSEvan Quan 9883712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9893712e7a4SEvan Quan ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, 9903712e7a4SEvan Quan task_id, 9913712e7a4SEvan Quan user_state); 9923712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9933712e7a4SEvan Quan 9943712e7a4SEvan Quan return ret; 99579c65f3fSEvan Quan } 99679c65f3fSEvan Quan 99779c65f3fSEvan Quan int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) 99879c65f3fSEvan Quan { 99979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10003712e7a4SEvan Quan int ret = 0; 100179c65f3fSEvan Quan 100279c65f3fSEvan Quan if (!pp_funcs->get_pp_table) 100379c65f3fSEvan Quan return 0; 100479c65f3fSEvan Quan 10053712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10063712e7a4SEvan Quan ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, 10073712e7a4SEvan Quan table); 10083712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10093712e7a4SEvan Quan 10103712e7a4SEvan Quan return ret; 101179c65f3fSEvan Quan } 101279c65f3fSEvan Quan 101379c65f3fSEvan Quan int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, 101479c65f3fSEvan Quan uint32_t type, 101579c65f3fSEvan Quan long *input, 101679c65f3fSEvan Quan uint32_t size) 101779c65f3fSEvan Quan { 101879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10193712e7a4SEvan Quan int ret = 0; 102079c65f3fSEvan Quan 102179c65f3fSEvan Quan if (!pp_funcs->set_fine_grain_clk_vol) 102279c65f3fSEvan Quan return 0; 102379c65f3fSEvan Quan 10243712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10253712e7a4SEvan Quan ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, 102679c65f3fSEvan Quan type, 102779c65f3fSEvan Quan input, 102879c65f3fSEvan Quan size); 10293712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10303712e7a4SEvan Quan 10313712e7a4SEvan Quan return ret; 103279c65f3fSEvan Quan } 103379c65f3fSEvan Quan 103479c65f3fSEvan Quan int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, 103579c65f3fSEvan Quan uint32_t type, 103679c65f3fSEvan Quan long *input, 103779c65f3fSEvan Quan uint32_t size) 103879c65f3fSEvan Quan { 103979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10403712e7a4SEvan Quan int ret = 0; 104179c65f3fSEvan Quan 104279c65f3fSEvan Quan if (!pp_funcs->odn_edit_dpm_table) 104379c65f3fSEvan Quan return 0; 104479c65f3fSEvan Quan 10453712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10463712e7a4SEvan Quan ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, 104779c65f3fSEvan Quan type, 104879c65f3fSEvan Quan input, 104979c65f3fSEvan Quan size); 10503712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10513712e7a4SEvan Quan 10523712e7a4SEvan Quan return ret; 105379c65f3fSEvan Quan } 105479c65f3fSEvan Quan 105579c65f3fSEvan Quan int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, 105679c65f3fSEvan Quan enum pp_clock_type type, 105779c65f3fSEvan Quan char *buf) 105879c65f3fSEvan Quan { 105979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10603712e7a4SEvan Quan int ret = 0; 106179c65f3fSEvan Quan 106279c65f3fSEvan Quan if (!pp_funcs->print_clock_levels) 106379c65f3fSEvan Quan return 0; 106479c65f3fSEvan Quan 10653712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10663712e7a4SEvan Quan ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle, 106779c65f3fSEvan Quan type, 106879c65f3fSEvan Quan buf); 10693712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10703712e7a4SEvan Quan 10713712e7a4SEvan Quan return ret; 107279c65f3fSEvan Quan } 107379c65f3fSEvan Quan 10745d64f9bbSDarren Powell int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, 10755d64f9bbSDarren Powell enum pp_clock_type type, 10765d64f9bbSDarren Powell char *buf, 10775d64f9bbSDarren Powell int *offset) 10785d64f9bbSDarren Powell { 10795d64f9bbSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10805d64f9bbSDarren Powell int ret = 0; 10815d64f9bbSDarren Powell 10825d64f9bbSDarren Powell if (!pp_funcs->emit_clock_levels) 10835d64f9bbSDarren Powell return -ENOENT; 10845d64f9bbSDarren Powell 10855d64f9bbSDarren Powell mutex_lock(&adev->pm.mutex); 10865d64f9bbSDarren Powell ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle, 10875d64f9bbSDarren Powell type, 10885d64f9bbSDarren Powell buf, 10895d64f9bbSDarren Powell offset); 10905d64f9bbSDarren Powell mutex_unlock(&adev->pm.mutex); 10915d64f9bbSDarren Powell 10925d64f9bbSDarren Powell return ret; 10935d64f9bbSDarren Powell } 10945d64f9bbSDarren Powell 109579c65f3fSEvan Quan int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, 109679c65f3fSEvan Quan uint64_t ppfeature_masks) 109779c65f3fSEvan Quan { 109879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10993712e7a4SEvan Quan int ret = 0; 110079c65f3fSEvan Quan 110179c65f3fSEvan Quan if (!pp_funcs->set_ppfeature_status) 110279c65f3fSEvan Quan return 0; 110379c65f3fSEvan Quan 11043712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11053712e7a4SEvan Quan ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, 110679c65f3fSEvan Quan ppfeature_masks); 11073712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11083712e7a4SEvan Quan 11093712e7a4SEvan Quan return ret; 111079c65f3fSEvan Quan } 111179c65f3fSEvan Quan 111279c65f3fSEvan Quan int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) 111379c65f3fSEvan Quan { 111479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11153712e7a4SEvan Quan int ret = 0; 111679c65f3fSEvan Quan 111779c65f3fSEvan Quan if (!pp_funcs->get_ppfeature_status) 111879c65f3fSEvan Quan return 0; 111979c65f3fSEvan Quan 11203712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11213712e7a4SEvan Quan ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, 112279c65f3fSEvan Quan buf); 11233712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11243712e7a4SEvan Quan 11253712e7a4SEvan Quan return ret; 112679c65f3fSEvan Quan } 112779c65f3fSEvan Quan 112879c65f3fSEvan Quan int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, 112979c65f3fSEvan Quan enum pp_clock_type type, 113079c65f3fSEvan Quan uint32_t mask) 113179c65f3fSEvan Quan { 113279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11333712e7a4SEvan Quan int ret = 0; 113479c65f3fSEvan Quan 113579c65f3fSEvan Quan if (!pp_funcs->force_clock_level) 113679c65f3fSEvan Quan return 0; 113779c65f3fSEvan Quan 11383712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11393712e7a4SEvan Quan ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle, 114079c65f3fSEvan Quan type, 114179c65f3fSEvan Quan mask); 11423712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11433712e7a4SEvan Quan 11443712e7a4SEvan Quan return ret; 114579c65f3fSEvan Quan } 114679c65f3fSEvan Quan 114779c65f3fSEvan Quan int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) 114879c65f3fSEvan Quan { 114979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11503712e7a4SEvan Quan int ret = 0; 115179c65f3fSEvan Quan 115279c65f3fSEvan Quan if (!pp_funcs->get_sclk_od) 115379c65f3fSEvan Quan return 0; 115479c65f3fSEvan Quan 11553712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11563712e7a4SEvan Quan ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle); 11573712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11583712e7a4SEvan Quan 11593712e7a4SEvan Quan return ret; 116079c65f3fSEvan Quan } 116179c65f3fSEvan Quan 116279c65f3fSEvan Quan int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) 116379c65f3fSEvan Quan { 116479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 116579c65f3fSEvan Quan 116679c65f3fSEvan Quan if (is_support_sw_smu(adev)) 116779c65f3fSEvan Quan return 0; 116879c65f3fSEvan Quan 11693712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 117079c65f3fSEvan Quan if (pp_funcs->set_sclk_od) 117179c65f3fSEvan Quan pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); 11723712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 117379c65f3fSEvan Quan 117479c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 117579c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 117679c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 117779c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 117884176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 117979c65f3fSEvan Quan } 118079c65f3fSEvan Quan 118179c65f3fSEvan Quan return 0; 118279c65f3fSEvan Quan } 118379c65f3fSEvan Quan 118479c65f3fSEvan Quan int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) 118579c65f3fSEvan Quan { 118679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11873712e7a4SEvan Quan int ret = 0; 118879c65f3fSEvan Quan 118979c65f3fSEvan Quan if (!pp_funcs->get_mclk_od) 119079c65f3fSEvan Quan return 0; 119179c65f3fSEvan Quan 11923712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11933712e7a4SEvan Quan ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle); 11943712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11953712e7a4SEvan Quan 11963712e7a4SEvan Quan return ret; 119779c65f3fSEvan Quan } 119879c65f3fSEvan Quan 119979c65f3fSEvan Quan int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) 120079c65f3fSEvan Quan { 120179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 120279c65f3fSEvan Quan 120379c65f3fSEvan Quan if (is_support_sw_smu(adev)) 120479c65f3fSEvan Quan return 0; 120579c65f3fSEvan Quan 12063712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 120779c65f3fSEvan Quan if (pp_funcs->set_mclk_od) 120879c65f3fSEvan Quan pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); 12093712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 121079c65f3fSEvan Quan 121179c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 121279c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 121379c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 121479c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 121584176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 121679c65f3fSEvan Quan } 121779c65f3fSEvan Quan 121879c65f3fSEvan Quan return 0; 121979c65f3fSEvan Quan } 122079c65f3fSEvan Quan 122179c65f3fSEvan Quan int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, 122279c65f3fSEvan Quan char *buf) 122379c65f3fSEvan Quan { 122479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12253712e7a4SEvan Quan int ret = 0; 122679c65f3fSEvan Quan 122779c65f3fSEvan Quan if (!pp_funcs->get_power_profile_mode) 122879c65f3fSEvan Quan return -EOPNOTSUPP; 122979c65f3fSEvan Quan 12303712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12313712e7a4SEvan Quan ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, 123279c65f3fSEvan Quan buf); 12333712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12343712e7a4SEvan Quan 12353712e7a4SEvan Quan return ret; 123679c65f3fSEvan Quan } 123779c65f3fSEvan Quan 123879c65f3fSEvan Quan int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, 123979c65f3fSEvan Quan long *input, uint32_t size) 124079c65f3fSEvan Quan { 124179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12423712e7a4SEvan Quan int ret = 0; 124379c65f3fSEvan Quan 124479c65f3fSEvan Quan if (!pp_funcs->set_power_profile_mode) 124579c65f3fSEvan Quan return 0; 124679c65f3fSEvan Quan 12473712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12483712e7a4SEvan Quan ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, 124979c65f3fSEvan Quan input, 125079c65f3fSEvan Quan size); 12513712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12523712e7a4SEvan Quan 12533712e7a4SEvan Quan return ret; 125479c65f3fSEvan Quan } 125579c65f3fSEvan Quan 125679c65f3fSEvan Quan int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) 125779c65f3fSEvan Quan { 125879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12593712e7a4SEvan Quan int ret = 0; 126079c65f3fSEvan Quan 126179c65f3fSEvan Quan if (!pp_funcs->get_gpu_metrics) 126279c65f3fSEvan Quan return 0; 126379c65f3fSEvan Quan 12643712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12653712e7a4SEvan Quan ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, 12663712e7a4SEvan Quan table); 12673712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12683712e7a4SEvan Quan 12693712e7a4SEvan Quan return ret; 127079c65f3fSEvan Quan } 127179c65f3fSEvan Quan 127279c65f3fSEvan Quan int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, 127379c65f3fSEvan Quan uint32_t *fan_mode) 127479c65f3fSEvan Quan { 127579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1276685fae24SEvan Quan int ret = 0; 127779c65f3fSEvan Quan 127879c65f3fSEvan Quan if (!pp_funcs->get_fan_control_mode) 127979c65f3fSEvan Quan return -EOPNOTSUPP; 128079c65f3fSEvan Quan 12813712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1282685fae24SEvan Quan ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, 1283685fae24SEvan Quan fan_mode); 12843712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 128579c65f3fSEvan Quan 1286685fae24SEvan Quan return ret; 128779c65f3fSEvan Quan } 128879c65f3fSEvan Quan 128979c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, 129079c65f3fSEvan Quan uint32_t speed) 129179c65f3fSEvan Quan { 129279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12933712e7a4SEvan Quan int ret = 0; 129479c65f3fSEvan Quan 129579c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_pwm) 1296685fae24SEvan Quan return -EOPNOTSUPP; 129779c65f3fSEvan Quan 12983712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12993712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, 13003712e7a4SEvan Quan speed); 13013712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13023712e7a4SEvan Quan 13033712e7a4SEvan Quan return ret; 130479c65f3fSEvan Quan } 130579c65f3fSEvan Quan 130679c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, 130779c65f3fSEvan Quan uint32_t *speed) 130879c65f3fSEvan Quan { 130979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13103712e7a4SEvan Quan int ret = 0; 131179c65f3fSEvan Quan 131279c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_pwm) 1313685fae24SEvan Quan return -EOPNOTSUPP; 131479c65f3fSEvan Quan 13153712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13163712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, 13173712e7a4SEvan Quan speed); 13183712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13193712e7a4SEvan Quan 13203712e7a4SEvan Quan return ret; 132179c65f3fSEvan Quan } 132279c65f3fSEvan Quan 132379c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, 132479c65f3fSEvan Quan uint32_t *speed) 132579c65f3fSEvan Quan { 132679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13273712e7a4SEvan Quan int ret = 0; 132879c65f3fSEvan Quan 132979c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_rpm) 1330685fae24SEvan Quan return -EOPNOTSUPP; 133179c65f3fSEvan Quan 13323712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13333712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, 13343712e7a4SEvan Quan speed); 13353712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13363712e7a4SEvan Quan 13373712e7a4SEvan Quan return ret; 133879c65f3fSEvan Quan } 133979c65f3fSEvan Quan 134079c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, 134179c65f3fSEvan Quan uint32_t speed) 134279c65f3fSEvan Quan { 134379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13443712e7a4SEvan Quan int ret = 0; 134579c65f3fSEvan Quan 134679c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_rpm) 1347685fae24SEvan Quan return -EOPNOTSUPP; 134879c65f3fSEvan Quan 13493712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13503712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, 13513712e7a4SEvan Quan speed); 13523712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13533712e7a4SEvan Quan 13543712e7a4SEvan Quan return ret; 135579c65f3fSEvan Quan } 135679c65f3fSEvan Quan 135779c65f3fSEvan Quan int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, 135879c65f3fSEvan Quan uint32_t mode) 135979c65f3fSEvan Quan { 136079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1361685fae24SEvan Quan int ret = 0; 136279c65f3fSEvan Quan 136379c65f3fSEvan Quan if (!pp_funcs->set_fan_control_mode) 136479c65f3fSEvan Quan return -EOPNOTSUPP; 136579c65f3fSEvan Quan 13663712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1367685fae24SEvan Quan ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, 13683712e7a4SEvan Quan mode); 13693712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 137079c65f3fSEvan Quan 1371685fae24SEvan Quan return ret; 137279c65f3fSEvan Quan } 137379c65f3fSEvan Quan 137479c65f3fSEvan Quan int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, 137579c65f3fSEvan Quan uint32_t *limit, 137679c65f3fSEvan Quan enum pp_power_limit_level pp_limit_level, 137779c65f3fSEvan Quan enum pp_power_type power_type) 137879c65f3fSEvan Quan { 137979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13803712e7a4SEvan Quan int ret = 0; 138179c65f3fSEvan Quan 138279c65f3fSEvan Quan if (!pp_funcs->get_power_limit) 138379c65f3fSEvan Quan return -ENODATA; 138479c65f3fSEvan Quan 13853712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13863712e7a4SEvan Quan ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle, 138779c65f3fSEvan Quan limit, 138879c65f3fSEvan Quan pp_limit_level, 138979c65f3fSEvan Quan power_type); 13903712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13913712e7a4SEvan Quan 13923712e7a4SEvan Quan return ret; 139379c65f3fSEvan Quan } 139479c65f3fSEvan Quan 139579c65f3fSEvan Quan int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, 139679c65f3fSEvan Quan uint32_t limit) 139779c65f3fSEvan Quan { 139879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13993712e7a4SEvan Quan int ret = 0; 140079c65f3fSEvan Quan 140179c65f3fSEvan Quan if (!pp_funcs->set_power_limit) 140279c65f3fSEvan Quan return -EINVAL; 140379c65f3fSEvan Quan 14043712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14053712e7a4SEvan Quan ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle, 14063712e7a4SEvan Quan limit); 14073712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14083712e7a4SEvan Quan 14093712e7a4SEvan Quan return ret; 141079c65f3fSEvan Quan } 141179c65f3fSEvan Quan 141279c65f3fSEvan Quan int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) 141379c65f3fSEvan Quan { 14143712e7a4SEvan Quan bool cclk_dpm_supported = false; 14153712e7a4SEvan Quan 141679c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 141779c65f3fSEvan Quan return false; 141879c65f3fSEvan Quan 14193712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14203712e7a4SEvan Quan cclk_dpm_supported = is_support_cclk_dpm(adev); 14213712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14223712e7a4SEvan Quan 14233712e7a4SEvan Quan return (int)cclk_dpm_supported; 142479c65f3fSEvan Quan } 142579c65f3fSEvan Quan 142679c65f3fSEvan Quan int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, 142779c65f3fSEvan Quan struct seq_file *m) 142879c65f3fSEvan Quan { 142979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 143079c65f3fSEvan Quan 143179c65f3fSEvan Quan if (!pp_funcs->debugfs_print_current_performance_level) 143279c65f3fSEvan Quan return -EOPNOTSUPP; 143379c65f3fSEvan Quan 14343712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 143579c65f3fSEvan Quan pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, 143679c65f3fSEvan Quan m); 14373712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 143879c65f3fSEvan Quan 143979c65f3fSEvan Quan return 0; 144079c65f3fSEvan Quan } 144179c65f3fSEvan Quan 144279c65f3fSEvan Quan int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, 144379c65f3fSEvan Quan void **addr, 144479c65f3fSEvan Quan size_t *size) 144579c65f3fSEvan Quan { 144679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14473712e7a4SEvan Quan int ret = 0; 144879c65f3fSEvan Quan 144979c65f3fSEvan Quan if (!pp_funcs->get_smu_prv_buf_details) 145079c65f3fSEvan Quan return -ENOSYS; 145179c65f3fSEvan Quan 14523712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14533712e7a4SEvan Quan ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, 145479c65f3fSEvan Quan addr, 145579c65f3fSEvan Quan size); 14563712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14573712e7a4SEvan Quan 14583712e7a4SEvan Quan return ret; 145979c65f3fSEvan Quan } 146079c65f3fSEvan Quan 146179c65f3fSEvan Quan int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) 146279c65f3fSEvan Quan { 146379c65f3fSEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; 1464ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 146579c65f3fSEvan Quan 1466ebfc2533SEvan Quan if ((is_support_sw_smu(adev) && smu->od_enabled) || 1467ebfc2533SEvan Quan (is_support_sw_smu(adev) && smu->is_apu) || 146879c65f3fSEvan Quan (!is_support_sw_smu(adev) && hwmgr->od_enabled)) 146979c65f3fSEvan Quan return true; 147079c65f3fSEvan Quan 147179c65f3fSEvan Quan return false; 147279c65f3fSEvan Quan } 147379c65f3fSEvan Quan 147479c65f3fSEvan Quan int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, 147579c65f3fSEvan Quan const char *buf, 147679c65f3fSEvan Quan size_t size) 147779c65f3fSEvan Quan { 147879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14793712e7a4SEvan Quan int ret = 0; 148079c65f3fSEvan Quan 148179c65f3fSEvan Quan if (!pp_funcs->set_pp_table) 148279c65f3fSEvan Quan return -EOPNOTSUPP; 148379c65f3fSEvan Quan 14843712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14853712e7a4SEvan Quan ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle, 148679c65f3fSEvan Quan buf, 148779c65f3fSEvan Quan size); 14883712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14893712e7a4SEvan Quan 14903712e7a4SEvan Quan return ret; 149179c65f3fSEvan Quan } 149279c65f3fSEvan Quan 149379c65f3fSEvan Quan int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) 149479c65f3fSEvan Quan { 1495ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 1496ebfc2533SEvan Quan 14973712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 14983712e7a4SEvan Quan return INT_MAX; 14993712e7a4SEvan Quan 1500ebfc2533SEvan Quan return smu->cpu_core_num; 150179c65f3fSEvan Quan } 150279c65f3fSEvan Quan 150379c65f3fSEvan Quan void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) 150479c65f3fSEvan Quan { 150579c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 150679c65f3fSEvan Quan return; 150779c65f3fSEvan Quan 150879c65f3fSEvan Quan amdgpu_smu_stb_debug_fs_init(adev); 150979c65f3fSEvan Quan } 151013f5dbd6SEvan Quan 151113f5dbd6SEvan Quan int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, 151213f5dbd6SEvan Quan const struct amd_pp_display_configuration *input) 151313f5dbd6SEvan Quan { 151413f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15153712e7a4SEvan Quan int ret = 0; 151613f5dbd6SEvan Quan 151713f5dbd6SEvan Quan if (!pp_funcs->display_configuration_change) 151813f5dbd6SEvan Quan return 0; 151913f5dbd6SEvan Quan 15203712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15213712e7a4SEvan Quan ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle, 152213f5dbd6SEvan Quan input); 15233712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15243712e7a4SEvan Quan 15253712e7a4SEvan Quan return ret; 152613f5dbd6SEvan Quan } 152713f5dbd6SEvan Quan 152813f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, 152913f5dbd6SEvan Quan enum amd_pp_clock_type type, 153013f5dbd6SEvan Quan struct amd_pp_clocks *clocks) 153113f5dbd6SEvan Quan { 153213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15333712e7a4SEvan Quan int ret = 0; 153413f5dbd6SEvan Quan 153513f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type) 153613f5dbd6SEvan Quan return 0; 153713f5dbd6SEvan Quan 15383712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15393712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, 154013f5dbd6SEvan Quan type, 154113f5dbd6SEvan Quan clocks); 15423712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15433712e7a4SEvan Quan 15443712e7a4SEvan Quan return ret; 154513f5dbd6SEvan Quan } 154613f5dbd6SEvan Quan 154713f5dbd6SEvan Quan int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, 154813f5dbd6SEvan Quan struct amd_pp_simple_clock_info *clocks) 154913f5dbd6SEvan Quan { 155013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15513712e7a4SEvan Quan int ret = 0; 155213f5dbd6SEvan Quan 155313f5dbd6SEvan Quan if (!pp_funcs->get_display_mode_validation_clocks) 155413f5dbd6SEvan Quan return 0; 155513f5dbd6SEvan Quan 15563712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15573712e7a4SEvan Quan ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, 155813f5dbd6SEvan Quan clocks); 15593712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15603712e7a4SEvan Quan 15613712e7a4SEvan Quan return ret; 156213f5dbd6SEvan Quan } 156313f5dbd6SEvan Quan 156413f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, 156513f5dbd6SEvan Quan enum amd_pp_clock_type type, 156613f5dbd6SEvan Quan struct pp_clock_levels_with_latency *clocks) 156713f5dbd6SEvan Quan { 156813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15693712e7a4SEvan Quan int ret = 0; 157013f5dbd6SEvan Quan 157113f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_latency) 157213f5dbd6SEvan Quan return 0; 157313f5dbd6SEvan Quan 15743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15753712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, 157613f5dbd6SEvan Quan type, 157713f5dbd6SEvan Quan clocks); 15783712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15793712e7a4SEvan Quan 15803712e7a4SEvan Quan return ret; 158113f5dbd6SEvan Quan } 158213f5dbd6SEvan Quan 158313f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, 158413f5dbd6SEvan Quan enum amd_pp_clock_type type, 158513f5dbd6SEvan Quan struct pp_clock_levels_with_voltage *clocks) 158613f5dbd6SEvan Quan { 158713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15883712e7a4SEvan Quan int ret = 0; 158913f5dbd6SEvan Quan 159013f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_voltage) 159113f5dbd6SEvan Quan return 0; 159213f5dbd6SEvan Quan 15933712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15943712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, 159513f5dbd6SEvan Quan type, 159613f5dbd6SEvan Quan clocks); 15973712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15983712e7a4SEvan Quan 15993712e7a4SEvan Quan return ret; 160013f5dbd6SEvan Quan } 160113f5dbd6SEvan Quan 160213f5dbd6SEvan Quan int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, 160313f5dbd6SEvan Quan void *clock_ranges) 160413f5dbd6SEvan Quan { 160513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16063712e7a4SEvan Quan int ret = 0; 160713f5dbd6SEvan Quan 160813f5dbd6SEvan Quan if (!pp_funcs->set_watermarks_for_clocks_ranges) 160913f5dbd6SEvan Quan return -EOPNOTSUPP; 161013f5dbd6SEvan Quan 16113712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16123712e7a4SEvan Quan ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, 161313f5dbd6SEvan Quan clock_ranges); 16143712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16153712e7a4SEvan Quan 16163712e7a4SEvan Quan return ret; 161713f5dbd6SEvan Quan } 161813f5dbd6SEvan Quan 161913f5dbd6SEvan Quan int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, 162013f5dbd6SEvan Quan struct pp_display_clock_request *clock) 162113f5dbd6SEvan Quan { 162213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16233712e7a4SEvan Quan int ret = 0; 162413f5dbd6SEvan Quan 162513f5dbd6SEvan Quan if (!pp_funcs->display_clock_voltage_request) 162613f5dbd6SEvan Quan return -EOPNOTSUPP; 162713f5dbd6SEvan Quan 16283712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16293712e7a4SEvan Quan ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, 163013f5dbd6SEvan Quan clock); 16313712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16323712e7a4SEvan Quan 16333712e7a4SEvan Quan return ret; 163413f5dbd6SEvan Quan } 163513f5dbd6SEvan Quan 163613f5dbd6SEvan Quan int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, 163713f5dbd6SEvan Quan struct amd_pp_clock_info *clocks) 163813f5dbd6SEvan Quan { 163913f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16403712e7a4SEvan Quan int ret = 0; 164113f5dbd6SEvan Quan 164213f5dbd6SEvan Quan if (!pp_funcs->get_current_clocks) 164313f5dbd6SEvan Quan return -EOPNOTSUPP; 164413f5dbd6SEvan Quan 16453712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16463712e7a4SEvan Quan ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle, 164713f5dbd6SEvan Quan clocks); 16483712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16493712e7a4SEvan Quan 16503712e7a4SEvan Quan return ret; 165113f5dbd6SEvan Quan } 165213f5dbd6SEvan Quan 165313f5dbd6SEvan Quan void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) 165413f5dbd6SEvan Quan { 165513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 165613f5dbd6SEvan Quan 165713f5dbd6SEvan Quan if (!pp_funcs->notify_smu_enable_pwe) 165813f5dbd6SEvan Quan return; 165913f5dbd6SEvan Quan 16603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 166113f5dbd6SEvan Quan pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); 16623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 166313f5dbd6SEvan Quan } 166413f5dbd6SEvan Quan 166513f5dbd6SEvan Quan int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, 166613f5dbd6SEvan Quan uint32_t count) 166713f5dbd6SEvan Quan { 166813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16693712e7a4SEvan Quan int ret = 0; 167013f5dbd6SEvan Quan 167113f5dbd6SEvan Quan if (!pp_funcs->set_active_display_count) 167213f5dbd6SEvan Quan return -EOPNOTSUPP; 167313f5dbd6SEvan Quan 16743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16753712e7a4SEvan Quan ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle, 167613f5dbd6SEvan Quan count); 16773712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16783712e7a4SEvan Quan 16793712e7a4SEvan Quan return ret; 168013f5dbd6SEvan Quan } 168113f5dbd6SEvan Quan 168213f5dbd6SEvan Quan int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, 168313f5dbd6SEvan Quan uint32_t clock) 168413f5dbd6SEvan Quan { 168513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16863712e7a4SEvan Quan int ret = 0; 168713f5dbd6SEvan Quan 168813f5dbd6SEvan Quan if (!pp_funcs->set_min_deep_sleep_dcefclk) 168913f5dbd6SEvan Quan return -EOPNOTSUPP; 169013f5dbd6SEvan Quan 16913712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16923712e7a4SEvan Quan ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, 169313f5dbd6SEvan Quan clock); 16943712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16953712e7a4SEvan Quan 16963712e7a4SEvan Quan return ret; 169713f5dbd6SEvan Quan } 169813f5dbd6SEvan Quan 169913f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, 170013f5dbd6SEvan Quan uint32_t clock) 170113f5dbd6SEvan Quan { 170213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 170313f5dbd6SEvan Quan 170413f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_dcefclk_by_freq) 170513f5dbd6SEvan Quan return; 170613f5dbd6SEvan Quan 17073712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 170813f5dbd6SEvan Quan pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, 170913f5dbd6SEvan Quan clock); 17103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 171113f5dbd6SEvan Quan } 171213f5dbd6SEvan Quan 171313f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, 171413f5dbd6SEvan Quan uint32_t clock) 171513f5dbd6SEvan Quan { 171613f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 171713f5dbd6SEvan Quan 171813f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_fclk_by_freq) 171913f5dbd6SEvan Quan return; 172013f5dbd6SEvan Quan 17213712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 172213f5dbd6SEvan Quan pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, 172313f5dbd6SEvan Quan clock); 17243712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 172513f5dbd6SEvan Quan } 172613f5dbd6SEvan Quan 172713f5dbd6SEvan Quan int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, 172813f5dbd6SEvan Quan bool disable_memory_clock_switch) 172913f5dbd6SEvan Quan { 173013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17313712e7a4SEvan Quan int ret = 0; 173213f5dbd6SEvan Quan 173313f5dbd6SEvan Quan if (!pp_funcs->display_disable_memory_clock_switch) 173413f5dbd6SEvan Quan return 0; 173513f5dbd6SEvan Quan 17363712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17373712e7a4SEvan Quan ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, 173813f5dbd6SEvan Quan disable_memory_clock_switch); 17393712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17403712e7a4SEvan Quan 17413712e7a4SEvan Quan return ret; 174213f5dbd6SEvan Quan } 174313f5dbd6SEvan Quan 174413f5dbd6SEvan Quan int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, 174513f5dbd6SEvan Quan struct pp_smu_nv_clock_table *max_clocks) 174613f5dbd6SEvan Quan { 174713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17483712e7a4SEvan Quan int ret = 0; 174913f5dbd6SEvan Quan 175013f5dbd6SEvan Quan if (!pp_funcs->get_max_sustainable_clocks_by_dc) 175113f5dbd6SEvan Quan return -EOPNOTSUPP; 175213f5dbd6SEvan Quan 17533712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17543712e7a4SEvan Quan ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, 175513f5dbd6SEvan Quan max_clocks); 17563712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17573712e7a4SEvan Quan 17583712e7a4SEvan Quan return ret; 175913f5dbd6SEvan Quan } 176013f5dbd6SEvan Quan 176113f5dbd6SEvan Quan enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, 176213f5dbd6SEvan Quan unsigned int *clock_values_in_khz, 176313f5dbd6SEvan Quan unsigned int *num_states) 176413f5dbd6SEvan Quan { 176513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17663712e7a4SEvan Quan int ret = 0; 176713f5dbd6SEvan Quan 176813f5dbd6SEvan Quan if (!pp_funcs->get_uclk_dpm_states) 176913f5dbd6SEvan Quan return -EOPNOTSUPP; 177013f5dbd6SEvan Quan 17713712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17723712e7a4SEvan Quan ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, 177313f5dbd6SEvan Quan clock_values_in_khz, 177413f5dbd6SEvan Quan num_states); 17753712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17763712e7a4SEvan Quan 17773712e7a4SEvan Quan return ret; 177813f5dbd6SEvan Quan } 177913f5dbd6SEvan Quan 178013f5dbd6SEvan Quan int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, 178113f5dbd6SEvan Quan struct dpm_clocks *clock_table) 178213f5dbd6SEvan Quan { 178313f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17843712e7a4SEvan Quan int ret = 0; 178513f5dbd6SEvan Quan 178613f5dbd6SEvan Quan if (!pp_funcs->get_dpm_clock_table) 178713f5dbd6SEvan Quan return -EOPNOTSUPP; 178813f5dbd6SEvan Quan 17893712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17903712e7a4SEvan Quan ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, 179113f5dbd6SEvan Quan clock_table); 17923712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17933712e7a4SEvan Quan 17943712e7a4SEvan Quan return ret; 179513f5dbd6SEvan Quan } 1796