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 230*230dd6bbSKenneth Feng int amdgpu_dpm_enable_gfx_features(struct amdgpu_device *adev) 231*230dd6bbSKenneth Feng { 232*230dd6bbSKenneth Feng const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 233*230dd6bbSKenneth Feng void *pp_handle = adev->powerplay.pp_handle; 234*230dd6bbSKenneth Feng int ret = 0; 235*230dd6bbSKenneth Feng 236*230dd6bbSKenneth Feng if (!pp_funcs || !pp_funcs->asic_reset_enable_gfx_features) 237*230dd6bbSKenneth Feng return -ENOENT; 238*230dd6bbSKenneth Feng 239*230dd6bbSKenneth Feng mutex_lock(&adev->pm.mutex); 240*230dd6bbSKenneth Feng 241*230dd6bbSKenneth Feng ret = pp_funcs->asic_reset_enable_gfx_features(pp_handle); 242*230dd6bbSKenneth Feng 243*230dd6bbSKenneth Feng mutex_unlock(&adev->pm.mutex); 244*230dd6bbSKenneth Feng 245*230dd6bbSKenneth Feng return ret; 246*230dd6bbSKenneth Feng } 247*230dd6bbSKenneth 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 45984176663SEvan Quan void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) 460e098bc96SEvan Quan { 4616ddbd37fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 462a71849cdSEvan Quan int i; 463e098bc96SEvan Quan 464e098bc96SEvan Quan if (!adev->pm.dpm_enabled) 465e098bc96SEvan Quan return; 466e098bc96SEvan Quan 4676ddbd37fSEvan Quan if (!pp_funcs->pm_compute_clocks) 4686ddbd37fSEvan Quan return; 469e098bc96SEvan Quan 470a71849cdSEvan Quan if (adev->mode_info.num_crtc) 471a71849cdSEvan Quan amdgpu_display_bandwidth_update(adev); 472a71849cdSEvan Quan 473a71849cdSEvan Quan for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 474a71849cdSEvan Quan struct amdgpu_ring *ring = adev->rings[i]; 475a71849cdSEvan Quan if (ring && ring->sched.ready) 476a71849cdSEvan Quan amdgpu_fence_wait_empty(ring); 477a71849cdSEvan Quan } 478a71849cdSEvan Quan 4793712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4806ddbd37fSEvan Quan pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); 4813712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 482e098bc96SEvan Quan } 483e098bc96SEvan Quan 484e098bc96SEvan Quan void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) 485e098bc96SEvan Quan { 486e098bc96SEvan Quan int ret = 0; 487e098bc96SEvan Quan 488a71849cdSEvan Quan if (adev->family == AMDGPU_FAMILY_SI) { 489a71849cdSEvan Quan mutex_lock(&adev->pm.mutex); 490a71849cdSEvan Quan if (enable) { 491a71849cdSEvan Quan adev->pm.dpm.uvd_active = true; 492a71849cdSEvan Quan adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; 493a71849cdSEvan Quan } else { 494a71849cdSEvan Quan adev->pm.dpm.uvd_active = false; 495a71849cdSEvan Quan } 496a71849cdSEvan Quan mutex_unlock(&adev->pm.mutex); 497a71849cdSEvan Quan 498a71849cdSEvan Quan amdgpu_dpm_compute_clocks(adev); 499a71849cdSEvan Quan return; 500a71849cdSEvan Quan } 501a71849cdSEvan Quan 502e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 503e098bc96SEvan Quan if (ret) 504e098bc96SEvan Quan DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", 505e098bc96SEvan Quan enable ? "enable" : "disable", ret); 506e098bc96SEvan Quan } 507e098bc96SEvan Quan 508e098bc96SEvan Quan void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) 509e098bc96SEvan Quan { 510e098bc96SEvan Quan int ret = 0; 511e098bc96SEvan Quan 512a71849cdSEvan Quan if (adev->family == AMDGPU_FAMILY_SI) { 513a71849cdSEvan Quan mutex_lock(&adev->pm.mutex); 514a71849cdSEvan Quan if (enable) { 515a71849cdSEvan Quan adev->pm.dpm.vce_active = true; 516a71849cdSEvan Quan /* XXX select vce level based on ring/task */ 517a71849cdSEvan Quan adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; 518a71849cdSEvan Quan } else { 519a71849cdSEvan Quan adev->pm.dpm.vce_active = false; 520a71849cdSEvan Quan } 521a71849cdSEvan Quan mutex_unlock(&adev->pm.mutex); 522a71849cdSEvan Quan 523a71849cdSEvan Quan amdgpu_dpm_compute_clocks(adev); 524a71849cdSEvan Quan return; 525a71849cdSEvan Quan } 526a71849cdSEvan Quan 527e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); 528e098bc96SEvan Quan if (ret) 529e098bc96SEvan Quan DRM_ERROR("Dpm %s vce failed, ret = %d. \n", 530e098bc96SEvan Quan enable ? "enable" : "disable", ret); 531e098bc96SEvan Quan } 532e098bc96SEvan Quan 533e098bc96SEvan Quan void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) 534e098bc96SEvan Quan { 535e098bc96SEvan Quan int ret = 0; 536e098bc96SEvan Quan 537e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); 538e098bc96SEvan Quan if (ret) 539e098bc96SEvan Quan DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", 540e098bc96SEvan Quan enable ? "enable" : "disable", ret); 541e098bc96SEvan Quan } 542e098bc96SEvan Quan 543e098bc96SEvan Quan int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) 544e098bc96SEvan Quan { 5453712e7a4SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 5463712e7a4SEvan Quan int r = 0; 547e098bc96SEvan Quan 5481613f346SFlora Cui if (!pp_funcs || !pp_funcs->load_firmware) 5493712e7a4SEvan Quan return 0; 5503712e7a4SEvan Quan 5513712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5523712e7a4SEvan Quan r = pp_funcs->load_firmware(adev->powerplay.pp_handle); 553e098bc96SEvan Quan if (r) { 554e098bc96SEvan Quan pr_err("smu firmware loading failed\n"); 5553712e7a4SEvan Quan goto out; 556e098bc96SEvan Quan } 5572e4b2f7bSEvan Quan 5582e4b2f7bSEvan Quan if (smu_version) 559e098bc96SEvan Quan *smu_version = adev->pm.fw_version; 5602e4b2f7bSEvan Quan 5613712e7a4SEvan Quan out: 5623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5633712e7a4SEvan Quan return r; 564e098bc96SEvan Quan } 565bc143d8bSEvan Quan 566bc143d8bSEvan Quan int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) 567bc143d8bSEvan Quan { 5683712e7a4SEvan Quan int ret = 0; 5693712e7a4SEvan Quan 5703712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 5713712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5723712e7a4SEvan Quan ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle, 5733712e7a4SEvan Quan enable); 5743712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5753712e7a4SEvan Quan } 5763712e7a4SEvan Quan 5773712e7a4SEvan Quan return ret; 578bc143d8bSEvan Quan } 579bc143d8bSEvan Quan 580bc143d8bSEvan Quan int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) 581bc143d8bSEvan Quan { 582ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 5833712e7a4SEvan Quan int ret = 0; 584ebfc2533SEvan Quan 58593dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 58693dde6ccSStanley.Yang return -EOPNOTSUPP; 58793dde6ccSStanley.Yang 5883712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5893712e7a4SEvan Quan ret = smu_send_hbm_bad_pages_num(smu, size); 5903712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5913712e7a4SEvan Quan 5923712e7a4SEvan Quan return ret; 593bc143d8bSEvan Quan } 594bc143d8bSEvan Quan 595d510eccfSStanley.Yang int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size) 596d510eccfSStanley.Yang { 597d510eccfSStanley.Yang struct smu_context *smu = adev->powerplay.pp_handle; 598d510eccfSStanley.Yang int ret = 0; 599d510eccfSStanley.Yang 60093dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 60193dde6ccSStanley.Yang return -EOPNOTSUPP; 60293dde6ccSStanley.Yang 603d510eccfSStanley.Yang mutex_lock(&adev->pm.mutex); 604d510eccfSStanley.Yang ret = smu_send_hbm_bad_channel_flag(smu, size); 605d510eccfSStanley.Yang mutex_unlock(&adev->pm.mutex); 606d510eccfSStanley.Yang 607d510eccfSStanley.Yang return ret; 608d510eccfSStanley.Yang } 609d510eccfSStanley.Yang 610bc143d8bSEvan Quan int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, 611bc143d8bSEvan Quan enum pp_clock_type type, 612bc143d8bSEvan Quan uint32_t *min, 613bc143d8bSEvan Quan uint32_t *max) 614bc143d8bSEvan Quan { 6153712e7a4SEvan Quan int ret = 0; 6163712e7a4SEvan Quan 6173712e7a4SEvan Quan if (type != PP_SCLK) 6183712e7a4SEvan Quan return -EINVAL; 6193712e7a4SEvan Quan 620bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 621bc143d8bSEvan Quan return -EOPNOTSUPP; 622bc143d8bSEvan Quan 6233712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6243712e7a4SEvan Quan ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle, 6253712e7a4SEvan Quan SMU_SCLK, 6263712e7a4SEvan Quan min, 6273712e7a4SEvan Quan max); 6283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6293712e7a4SEvan Quan 6303712e7a4SEvan Quan return ret; 631bc143d8bSEvan Quan } 632bc143d8bSEvan Quan 633bc143d8bSEvan Quan int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, 634bc143d8bSEvan Quan enum pp_clock_type type, 635bc143d8bSEvan Quan uint32_t min, 636bc143d8bSEvan Quan uint32_t max) 637bc143d8bSEvan Quan { 638ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6393712e7a4SEvan Quan int ret = 0; 6403712e7a4SEvan Quan 6413712e7a4SEvan Quan if (type != PP_SCLK) 6423712e7a4SEvan Quan return -EINVAL; 643ebfc2533SEvan Quan 644bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 645bc143d8bSEvan Quan return -EOPNOTSUPP; 646bc143d8bSEvan Quan 6473712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6483712e7a4SEvan Quan ret = smu_set_soft_freq_range(smu, 6493712e7a4SEvan Quan SMU_SCLK, 6503712e7a4SEvan Quan min, 6513712e7a4SEvan Quan max); 6523712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6533712e7a4SEvan Quan 6543712e7a4SEvan Quan return ret; 655bc143d8bSEvan Quan } 656bc143d8bSEvan Quan 65713f5dbd6SEvan Quan int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) 65813f5dbd6SEvan Quan { 659ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6603712e7a4SEvan Quan int ret = 0; 661ebfc2533SEvan Quan 66213f5dbd6SEvan Quan if (!is_support_sw_smu(adev)) 66313f5dbd6SEvan Quan return 0; 66413f5dbd6SEvan Quan 6653712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6663712e7a4SEvan Quan ret = smu_write_watermarks_table(smu); 6673712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6683712e7a4SEvan Quan 6693712e7a4SEvan Quan return ret; 67013f5dbd6SEvan Quan } 67113f5dbd6SEvan Quan 672bc143d8bSEvan Quan int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, 673bc143d8bSEvan Quan enum smu_event_type event, 674bc143d8bSEvan Quan uint64_t event_arg) 675bc143d8bSEvan Quan { 676ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6773712e7a4SEvan Quan int ret = 0; 678ebfc2533SEvan Quan 679bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 680bc143d8bSEvan Quan return -EOPNOTSUPP; 681bc143d8bSEvan Quan 6823712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6833712e7a4SEvan Quan ret = smu_wait_for_event(smu, event, event_arg); 6843712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6853712e7a4SEvan Quan 6863712e7a4SEvan Quan return ret; 687bc143d8bSEvan Quan } 688bc143d8bSEvan Quan 6890ad7347aSAndré Almeida int amdgpu_dpm_set_residency_gfxoff(struct amdgpu_device *adev, bool value) 6900ad7347aSAndré Almeida { 6910ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 6920ad7347aSAndré Almeida int ret = 0; 6930ad7347aSAndré Almeida 6940ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 6950ad7347aSAndré Almeida return -EOPNOTSUPP; 6960ad7347aSAndré Almeida 6970ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 6980ad7347aSAndré Almeida ret = smu_set_residency_gfxoff(smu, value); 6990ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 7000ad7347aSAndré Almeida 7010ad7347aSAndré Almeida return ret; 7020ad7347aSAndré Almeida } 7030ad7347aSAndré Almeida 7040ad7347aSAndré Almeida int amdgpu_dpm_get_residency_gfxoff(struct amdgpu_device *adev, u32 *value) 7050ad7347aSAndré Almeida { 7060ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 7070ad7347aSAndré Almeida int ret = 0; 7080ad7347aSAndré Almeida 7090ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 7100ad7347aSAndré Almeida return -EOPNOTSUPP; 7110ad7347aSAndré Almeida 7120ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 7130ad7347aSAndré Almeida ret = smu_get_residency_gfxoff(smu, value); 7140ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 7150ad7347aSAndré Almeida 7160ad7347aSAndré Almeida return ret; 7170ad7347aSAndré Almeida } 7180ad7347aSAndré Almeida 7190ad7347aSAndré Almeida int amdgpu_dpm_get_entrycount_gfxoff(struct amdgpu_device *adev, u64 *value) 7200ad7347aSAndré Almeida { 7210ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 7220ad7347aSAndré Almeida int ret = 0; 7230ad7347aSAndré Almeida 7240ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 7250ad7347aSAndré Almeida return -EOPNOTSUPP; 7260ad7347aSAndré Almeida 7270ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 7280ad7347aSAndré Almeida ret = smu_get_entrycount_gfxoff(smu, value); 7290ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 7300ad7347aSAndré Almeida 7310ad7347aSAndré Almeida return ret; 7320ad7347aSAndré Almeida } 7330ad7347aSAndré Almeida 734bc143d8bSEvan Quan int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) 735bc143d8bSEvan Quan { 736ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 7373712e7a4SEvan Quan int ret = 0; 738ebfc2533SEvan Quan 739bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 740bc143d8bSEvan Quan return -EOPNOTSUPP; 741bc143d8bSEvan Quan 7423712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 7433712e7a4SEvan Quan ret = smu_get_status_gfxoff(smu, value); 7443712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 7453712e7a4SEvan Quan 7463712e7a4SEvan Quan return ret; 747bc143d8bSEvan Quan } 748bc143d8bSEvan Quan 749bc143d8bSEvan Quan uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) 750bc143d8bSEvan Quan { 751ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 752ebfc2533SEvan Quan 7533712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 7543712e7a4SEvan Quan return 0; 7553712e7a4SEvan Quan 756ebfc2533SEvan Quan return atomic64_read(&smu->throttle_int_counter); 757bc143d8bSEvan Quan } 758bc143d8bSEvan Quan 759bc143d8bSEvan Quan /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set 760bc143d8bSEvan Quan * @adev: amdgpu_device pointer 761bc143d8bSEvan Quan * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) 762bc143d8bSEvan Quan * 763bc143d8bSEvan Quan */ 764bc143d8bSEvan Quan void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, 765bc143d8bSEvan Quan enum gfx_change_state state) 766bc143d8bSEvan Quan { 767bc143d8bSEvan Quan mutex_lock(&adev->pm.mutex); 768bc143d8bSEvan Quan if (adev->powerplay.pp_funcs && 769bc143d8bSEvan Quan adev->powerplay.pp_funcs->gfx_state_change_set) 770bc143d8bSEvan Quan ((adev)->powerplay.pp_funcs->gfx_state_change_set( 771bc143d8bSEvan Quan (adev)->powerplay.pp_handle, state)); 772bc143d8bSEvan Quan mutex_unlock(&adev->pm.mutex); 773bc143d8bSEvan Quan } 774bc143d8bSEvan Quan 775bc143d8bSEvan Quan int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, 776bc143d8bSEvan Quan void *umc_ecc) 777bc143d8bSEvan Quan { 778ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 779a29d44aeSStanley.Yang int ret = 0; 780ebfc2533SEvan Quan 781bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 782bc143d8bSEvan Quan return -EOPNOTSUPP; 783bc143d8bSEvan Quan 784a29d44aeSStanley.Yang mutex_lock(&adev->pm.mutex); 785a29d44aeSStanley.Yang ret = smu_get_ecc_info(smu, umc_ecc); 786a29d44aeSStanley.Yang mutex_unlock(&adev->pm.mutex); 787a29d44aeSStanley.Yang 788a29d44aeSStanley.Yang return ret; 789bc143d8bSEvan Quan } 79079c65f3fSEvan Quan 79179c65f3fSEvan Quan struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, 79279c65f3fSEvan Quan uint32_t idx) 79379c65f3fSEvan Quan { 79479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 7953712e7a4SEvan Quan struct amd_vce_state *vstate = NULL; 79679c65f3fSEvan Quan 79779c65f3fSEvan Quan if (!pp_funcs->get_vce_clock_state) 79879c65f3fSEvan Quan return NULL; 79979c65f3fSEvan Quan 8003712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8013712e7a4SEvan Quan vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, 80279c65f3fSEvan Quan idx); 8033712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8043712e7a4SEvan Quan 8053712e7a4SEvan Quan return vstate; 80679c65f3fSEvan Quan } 80779c65f3fSEvan Quan 80879c65f3fSEvan Quan void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, 80979c65f3fSEvan Quan enum amd_pm_state_type *state) 81079c65f3fSEvan Quan { 81179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 81279c65f3fSEvan Quan 8133712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8143712e7a4SEvan Quan 81579c65f3fSEvan Quan if (!pp_funcs->get_current_power_state) { 81679c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 8173712e7a4SEvan Quan goto out; 81879c65f3fSEvan Quan } 81979c65f3fSEvan Quan 82079c65f3fSEvan Quan *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); 82179c65f3fSEvan Quan if (*state < POWER_STATE_TYPE_DEFAULT || 82279c65f3fSEvan Quan *state > POWER_STATE_TYPE_INTERNAL_3DPERF) 82379c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 8243712e7a4SEvan Quan 8253712e7a4SEvan Quan out: 8263712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 82779c65f3fSEvan Quan } 82879c65f3fSEvan Quan 82979c65f3fSEvan Quan void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, 83079c65f3fSEvan Quan enum amd_pm_state_type state) 83179c65f3fSEvan Quan { 8323712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 83379c65f3fSEvan Quan adev->pm.dpm.user_state = state; 8343712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 83579c65f3fSEvan Quan 83679c65f3fSEvan Quan if (is_support_sw_smu(adev)) 83779c65f3fSEvan Quan return; 83879c65f3fSEvan Quan 83979c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 84079c65f3fSEvan Quan AMD_PP_TASK_ENABLE_USER_STATE, 84179c65f3fSEvan Quan &state) == -EOPNOTSUPP) 84284176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 84379c65f3fSEvan Quan } 84479c65f3fSEvan Quan 84575513bf5SEvan Quan enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) 84679c65f3fSEvan Quan { 84779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 84879c65f3fSEvan Quan enum amd_dpm_forced_level level; 84979c65f3fSEvan Quan 85039dbde65SLijo Lazar if (!pp_funcs) 85139dbde65SLijo Lazar return AMD_DPM_FORCED_LEVEL_AUTO; 85239dbde65SLijo Lazar 85375513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 85479c65f3fSEvan Quan if (pp_funcs->get_performance_level) 85579c65f3fSEvan Quan level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); 85679c65f3fSEvan Quan else 85779c65f3fSEvan Quan level = adev->pm.dpm.forced_level; 8583712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 85979c65f3fSEvan Quan 86079c65f3fSEvan Quan return level; 86179c65f3fSEvan Quan } 86279c65f3fSEvan Quan 86379c65f3fSEvan Quan int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, 86479c65f3fSEvan Quan enum amd_dpm_forced_level level) 86579c65f3fSEvan Quan { 86679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 86754c73b51SAlex Deucher enum amd_dpm_forced_level current_level; 86854c73b51SAlex Deucher uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | 86954c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | 87054c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | 87154c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; 87279c65f3fSEvan Quan 873eea5c7b3SHuang Rui if (!pp_funcs || !pp_funcs->force_performance_level) 8743712e7a4SEvan Quan return 0; 8753712e7a4SEvan Quan 87675513bf5SEvan Quan if (adev->pm.dpm.thermal_active) 87775513bf5SEvan Quan return -EINVAL; 8783712e7a4SEvan Quan 87975513bf5SEvan Quan current_level = amdgpu_dpm_get_performance_level(adev); 88075513bf5SEvan Quan if (current_level == level) 88175513bf5SEvan Quan return 0; 88254c73b51SAlex Deucher 88354c73b51SAlex Deucher if (adev->asic_type == CHIP_RAVEN) { 88454c73b51SAlex Deucher if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { 88554c73b51SAlex Deucher if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && 88654c73b51SAlex Deucher level == AMD_DPM_FORCED_LEVEL_MANUAL) 88754c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, false); 88854c73b51SAlex Deucher else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && 88954c73b51SAlex Deucher level != AMD_DPM_FORCED_LEVEL_MANUAL) 89054c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, true); 89154c73b51SAlex Deucher } 89254c73b51SAlex Deucher } 89354c73b51SAlex Deucher 89454c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 89575513bf5SEvan Quan (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 89675513bf5SEvan Quan return -EINVAL; 89754c73b51SAlex Deucher 89854c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 89954c73b51SAlex Deucher (level & profile_mode_mask)) { 90054c73b51SAlex Deucher /* enter UMD Pstate */ 90154c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 90254c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 90354c73b51SAlex Deucher AMD_PG_STATE_UNGATE); 90454c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 90554c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 90654c73b51SAlex Deucher AMD_CG_STATE_UNGATE); 90754c73b51SAlex Deucher } else if ((current_level & profile_mode_mask) && 90854c73b51SAlex Deucher !(level & profile_mode_mask)) { 90954c73b51SAlex Deucher /* exit UMD Pstate */ 91054c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 91154c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 91254c73b51SAlex Deucher AMD_CG_STATE_GATE); 91354c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 91454c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 91554c73b51SAlex Deucher AMD_PG_STATE_GATE); 91654c73b51SAlex Deucher } 91754c73b51SAlex Deucher 91875513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 91979c65f3fSEvan Quan 92075513bf5SEvan Quan if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, 92175513bf5SEvan Quan level)) { 92275513bf5SEvan Quan mutex_unlock(&adev->pm.mutex); 92375513bf5SEvan Quan return -EINVAL; 92475513bf5SEvan Quan } 92575513bf5SEvan Quan 92679c65f3fSEvan Quan adev->pm.dpm.forced_level = level; 92779c65f3fSEvan Quan 9283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9293712e7a4SEvan Quan 93075513bf5SEvan Quan return 0; 93179c65f3fSEvan Quan } 93279c65f3fSEvan Quan 93379c65f3fSEvan Quan int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, 93479c65f3fSEvan Quan struct pp_states_info *states) 93579c65f3fSEvan Quan { 93679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9373712e7a4SEvan Quan int ret = 0; 93879c65f3fSEvan Quan 93979c65f3fSEvan Quan if (!pp_funcs->get_pp_num_states) 94079c65f3fSEvan Quan return -EOPNOTSUPP; 94179c65f3fSEvan Quan 9423712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9433712e7a4SEvan Quan ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, 9443712e7a4SEvan Quan states); 9453712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9463712e7a4SEvan Quan 9473712e7a4SEvan Quan return ret; 94879c65f3fSEvan Quan } 94979c65f3fSEvan Quan 95079c65f3fSEvan Quan int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, 95179c65f3fSEvan Quan enum amd_pp_task task_id, 95279c65f3fSEvan Quan enum amd_pm_state_type *user_state) 95379c65f3fSEvan Quan { 95479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9553712e7a4SEvan Quan int ret = 0; 95679c65f3fSEvan Quan 95779c65f3fSEvan Quan if (!pp_funcs->dispatch_tasks) 95879c65f3fSEvan Quan return -EOPNOTSUPP; 95979c65f3fSEvan Quan 9603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9613712e7a4SEvan Quan ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, 9623712e7a4SEvan Quan task_id, 9633712e7a4SEvan Quan user_state); 9643712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9653712e7a4SEvan Quan 9663712e7a4SEvan Quan return ret; 96779c65f3fSEvan Quan } 96879c65f3fSEvan Quan 96979c65f3fSEvan Quan int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) 97079c65f3fSEvan Quan { 97179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9723712e7a4SEvan Quan int ret = 0; 97379c65f3fSEvan Quan 97479c65f3fSEvan Quan if (!pp_funcs->get_pp_table) 97579c65f3fSEvan Quan return 0; 97679c65f3fSEvan Quan 9773712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9783712e7a4SEvan Quan ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, 9793712e7a4SEvan Quan table); 9803712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9813712e7a4SEvan Quan 9823712e7a4SEvan Quan return ret; 98379c65f3fSEvan Quan } 98479c65f3fSEvan Quan 98579c65f3fSEvan Quan int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, 98679c65f3fSEvan Quan uint32_t type, 98779c65f3fSEvan Quan long *input, 98879c65f3fSEvan Quan uint32_t size) 98979c65f3fSEvan Quan { 99079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9913712e7a4SEvan Quan int ret = 0; 99279c65f3fSEvan Quan 99379c65f3fSEvan Quan if (!pp_funcs->set_fine_grain_clk_vol) 99479c65f3fSEvan Quan return 0; 99579c65f3fSEvan Quan 9963712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9973712e7a4SEvan Quan ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, 99879c65f3fSEvan Quan type, 99979c65f3fSEvan Quan input, 100079c65f3fSEvan Quan size); 10013712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10023712e7a4SEvan Quan 10033712e7a4SEvan Quan return ret; 100479c65f3fSEvan Quan } 100579c65f3fSEvan Quan 100679c65f3fSEvan Quan int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, 100779c65f3fSEvan Quan uint32_t type, 100879c65f3fSEvan Quan long *input, 100979c65f3fSEvan Quan uint32_t size) 101079c65f3fSEvan Quan { 101179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10123712e7a4SEvan Quan int ret = 0; 101379c65f3fSEvan Quan 101479c65f3fSEvan Quan if (!pp_funcs->odn_edit_dpm_table) 101579c65f3fSEvan Quan return 0; 101679c65f3fSEvan Quan 10173712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10183712e7a4SEvan Quan ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, 101979c65f3fSEvan Quan type, 102079c65f3fSEvan Quan input, 102179c65f3fSEvan Quan size); 10223712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10233712e7a4SEvan Quan 10243712e7a4SEvan Quan return ret; 102579c65f3fSEvan Quan } 102679c65f3fSEvan Quan 102779c65f3fSEvan Quan int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, 102879c65f3fSEvan Quan enum pp_clock_type type, 102979c65f3fSEvan Quan char *buf) 103079c65f3fSEvan Quan { 103179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10323712e7a4SEvan Quan int ret = 0; 103379c65f3fSEvan Quan 103479c65f3fSEvan Quan if (!pp_funcs->print_clock_levels) 103579c65f3fSEvan Quan return 0; 103679c65f3fSEvan Quan 10373712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10383712e7a4SEvan Quan ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle, 103979c65f3fSEvan Quan type, 104079c65f3fSEvan Quan buf); 10413712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10423712e7a4SEvan Quan 10433712e7a4SEvan Quan return ret; 104479c65f3fSEvan Quan } 104579c65f3fSEvan Quan 10465d64f9bbSDarren Powell int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, 10475d64f9bbSDarren Powell enum pp_clock_type type, 10485d64f9bbSDarren Powell char *buf, 10495d64f9bbSDarren Powell int *offset) 10505d64f9bbSDarren Powell { 10515d64f9bbSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10525d64f9bbSDarren Powell int ret = 0; 10535d64f9bbSDarren Powell 10545d64f9bbSDarren Powell if (!pp_funcs->emit_clock_levels) 10555d64f9bbSDarren Powell return -ENOENT; 10565d64f9bbSDarren Powell 10575d64f9bbSDarren Powell mutex_lock(&adev->pm.mutex); 10585d64f9bbSDarren Powell ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle, 10595d64f9bbSDarren Powell type, 10605d64f9bbSDarren Powell buf, 10615d64f9bbSDarren Powell offset); 10625d64f9bbSDarren Powell mutex_unlock(&adev->pm.mutex); 10635d64f9bbSDarren Powell 10645d64f9bbSDarren Powell return ret; 10655d64f9bbSDarren Powell } 10665d64f9bbSDarren Powell 106779c65f3fSEvan Quan int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, 106879c65f3fSEvan Quan uint64_t ppfeature_masks) 106979c65f3fSEvan Quan { 107079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10713712e7a4SEvan Quan int ret = 0; 107279c65f3fSEvan Quan 107379c65f3fSEvan Quan if (!pp_funcs->set_ppfeature_status) 107479c65f3fSEvan Quan return 0; 107579c65f3fSEvan Quan 10763712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10773712e7a4SEvan Quan ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, 107879c65f3fSEvan Quan ppfeature_masks); 10793712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10803712e7a4SEvan Quan 10813712e7a4SEvan Quan return ret; 108279c65f3fSEvan Quan } 108379c65f3fSEvan Quan 108479c65f3fSEvan Quan int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) 108579c65f3fSEvan Quan { 108679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10873712e7a4SEvan Quan int ret = 0; 108879c65f3fSEvan Quan 108979c65f3fSEvan Quan if (!pp_funcs->get_ppfeature_status) 109079c65f3fSEvan Quan return 0; 109179c65f3fSEvan Quan 10923712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10933712e7a4SEvan Quan ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, 109479c65f3fSEvan Quan buf); 10953712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10963712e7a4SEvan Quan 10973712e7a4SEvan Quan return ret; 109879c65f3fSEvan Quan } 109979c65f3fSEvan Quan 110079c65f3fSEvan Quan int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, 110179c65f3fSEvan Quan enum pp_clock_type type, 110279c65f3fSEvan Quan uint32_t mask) 110379c65f3fSEvan Quan { 110479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11053712e7a4SEvan Quan int ret = 0; 110679c65f3fSEvan Quan 110779c65f3fSEvan Quan if (!pp_funcs->force_clock_level) 110879c65f3fSEvan Quan return 0; 110979c65f3fSEvan Quan 11103712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11113712e7a4SEvan Quan ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle, 111279c65f3fSEvan Quan type, 111379c65f3fSEvan Quan mask); 11143712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11153712e7a4SEvan Quan 11163712e7a4SEvan Quan return ret; 111779c65f3fSEvan Quan } 111879c65f3fSEvan Quan 111979c65f3fSEvan Quan int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) 112079c65f3fSEvan Quan { 112179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11223712e7a4SEvan Quan int ret = 0; 112379c65f3fSEvan Quan 112479c65f3fSEvan Quan if (!pp_funcs->get_sclk_od) 112579c65f3fSEvan Quan return 0; 112679c65f3fSEvan Quan 11273712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11283712e7a4SEvan Quan ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle); 11293712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11303712e7a4SEvan Quan 11313712e7a4SEvan Quan return ret; 113279c65f3fSEvan Quan } 113379c65f3fSEvan Quan 113479c65f3fSEvan Quan int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) 113579c65f3fSEvan Quan { 113679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 113779c65f3fSEvan Quan 113879c65f3fSEvan Quan if (is_support_sw_smu(adev)) 113979c65f3fSEvan Quan return 0; 114079c65f3fSEvan Quan 11413712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 114279c65f3fSEvan Quan if (pp_funcs->set_sclk_od) 114379c65f3fSEvan Quan pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); 11443712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 114579c65f3fSEvan Quan 114679c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 114779c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 114879c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 114979c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 115084176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 115179c65f3fSEvan Quan } 115279c65f3fSEvan Quan 115379c65f3fSEvan Quan return 0; 115479c65f3fSEvan Quan } 115579c65f3fSEvan Quan 115679c65f3fSEvan Quan int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) 115779c65f3fSEvan Quan { 115879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11593712e7a4SEvan Quan int ret = 0; 116079c65f3fSEvan Quan 116179c65f3fSEvan Quan if (!pp_funcs->get_mclk_od) 116279c65f3fSEvan Quan return 0; 116379c65f3fSEvan Quan 11643712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11653712e7a4SEvan Quan ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle); 11663712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11673712e7a4SEvan Quan 11683712e7a4SEvan Quan return ret; 116979c65f3fSEvan Quan } 117079c65f3fSEvan Quan 117179c65f3fSEvan Quan int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) 117279c65f3fSEvan Quan { 117379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 117479c65f3fSEvan Quan 117579c65f3fSEvan Quan if (is_support_sw_smu(adev)) 117679c65f3fSEvan Quan return 0; 117779c65f3fSEvan Quan 11783712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 117979c65f3fSEvan Quan if (pp_funcs->set_mclk_od) 118079c65f3fSEvan Quan pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); 11813712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 118279c65f3fSEvan Quan 118379c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 118479c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 118579c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 118679c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 118784176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 118879c65f3fSEvan Quan } 118979c65f3fSEvan Quan 119079c65f3fSEvan Quan return 0; 119179c65f3fSEvan Quan } 119279c65f3fSEvan Quan 119379c65f3fSEvan Quan int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, 119479c65f3fSEvan Quan char *buf) 119579c65f3fSEvan Quan { 119679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11973712e7a4SEvan Quan int ret = 0; 119879c65f3fSEvan Quan 119979c65f3fSEvan Quan if (!pp_funcs->get_power_profile_mode) 120079c65f3fSEvan Quan return -EOPNOTSUPP; 120179c65f3fSEvan Quan 12023712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12033712e7a4SEvan Quan ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, 120479c65f3fSEvan Quan buf); 12053712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12063712e7a4SEvan Quan 12073712e7a4SEvan Quan return ret; 120879c65f3fSEvan Quan } 120979c65f3fSEvan Quan 121079c65f3fSEvan Quan int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, 121179c65f3fSEvan Quan long *input, uint32_t size) 121279c65f3fSEvan Quan { 121379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12143712e7a4SEvan Quan int ret = 0; 121579c65f3fSEvan Quan 121679c65f3fSEvan Quan if (!pp_funcs->set_power_profile_mode) 121779c65f3fSEvan Quan return 0; 121879c65f3fSEvan Quan 12193712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12203712e7a4SEvan Quan ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, 122179c65f3fSEvan Quan input, 122279c65f3fSEvan Quan size); 12233712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12243712e7a4SEvan Quan 12253712e7a4SEvan Quan return ret; 122679c65f3fSEvan Quan } 122779c65f3fSEvan Quan 122879c65f3fSEvan Quan int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) 122979c65f3fSEvan Quan { 123079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12313712e7a4SEvan Quan int ret = 0; 123279c65f3fSEvan Quan 123379c65f3fSEvan Quan if (!pp_funcs->get_gpu_metrics) 123479c65f3fSEvan Quan return 0; 123579c65f3fSEvan Quan 12363712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12373712e7a4SEvan Quan ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, 12383712e7a4SEvan Quan table); 12393712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12403712e7a4SEvan Quan 12413712e7a4SEvan Quan return ret; 124279c65f3fSEvan Quan } 124379c65f3fSEvan Quan 124479c65f3fSEvan Quan int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, 124579c65f3fSEvan Quan uint32_t *fan_mode) 124679c65f3fSEvan Quan { 124779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1248685fae24SEvan Quan int ret = 0; 124979c65f3fSEvan Quan 125079c65f3fSEvan Quan if (!pp_funcs->get_fan_control_mode) 125179c65f3fSEvan Quan return -EOPNOTSUPP; 125279c65f3fSEvan Quan 12533712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1254685fae24SEvan Quan ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, 1255685fae24SEvan Quan fan_mode); 12563712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 125779c65f3fSEvan Quan 1258685fae24SEvan Quan return ret; 125979c65f3fSEvan Quan } 126079c65f3fSEvan Quan 126179c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, 126279c65f3fSEvan Quan uint32_t speed) 126379c65f3fSEvan Quan { 126479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12653712e7a4SEvan Quan int ret = 0; 126679c65f3fSEvan Quan 126779c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_pwm) 1268685fae24SEvan Quan return -EOPNOTSUPP; 126979c65f3fSEvan Quan 12703712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12713712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, 12723712e7a4SEvan Quan speed); 12733712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12743712e7a4SEvan Quan 12753712e7a4SEvan Quan return ret; 127679c65f3fSEvan Quan } 127779c65f3fSEvan Quan 127879c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, 127979c65f3fSEvan Quan uint32_t *speed) 128079c65f3fSEvan Quan { 128179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12823712e7a4SEvan Quan int ret = 0; 128379c65f3fSEvan Quan 128479c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_pwm) 1285685fae24SEvan Quan return -EOPNOTSUPP; 128679c65f3fSEvan Quan 12873712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12883712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, 12893712e7a4SEvan Quan speed); 12903712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12913712e7a4SEvan Quan 12923712e7a4SEvan Quan return ret; 129379c65f3fSEvan Quan } 129479c65f3fSEvan Quan 129579c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, 129679c65f3fSEvan Quan uint32_t *speed) 129779c65f3fSEvan Quan { 129879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12993712e7a4SEvan Quan int ret = 0; 130079c65f3fSEvan Quan 130179c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_rpm) 1302685fae24SEvan Quan return -EOPNOTSUPP; 130379c65f3fSEvan Quan 13043712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13053712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, 13063712e7a4SEvan Quan speed); 13073712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13083712e7a4SEvan Quan 13093712e7a4SEvan Quan return ret; 131079c65f3fSEvan Quan } 131179c65f3fSEvan Quan 131279c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, 131379c65f3fSEvan Quan uint32_t speed) 131479c65f3fSEvan Quan { 131579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13163712e7a4SEvan Quan int ret = 0; 131779c65f3fSEvan Quan 131879c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_rpm) 1319685fae24SEvan Quan return -EOPNOTSUPP; 132079c65f3fSEvan Quan 13213712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13223712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, 13233712e7a4SEvan Quan speed); 13243712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13253712e7a4SEvan Quan 13263712e7a4SEvan Quan return ret; 132779c65f3fSEvan Quan } 132879c65f3fSEvan Quan 132979c65f3fSEvan Quan int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, 133079c65f3fSEvan Quan uint32_t mode) 133179c65f3fSEvan Quan { 133279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1333685fae24SEvan Quan int ret = 0; 133479c65f3fSEvan Quan 133579c65f3fSEvan Quan if (!pp_funcs->set_fan_control_mode) 133679c65f3fSEvan Quan return -EOPNOTSUPP; 133779c65f3fSEvan Quan 13383712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1339685fae24SEvan Quan ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, 13403712e7a4SEvan Quan mode); 13413712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 134279c65f3fSEvan Quan 1343685fae24SEvan Quan return ret; 134479c65f3fSEvan Quan } 134579c65f3fSEvan Quan 134679c65f3fSEvan Quan int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, 134779c65f3fSEvan Quan uint32_t *limit, 134879c65f3fSEvan Quan enum pp_power_limit_level pp_limit_level, 134979c65f3fSEvan Quan enum pp_power_type power_type) 135079c65f3fSEvan Quan { 135179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13523712e7a4SEvan Quan int ret = 0; 135379c65f3fSEvan Quan 135479c65f3fSEvan Quan if (!pp_funcs->get_power_limit) 135579c65f3fSEvan Quan return -ENODATA; 135679c65f3fSEvan Quan 13573712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13583712e7a4SEvan Quan ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle, 135979c65f3fSEvan Quan limit, 136079c65f3fSEvan Quan pp_limit_level, 136179c65f3fSEvan Quan power_type); 13623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13633712e7a4SEvan Quan 13643712e7a4SEvan Quan return ret; 136579c65f3fSEvan Quan } 136679c65f3fSEvan Quan 136779c65f3fSEvan Quan int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, 136879c65f3fSEvan Quan uint32_t limit) 136979c65f3fSEvan Quan { 137079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13713712e7a4SEvan Quan int ret = 0; 137279c65f3fSEvan Quan 137379c65f3fSEvan Quan if (!pp_funcs->set_power_limit) 137479c65f3fSEvan Quan return -EINVAL; 137579c65f3fSEvan Quan 13763712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13773712e7a4SEvan Quan ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle, 13783712e7a4SEvan Quan limit); 13793712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13803712e7a4SEvan Quan 13813712e7a4SEvan Quan return ret; 138279c65f3fSEvan Quan } 138379c65f3fSEvan Quan 138479c65f3fSEvan Quan int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) 138579c65f3fSEvan Quan { 13863712e7a4SEvan Quan bool cclk_dpm_supported = false; 13873712e7a4SEvan Quan 138879c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 138979c65f3fSEvan Quan return false; 139079c65f3fSEvan Quan 13913712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13923712e7a4SEvan Quan cclk_dpm_supported = is_support_cclk_dpm(adev); 13933712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13943712e7a4SEvan Quan 13953712e7a4SEvan Quan return (int)cclk_dpm_supported; 139679c65f3fSEvan Quan } 139779c65f3fSEvan Quan 139879c65f3fSEvan Quan int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, 139979c65f3fSEvan Quan struct seq_file *m) 140079c65f3fSEvan Quan { 140179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 140279c65f3fSEvan Quan 140379c65f3fSEvan Quan if (!pp_funcs->debugfs_print_current_performance_level) 140479c65f3fSEvan Quan return -EOPNOTSUPP; 140579c65f3fSEvan Quan 14063712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 140779c65f3fSEvan Quan pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, 140879c65f3fSEvan Quan m); 14093712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 141079c65f3fSEvan Quan 141179c65f3fSEvan Quan return 0; 141279c65f3fSEvan Quan } 141379c65f3fSEvan Quan 141479c65f3fSEvan Quan int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, 141579c65f3fSEvan Quan void **addr, 141679c65f3fSEvan Quan size_t *size) 141779c65f3fSEvan Quan { 141879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14193712e7a4SEvan Quan int ret = 0; 142079c65f3fSEvan Quan 142179c65f3fSEvan Quan if (!pp_funcs->get_smu_prv_buf_details) 142279c65f3fSEvan Quan return -ENOSYS; 142379c65f3fSEvan Quan 14243712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14253712e7a4SEvan Quan ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, 142679c65f3fSEvan Quan addr, 142779c65f3fSEvan Quan size); 14283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14293712e7a4SEvan Quan 14303712e7a4SEvan Quan return ret; 143179c65f3fSEvan Quan } 143279c65f3fSEvan Quan 143379c65f3fSEvan Quan int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) 143479c65f3fSEvan Quan { 143579c65f3fSEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; 1436ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 143779c65f3fSEvan Quan 1438ebfc2533SEvan Quan if ((is_support_sw_smu(adev) && smu->od_enabled) || 1439ebfc2533SEvan Quan (is_support_sw_smu(adev) && smu->is_apu) || 144079c65f3fSEvan Quan (!is_support_sw_smu(adev) && hwmgr->od_enabled)) 144179c65f3fSEvan Quan return true; 144279c65f3fSEvan Quan 144379c65f3fSEvan Quan return false; 144479c65f3fSEvan Quan } 144579c65f3fSEvan Quan 144679c65f3fSEvan Quan int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, 144779c65f3fSEvan Quan const char *buf, 144879c65f3fSEvan Quan size_t size) 144979c65f3fSEvan Quan { 145079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14513712e7a4SEvan Quan int ret = 0; 145279c65f3fSEvan Quan 145379c65f3fSEvan Quan if (!pp_funcs->set_pp_table) 145479c65f3fSEvan Quan return -EOPNOTSUPP; 145579c65f3fSEvan Quan 14563712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14573712e7a4SEvan Quan ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle, 145879c65f3fSEvan Quan buf, 145979c65f3fSEvan Quan size); 14603712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14613712e7a4SEvan Quan 14623712e7a4SEvan Quan return ret; 146379c65f3fSEvan Quan } 146479c65f3fSEvan Quan 146579c65f3fSEvan Quan int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) 146679c65f3fSEvan Quan { 1467ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 1468ebfc2533SEvan Quan 14693712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 14703712e7a4SEvan Quan return INT_MAX; 14713712e7a4SEvan Quan 1472ebfc2533SEvan Quan return smu->cpu_core_num; 147379c65f3fSEvan Quan } 147479c65f3fSEvan Quan 147579c65f3fSEvan Quan void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) 147679c65f3fSEvan Quan { 147779c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 147879c65f3fSEvan Quan return; 147979c65f3fSEvan Quan 148079c65f3fSEvan Quan amdgpu_smu_stb_debug_fs_init(adev); 148179c65f3fSEvan Quan } 148213f5dbd6SEvan Quan 148313f5dbd6SEvan Quan int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, 148413f5dbd6SEvan Quan const struct amd_pp_display_configuration *input) 148513f5dbd6SEvan Quan { 148613f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14873712e7a4SEvan Quan int ret = 0; 148813f5dbd6SEvan Quan 148913f5dbd6SEvan Quan if (!pp_funcs->display_configuration_change) 149013f5dbd6SEvan Quan return 0; 149113f5dbd6SEvan Quan 14923712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14933712e7a4SEvan Quan ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle, 149413f5dbd6SEvan Quan input); 14953712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14963712e7a4SEvan Quan 14973712e7a4SEvan Quan return ret; 149813f5dbd6SEvan Quan } 149913f5dbd6SEvan Quan 150013f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, 150113f5dbd6SEvan Quan enum amd_pp_clock_type type, 150213f5dbd6SEvan Quan struct amd_pp_clocks *clocks) 150313f5dbd6SEvan Quan { 150413f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15053712e7a4SEvan Quan int ret = 0; 150613f5dbd6SEvan Quan 150713f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type) 150813f5dbd6SEvan Quan return 0; 150913f5dbd6SEvan Quan 15103712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15113712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, 151213f5dbd6SEvan Quan type, 151313f5dbd6SEvan Quan clocks); 15143712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15153712e7a4SEvan Quan 15163712e7a4SEvan Quan return ret; 151713f5dbd6SEvan Quan } 151813f5dbd6SEvan Quan 151913f5dbd6SEvan Quan int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, 152013f5dbd6SEvan Quan struct amd_pp_simple_clock_info *clocks) 152113f5dbd6SEvan Quan { 152213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15233712e7a4SEvan Quan int ret = 0; 152413f5dbd6SEvan Quan 152513f5dbd6SEvan Quan if (!pp_funcs->get_display_mode_validation_clocks) 152613f5dbd6SEvan Quan return 0; 152713f5dbd6SEvan Quan 15283712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15293712e7a4SEvan Quan ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, 153013f5dbd6SEvan Quan clocks); 15313712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15323712e7a4SEvan Quan 15333712e7a4SEvan Quan return ret; 153413f5dbd6SEvan Quan } 153513f5dbd6SEvan Quan 153613f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, 153713f5dbd6SEvan Quan enum amd_pp_clock_type type, 153813f5dbd6SEvan Quan struct pp_clock_levels_with_latency *clocks) 153913f5dbd6SEvan Quan { 154013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15413712e7a4SEvan Quan int ret = 0; 154213f5dbd6SEvan Quan 154313f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_latency) 154413f5dbd6SEvan Quan return 0; 154513f5dbd6SEvan Quan 15463712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15473712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, 154813f5dbd6SEvan Quan type, 154913f5dbd6SEvan Quan clocks); 15503712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15513712e7a4SEvan Quan 15523712e7a4SEvan Quan return ret; 155313f5dbd6SEvan Quan } 155413f5dbd6SEvan Quan 155513f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, 155613f5dbd6SEvan Quan enum amd_pp_clock_type type, 155713f5dbd6SEvan Quan struct pp_clock_levels_with_voltage *clocks) 155813f5dbd6SEvan Quan { 155913f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15603712e7a4SEvan Quan int ret = 0; 156113f5dbd6SEvan Quan 156213f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_voltage) 156313f5dbd6SEvan Quan return 0; 156413f5dbd6SEvan Quan 15653712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15663712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, 156713f5dbd6SEvan Quan type, 156813f5dbd6SEvan Quan clocks); 15693712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15703712e7a4SEvan Quan 15713712e7a4SEvan Quan return ret; 157213f5dbd6SEvan Quan } 157313f5dbd6SEvan Quan 157413f5dbd6SEvan Quan int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, 157513f5dbd6SEvan Quan void *clock_ranges) 157613f5dbd6SEvan Quan { 157713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15783712e7a4SEvan Quan int ret = 0; 157913f5dbd6SEvan Quan 158013f5dbd6SEvan Quan if (!pp_funcs->set_watermarks_for_clocks_ranges) 158113f5dbd6SEvan Quan return -EOPNOTSUPP; 158213f5dbd6SEvan Quan 15833712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15843712e7a4SEvan Quan ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, 158513f5dbd6SEvan Quan clock_ranges); 15863712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15873712e7a4SEvan Quan 15883712e7a4SEvan Quan return ret; 158913f5dbd6SEvan Quan } 159013f5dbd6SEvan Quan 159113f5dbd6SEvan Quan int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, 159213f5dbd6SEvan Quan struct pp_display_clock_request *clock) 159313f5dbd6SEvan Quan { 159413f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15953712e7a4SEvan Quan int ret = 0; 159613f5dbd6SEvan Quan 159713f5dbd6SEvan Quan if (!pp_funcs->display_clock_voltage_request) 159813f5dbd6SEvan Quan return -EOPNOTSUPP; 159913f5dbd6SEvan Quan 16003712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16013712e7a4SEvan Quan ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, 160213f5dbd6SEvan Quan clock); 16033712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16043712e7a4SEvan Quan 16053712e7a4SEvan Quan return ret; 160613f5dbd6SEvan Quan } 160713f5dbd6SEvan Quan 160813f5dbd6SEvan Quan int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, 160913f5dbd6SEvan Quan struct amd_pp_clock_info *clocks) 161013f5dbd6SEvan Quan { 161113f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16123712e7a4SEvan Quan int ret = 0; 161313f5dbd6SEvan Quan 161413f5dbd6SEvan Quan if (!pp_funcs->get_current_clocks) 161513f5dbd6SEvan Quan return -EOPNOTSUPP; 161613f5dbd6SEvan Quan 16173712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16183712e7a4SEvan Quan ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle, 161913f5dbd6SEvan Quan clocks); 16203712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16213712e7a4SEvan Quan 16223712e7a4SEvan Quan return ret; 162313f5dbd6SEvan Quan } 162413f5dbd6SEvan Quan 162513f5dbd6SEvan Quan void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) 162613f5dbd6SEvan Quan { 162713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 162813f5dbd6SEvan Quan 162913f5dbd6SEvan Quan if (!pp_funcs->notify_smu_enable_pwe) 163013f5dbd6SEvan Quan return; 163113f5dbd6SEvan Quan 16323712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 163313f5dbd6SEvan Quan pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); 16343712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 163513f5dbd6SEvan Quan } 163613f5dbd6SEvan Quan 163713f5dbd6SEvan Quan int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, 163813f5dbd6SEvan Quan uint32_t count) 163913f5dbd6SEvan Quan { 164013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16413712e7a4SEvan Quan int ret = 0; 164213f5dbd6SEvan Quan 164313f5dbd6SEvan Quan if (!pp_funcs->set_active_display_count) 164413f5dbd6SEvan Quan return -EOPNOTSUPP; 164513f5dbd6SEvan Quan 16463712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16473712e7a4SEvan Quan ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle, 164813f5dbd6SEvan Quan count); 16493712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16503712e7a4SEvan Quan 16513712e7a4SEvan Quan return ret; 165213f5dbd6SEvan Quan } 165313f5dbd6SEvan Quan 165413f5dbd6SEvan Quan int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, 165513f5dbd6SEvan Quan uint32_t clock) 165613f5dbd6SEvan Quan { 165713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16583712e7a4SEvan Quan int ret = 0; 165913f5dbd6SEvan Quan 166013f5dbd6SEvan Quan if (!pp_funcs->set_min_deep_sleep_dcefclk) 166113f5dbd6SEvan Quan return -EOPNOTSUPP; 166213f5dbd6SEvan Quan 16633712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16643712e7a4SEvan Quan ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, 166513f5dbd6SEvan Quan clock); 16663712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16673712e7a4SEvan Quan 16683712e7a4SEvan Quan return ret; 166913f5dbd6SEvan Quan } 167013f5dbd6SEvan Quan 167113f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, 167213f5dbd6SEvan Quan uint32_t clock) 167313f5dbd6SEvan Quan { 167413f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 167513f5dbd6SEvan Quan 167613f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_dcefclk_by_freq) 167713f5dbd6SEvan Quan return; 167813f5dbd6SEvan Quan 16793712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 168013f5dbd6SEvan Quan pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, 168113f5dbd6SEvan Quan clock); 16823712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 168313f5dbd6SEvan Quan } 168413f5dbd6SEvan Quan 168513f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, 168613f5dbd6SEvan Quan uint32_t clock) 168713f5dbd6SEvan Quan { 168813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 168913f5dbd6SEvan Quan 169013f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_fclk_by_freq) 169113f5dbd6SEvan Quan return; 169213f5dbd6SEvan Quan 16933712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 169413f5dbd6SEvan Quan pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, 169513f5dbd6SEvan Quan clock); 16963712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 169713f5dbd6SEvan Quan } 169813f5dbd6SEvan Quan 169913f5dbd6SEvan Quan int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, 170013f5dbd6SEvan Quan bool disable_memory_clock_switch) 170113f5dbd6SEvan Quan { 170213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17033712e7a4SEvan Quan int ret = 0; 170413f5dbd6SEvan Quan 170513f5dbd6SEvan Quan if (!pp_funcs->display_disable_memory_clock_switch) 170613f5dbd6SEvan Quan return 0; 170713f5dbd6SEvan Quan 17083712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17093712e7a4SEvan Quan ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, 171013f5dbd6SEvan Quan disable_memory_clock_switch); 17113712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17123712e7a4SEvan Quan 17133712e7a4SEvan Quan return ret; 171413f5dbd6SEvan Quan } 171513f5dbd6SEvan Quan 171613f5dbd6SEvan Quan int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, 171713f5dbd6SEvan Quan struct pp_smu_nv_clock_table *max_clocks) 171813f5dbd6SEvan Quan { 171913f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17203712e7a4SEvan Quan int ret = 0; 172113f5dbd6SEvan Quan 172213f5dbd6SEvan Quan if (!pp_funcs->get_max_sustainable_clocks_by_dc) 172313f5dbd6SEvan Quan return -EOPNOTSUPP; 172413f5dbd6SEvan Quan 17253712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17263712e7a4SEvan Quan ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, 172713f5dbd6SEvan Quan max_clocks); 17283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17293712e7a4SEvan Quan 17303712e7a4SEvan Quan return ret; 173113f5dbd6SEvan Quan } 173213f5dbd6SEvan Quan 173313f5dbd6SEvan Quan enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, 173413f5dbd6SEvan Quan unsigned int *clock_values_in_khz, 173513f5dbd6SEvan Quan unsigned int *num_states) 173613f5dbd6SEvan Quan { 173713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17383712e7a4SEvan Quan int ret = 0; 173913f5dbd6SEvan Quan 174013f5dbd6SEvan Quan if (!pp_funcs->get_uclk_dpm_states) 174113f5dbd6SEvan Quan return -EOPNOTSUPP; 174213f5dbd6SEvan Quan 17433712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17443712e7a4SEvan Quan ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, 174513f5dbd6SEvan Quan clock_values_in_khz, 174613f5dbd6SEvan Quan num_states); 17473712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17483712e7a4SEvan Quan 17493712e7a4SEvan Quan return ret; 175013f5dbd6SEvan Quan } 175113f5dbd6SEvan Quan 175213f5dbd6SEvan Quan int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, 175313f5dbd6SEvan Quan struct dpm_clocks *clock_table) 175413f5dbd6SEvan Quan { 175513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17563712e7a4SEvan Quan int ret = 0; 175713f5dbd6SEvan Quan 175813f5dbd6SEvan Quan if (!pp_funcs->get_dpm_clock_table) 175913f5dbd6SEvan Quan return -EOPNOTSUPP; 176013f5dbd6SEvan Quan 17613712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17623712e7a4SEvan Quan ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, 176313f5dbd6SEvan Quan clock_table); 17643712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17653712e7a4SEvan Quan 17663712e7a4SEvan Quan return ret; 176713f5dbd6SEvan Quan } 1768