162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1262306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Authors: Alex Deucher 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "amdgpu.h" 2662306a36Sopenharmony_ci#include "amdgpu_atombios.h" 2762306a36Sopenharmony_ci#include "amdgpu_i2c.h" 2862306a36Sopenharmony_ci#include "amdgpu_dpm.h" 2962306a36Sopenharmony_ci#include "atom.h" 3062306a36Sopenharmony_ci#include "amd_pcie.h" 3162306a36Sopenharmony_ci#include "amdgpu_display.h" 3262306a36Sopenharmony_ci#include "hwmgr.h" 3362306a36Sopenharmony_ci#include <linux/power_supply.h> 3462306a36Sopenharmony_ci#include "amdgpu_smu.h" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define amdgpu_dpm_enable_bapm(adev, e) \ 3762306a36Sopenharmony_ci ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define amdgpu_dpm_is_legacy_dpm(adev) ((adev)->powerplay.pp_handle == (adev)) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciint amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 4462306a36Sopenharmony_ci int ret = 0; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci if (!pp_funcs->get_sclk) 4762306a36Sopenharmony_ci return 0; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 5062306a36Sopenharmony_ci ret = pp_funcs->get_sclk((adev)->powerplay.pp_handle, 5162306a36Sopenharmony_ci low); 5262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return ret; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciint amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 6062306a36Sopenharmony_ci int ret = 0; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (!pp_funcs->get_mclk) 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 6662306a36Sopenharmony_ci ret = pp_funcs->get_mclk((adev)->powerplay.pp_handle, 6762306a36Sopenharmony_ci low); 6862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci return ret; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciint amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int ret = 0; 7662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 7762306a36Sopenharmony_ci enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) { 8062306a36Sopenharmony_ci dev_dbg(adev->dev, "IP block%d already in the target %s state!", 8162306a36Sopenharmony_ci block_type, gate ? "gate" : "ungate"); 8262306a36Sopenharmony_ci return 0; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci switch (block_type) { 8862306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_UVD: 8962306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_VCE: 9062306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_GFX: 9162306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_VCN: 9262306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_SDMA: 9362306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_JPEG: 9462306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_GMC: 9562306a36Sopenharmony_ci case AMD_IP_BLOCK_TYPE_ACP: 9662306a36Sopenharmony_ci if (pp_funcs && pp_funcs->set_powergating_by_smu) 9762306a36Sopenharmony_ci ret = (pp_funcs->set_powergating_by_smu( 9862306a36Sopenharmony_ci (adev)->powerplay.pp_handle, block_type, gate)); 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci default: 10162306a36Sopenharmony_ci break; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (!ret) 10562306a36Sopenharmony_ci atomic_set(&adev->pm.pwr_state[block_type], pwr_state); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return ret; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciint amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 11562306a36Sopenharmony_ci int ret = -EOPNOTSUPP; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 11862306a36Sopenharmony_ci ret = smu_set_gfx_power_up_by_imu(smu); 11962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci msleep(10); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return ret; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciint amdgpu_dpm_baco_enter(struct amdgpu_device *adev) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12962306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 13062306a36Sopenharmony_ci int ret = 0; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->set_asic_baco_state) 13362306a36Sopenharmony_ci return -ENOENT; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* enter BACO state */ 13862306a36Sopenharmony_ci ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return ret; 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciint amdgpu_dpm_baco_exit(struct amdgpu_device *adev) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14862306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 14962306a36Sopenharmony_ci int ret = 0; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->set_asic_baco_state) 15262306a36Sopenharmony_ci return -ENOENT; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* exit BACO state */ 15762306a36Sopenharmony_ci ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return ret; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciint amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, 16562306a36Sopenharmony_ci enum pp_mp1_state mp1_state) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci int ret = 0; 16862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (pp_funcs && pp_funcs->set_mp1_state) { 17162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci ret = pp_funcs->set_mp1_state( 17462306a36Sopenharmony_ci adev->powerplay.pp_handle, 17562306a36Sopenharmony_ci mp1_state); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return ret; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cibool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 18662306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 18762306a36Sopenharmony_ci bool baco_cap; 18862306a36Sopenharmony_ci int ret = 0; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->get_asic_baco_capability) 19162306a36Sopenharmony_ci return false; 19262306a36Sopenharmony_ci /* Don't use baco for reset in S3. 19362306a36Sopenharmony_ci * This is a workaround for some platforms 19462306a36Sopenharmony_ci * where entering BACO during suspend 19562306a36Sopenharmony_ci * seems to cause reboots or hangs. 19662306a36Sopenharmony_ci * This might be related to the fact that BACO controls 19762306a36Sopenharmony_ci * power to the whole GPU including devices like audio and USB. 19862306a36Sopenharmony_ci * Powering down/up everything may adversely affect these other 19962306a36Sopenharmony_ci * devices. Needs more investigation. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci if (adev->in_s3) 20262306a36Sopenharmony_ci return false; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci ret = pp_funcs->get_asic_baco_capability(pp_handle, 20762306a36Sopenharmony_ci &baco_cap); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci return ret ? false : baco_cap; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciint amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 21762306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 21862306a36Sopenharmony_ci int ret = 0; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->asic_reset_mode_2) 22162306a36Sopenharmony_ci return -ENOENT; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci ret = pp_funcs->asic_reset_mode_2(pp_handle); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ciint amdgpu_dpm_enable_gfx_features(struct amdgpu_device *adev) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 23562306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 23662306a36Sopenharmony_ci int ret = 0; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->asic_reset_enable_gfx_features) 23962306a36Sopenharmony_ci return -ENOENT; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci ret = pp_funcs->asic_reset_enable_gfx_features(pp_handle); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci return ret; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ciint amdgpu_dpm_baco_reset(struct amdgpu_device *adev) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 25362306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 25462306a36Sopenharmony_ci int ret = 0; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->set_asic_baco_state) 25762306a36Sopenharmony_ci return -ENOENT; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci /* enter BACO state */ 26262306a36Sopenharmony_ci ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 26362306a36Sopenharmony_ci if (ret) 26462306a36Sopenharmony_ci goto out; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* exit BACO state */ 26762306a36Sopenharmony_ci ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ciout: 27062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 27162306a36Sopenharmony_ci return ret; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cibool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 27762306a36Sopenharmony_ci bool support_mode1_reset = false; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (is_support_sw_smu(adev)) { 28062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 28162306a36Sopenharmony_ci support_mode1_reset = smu_mode1_reset_is_support(smu); 28262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return support_mode1_reset; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciint amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 29162306a36Sopenharmony_ci int ret = -EOPNOTSUPP; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (is_support_sw_smu(adev)) { 29462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 29562306a36Sopenharmony_ci ret = smu_mode1_reset(smu); 29662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci return ret; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ciint amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, 30362306a36Sopenharmony_ci enum PP_SMC_POWER_PROFILE type, 30462306a36Sopenharmony_ci bool en) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 30762306a36Sopenharmony_ci int ret = 0; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (amdgpu_sriov_vf(adev)) 31062306a36Sopenharmony_ci return 0; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (pp_funcs && pp_funcs->switch_power_profile) { 31362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 31462306a36Sopenharmony_ci ret = pp_funcs->switch_power_profile( 31562306a36Sopenharmony_ci adev->powerplay.pp_handle, type, en); 31662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return ret; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ciint amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, 32362306a36Sopenharmony_ci uint32_t pstate) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 32662306a36Sopenharmony_ci int ret = 0; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (pp_funcs && pp_funcs->set_xgmi_pstate) { 32962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 33062306a36Sopenharmony_ci ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, 33162306a36Sopenharmony_ci pstate); 33262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return ret; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ciint amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, 33962306a36Sopenharmony_ci uint32_t cstate) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci int ret = 0; 34262306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 34362306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (pp_funcs && pp_funcs->set_df_cstate) { 34662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 34762306a36Sopenharmony_ci ret = pp_funcs->set_df_cstate(pp_handle, cstate); 34862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci return ret; 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ciint amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 35762306a36Sopenharmony_ci int ret = 0; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if (is_support_sw_smu(adev)) { 36062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 36162306a36Sopenharmony_ci ret = smu_allow_xgmi_power_down(smu, en); 36262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return ret; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ciint amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 37162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = 37262306a36Sopenharmony_ci adev->powerplay.pp_funcs; 37362306a36Sopenharmony_ci int ret = 0; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) { 37662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 37762306a36Sopenharmony_ci ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); 37862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci return ret; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ciint amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, 38562306a36Sopenharmony_ci uint32_t msg_id) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 38862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = 38962306a36Sopenharmony_ci adev->powerplay.pp_funcs; 39062306a36Sopenharmony_ci int ret = 0; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (pp_funcs && pp_funcs->set_clockgating_by_smu) { 39362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 39462306a36Sopenharmony_ci ret = pp_funcs->set_clockgating_by_smu(pp_handle, 39562306a36Sopenharmony_ci msg_id); 39662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci return ret; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ciint amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, 40362306a36Sopenharmony_ci bool acquire) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci void *pp_handle = adev->powerplay.pp_handle; 40662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = 40762306a36Sopenharmony_ci adev->powerplay.pp_funcs; 40862306a36Sopenharmony_ci int ret = -EOPNOTSUPP; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (pp_funcs && pp_funcs->smu_i2c_bus_access) { 41162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 41262306a36Sopenharmony_ci ret = pp_funcs->smu_i2c_bus_access(pp_handle, 41362306a36Sopenharmony_ci acquire); 41462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci return ret; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_civoid amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci if (adev->pm.dpm_enabled) { 42362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 42462306a36Sopenharmony_ci if (power_supply_is_system_supplied() > 0) 42562306a36Sopenharmony_ci adev->pm.ac_power = true; 42662306a36Sopenharmony_ci else 42762306a36Sopenharmony_ci adev->pm.ac_power = false; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci if (adev->powerplay.pp_funcs && 43062306a36Sopenharmony_ci adev->powerplay.pp_funcs->enable_bapm) 43162306a36Sopenharmony_ci amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (is_support_sw_smu(adev)) 43462306a36Sopenharmony_ci smu_set_ac_dc(adev->powerplay.pp_handle); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciint amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, 44162306a36Sopenharmony_ci void *data, uint32_t *size) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 44462306a36Sopenharmony_ci int ret = -EINVAL; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (!data || !size) 44762306a36Sopenharmony_ci return -EINVAL; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (pp_funcs && pp_funcs->read_sensor) { 45062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 45162306a36Sopenharmony_ci ret = pp_funcs->read_sensor(adev->powerplay.pp_handle, 45262306a36Sopenharmony_ci sensor, 45362306a36Sopenharmony_ci data, 45462306a36Sopenharmony_ci size); 45562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return ret; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ciint amdgpu_dpm_get_apu_thermal_limit(struct amdgpu_device *adev, uint32_t *limit) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 46462306a36Sopenharmony_ci int ret = -EINVAL; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (pp_funcs && pp_funcs->get_apu_thermal_limit) { 46762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 46862306a36Sopenharmony_ci ret = pp_funcs->get_apu_thermal_limit(adev->powerplay.pp_handle, limit); 46962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return ret; 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ciint amdgpu_dpm_set_apu_thermal_limit(struct amdgpu_device *adev, uint32_t limit) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 47862306a36Sopenharmony_ci int ret = -EINVAL; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci if (pp_funcs && pp_funcs->set_apu_thermal_limit) { 48162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 48262306a36Sopenharmony_ci ret = pp_funcs->set_apu_thermal_limit(adev->powerplay.pp_handle, limit); 48362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci return ret; 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_civoid amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 49262306a36Sopenharmony_ci int i; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (!adev->pm.dpm_enabled) 49562306a36Sopenharmony_ci return; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci if (!pp_funcs->pm_compute_clocks) 49862306a36Sopenharmony_ci return; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci if (adev->mode_info.num_crtc) 50162306a36Sopenharmony_ci amdgpu_display_bandwidth_update(adev); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 50462306a36Sopenharmony_ci struct amdgpu_ring *ring = adev->rings[i]; 50562306a36Sopenharmony_ci if (ring && ring->sched.ready) 50662306a36Sopenharmony_ci amdgpu_fence_wait_empty(ring); 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 51062306a36Sopenharmony_ci pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); 51162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_civoid amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci int ret = 0; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (adev->family == AMDGPU_FAMILY_SI) { 51962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 52062306a36Sopenharmony_ci if (enable) { 52162306a36Sopenharmony_ci adev->pm.dpm.uvd_active = true; 52262306a36Sopenharmony_ci adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; 52362306a36Sopenharmony_ci } else { 52462306a36Sopenharmony_ci adev->pm.dpm.uvd_active = false; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci amdgpu_dpm_compute_clocks(adev); 52962306a36Sopenharmony_ci return; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 53362306a36Sopenharmony_ci if (ret) 53462306a36Sopenharmony_ci DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", 53562306a36Sopenharmony_ci enable ? "enable" : "disable", ret); 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_civoid amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci int ret = 0; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (adev->family == AMDGPU_FAMILY_SI) { 54362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 54462306a36Sopenharmony_ci if (enable) { 54562306a36Sopenharmony_ci adev->pm.dpm.vce_active = true; 54662306a36Sopenharmony_ci /* XXX select vce level based on ring/task */ 54762306a36Sopenharmony_ci adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; 54862306a36Sopenharmony_ci } else { 54962306a36Sopenharmony_ci adev->pm.dpm.vce_active = false; 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci amdgpu_dpm_compute_clocks(adev); 55462306a36Sopenharmony_ci return; 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); 55862306a36Sopenharmony_ci if (ret) 55962306a36Sopenharmony_ci DRM_ERROR("Dpm %s vce failed, ret = %d. \n", 56062306a36Sopenharmony_ci enable ? "enable" : "disable", ret); 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_civoid amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) 56462306a36Sopenharmony_ci{ 56562306a36Sopenharmony_ci int ret = 0; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); 56862306a36Sopenharmony_ci if (ret) 56962306a36Sopenharmony_ci DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", 57062306a36Sopenharmony_ci enable ? "enable" : "disable", ret); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ciint amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) 57462306a36Sopenharmony_ci{ 57562306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 57662306a36Sopenharmony_ci int r = 0; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->load_firmware) 57962306a36Sopenharmony_ci return 0; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 58262306a36Sopenharmony_ci r = pp_funcs->load_firmware(adev->powerplay.pp_handle); 58362306a36Sopenharmony_ci if (r) { 58462306a36Sopenharmony_ci pr_err("smu firmware loading failed\n"); 58562306a36Sopenharmony_ci goto out; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (smu_version) 58962306a36Sopenharmony_ci *smu_version = adev->pm.fw_version; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ciout: 59262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 59362306a36Sopenharmony_ci return r; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ciint amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) 59762306a36Sopenharmony_ci{ 59862306a36Sopenharmony_ci int ret = 0; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (is_support_sw_smu(adev)) { 60162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 60262306a36Sopenharmony_ci ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle, 60362306a36Sopenharmony_ci enable); 60462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci return ret; 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ciint amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 61362306a36Sopenharmony_ci int ret = 0; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 61662306a36Sopenharmony_ci return -EOPNOTSUPP; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 61962306a36Sopenharmony_ci ret = smu_send_hbm_bad_pages_num(smu, size); 62062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return ret; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciint amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 62862306a36Sopenharmony_ci int ret = 0; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 63162306a36Sopenharmony_ci return -EOPNOTSUPP; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 63462306a36Sopenharmony_ci ret = smu_send_hbm_bad_channel_flag(smu, size); 63562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return ret; 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ciint amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, 64162306a36Sopenharmony_ci enum pp_clock_type type, 64262306a36Sopenharmony_ci uint32_t *min, 64362306a36Sopenharmony_ci uint32_t *max) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci int ret = 0; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (type != PP_SCLK) 64862306a36Sopenharmony_ci return -EINVAL; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 65162306a36Sopenharmony_ci return -EOPNOTSUPP; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 65462306a36Sopenharmony_ci ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle, 65562306a36Sopenharmony_ci SMU_SCLK, 65662306a36Sopenharmony_ci min, 65762306a36Sopenharmony_ci max); 65862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci return ret; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ciint amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, 66462306a36Sopenharmony_ci enum pp_clock_type type, 66562306a36Sopenharmony_ci uint32_t min, 66662306a36Sopenharmony_ci uint32_t max) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 66962306a36Sopenharmony_ci int ret = 0; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (type != PP_SCLK) 67262306a36Sopenharmony_ci return -EINVAL; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 67562306a36Sopenharmony_ci return -EOPNOTSUPP; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 67862306a36Sopenharmony_ci ret = smu_set_soft_freq_range(smu, 67962306a36Sopenharmony_ci SMU_SCLK, 68062306a36Sopenharmony_ci min, 68162306a36Sopenharmony_ci max); 68262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return ret; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ciint amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 69062306a36Sopenharmony_ci int ret = 0; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 69362306a36Sopenharmony_ci return 0; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 69662306a36Sopenharmony_ci ret = smu_write_watermarks_table(smu); 69762306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci return ret; 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ciint amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, 70362306a36Sopenharmony_ci enum smu_event_type event, 70462306a36Sopenharmony_ci uint64_t event_arg) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 70762306a36Sopenharmony_ci int ret = 0; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 71062306a36Sopenharmony_ci return -EOPNOTSUPP; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 71362306a36Sopenharmony_ci ret = smu_wait_for_event(smu, event, event_arg); 71462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci return ret; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ciint amdgpu_dpm_set_residency_gfxoff(struct amdgpu_device *adev, bool value) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 72262306a36Sopenharmony_ci int ret = 0; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 72562306a36Sopenharmony_ci return -EOPNOTSUPP; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 72862306a36Sopenharmony_ci ret = smu_set_residency_gfxoff(smu, value); 72962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci return ret; 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ciint amdgpu_dpm_get_residency_gfxoff(struct amdgpu_device *adev, u32 *value) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 73762306a36Sopenharmony_ci int ret = 0; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 74062306a36Sopenharmony_ci return -EOPNOTSUPP; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 74362306a36Sopenharmony_ci ret = smu_get_residency_gfxoff(smu, value); 74462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci return ret; 74762306a36Sopenharmony_ci} 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ciint amdgpu_dpm_get_entrycount_gfxoff(struct amdgpu_device *adev, u64 *value) 75062306a36Sopenharmony_ci{ 75162306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 75262306a36Sopenharmony_ci int ret = 0; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 75562306a36Sopenharmony_ci return -EOPNOTSUPP; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 75862306a36Sopenharmony_ci ret = smu_get_entrycount_gfxoff(smu, value); 75962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return ret; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ciint amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 76762306a36Sopenharmony_ci int ret = 0; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 77062306a36Sopenharmony_ci return -EOPNOTSUPP; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 77362306a36Sopenharmony_ci ret = smu_get_status_gfxoff(smu, value); 77462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci return ret; 77762306a36Sopenharmony_ci} 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ciuint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 78462306a36Sopenharmony_ci return 0; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return atomic64_read(&smu->throttle_int_counter); 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci/* amdgpu_dpm_gfx_state_change - Handle gfx power state change set 79062306a36Sopenharmony_ci * @adev: amdgpu_device pointer 79162306a36Sopenharmony_ci * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) 79262306a36Sopenharmony_ci * 79362306a36Sopenharmony_ci */ 79462306a36Sopenharmony_civoid amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, 79562306a36Sopenharmony_ci enum gfx_change_state state) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 79862306a36Sopenharmony_ci if (adev->powerplay.pp_funcs && 79962306a36Sopenharmony_ci adev->powerplay.pp_funcs->gfx_state_change_set) 80062306a36Sopenharmony_ci ((adev)->powerplay.pp_funcs->gfx_state_change_set( 80162306a36Sopenharmony_ci (adev)->powerplay.pp_handle, state)); 80262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 80362306a36Sopenharmony_ci} 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ciint amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, 80662306a36Sopenharmony_ci void *umc_ecc) 80762306a36Sopenharmony_ci{ 80862306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 80962306a36Sopenharmony_ci int ret = 0; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 81262306a36Sopenharmony_ci return -EOPNOTSUPP; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 81562306a36Sopenharmony_ci ret = smu_get_ecc_info(smu, umc_ecc); 81662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci return ret; 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_cistruct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, 82262306a36Sopenharmony_ci uint32_t idx) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 82562306a36Sopenharmony_ci struct amd_vce_state *vstate = NULL; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (!pp_funcs->get_vce_clock_state) 82862306a36Sopenharmony_ci return NULL; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 83162306a36Sopenharmony_ci vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, 83262306a36Sopenharmony_ci idx); 83362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci return vstate; 83662306a36Sopenharmony_ci} 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_civoid amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, 83962306a36Sopenharmony_ci enum amd_pm_state_type *state) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (!pp_funcs->get_current_power_state) { 84662306a36Sopenharmony_ci *state = adev->pm.dpm.user_state; 84762306a36Sopenharmony_ci goto out; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); 85162306a36Sopenharmony_ci if (*state < POWER_STATE_TYPE_DEFAULT || 85262306a36Sopenharmony_ci *state > POWER_STATE_TYPE_INTERNAL_3DPERF) 85362306a36Sopenharmony_ci *state = adev->pm.dpm.user_state; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ciout: 85662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_civoid amdgpu_dpm_set_power_state(struct amdgpu_device *adev, 86062306a36Sopenharmony_ci enum amd_pm_state_type state) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 86362306a36Sopenharmony_ci adev->pm.dpm.user_state = state; 86462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci if (is_support_sw_smu(adev)) 86762306a36Sopenharmony_ci return; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci if (amdgpu_dpm_dispatch_task(adev, 87062306a36Sopenharmony_ci AMD_PP_TASK_ENABLE_USER_STATE, 87162306a36Sopenharmony_ci &state) == -EOPNOTSUPP) 87262306a36Sopenharmony_ci amdgpu_dpm_compute_clocks(adev); 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cienum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 87862306a36Sopenharmony_ci enum amd_dpm_forced_level level; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (!pp_funcs) 88162306a36Sopenharmony_ci return AMD_DPM_FORCED_LEVEL_AUTO; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 88462306a36Sopenharmony_ci if (pp_funcs->get_performance_level) 88562306a36Sopenharmony_ci level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); 88662306a36Sopenharmony_ci else 88762306a36Sopenharmony_ci level = adev->pm.dpm.forced_level; 88862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci return level; 89162306a36Sopenharmony_ci} 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ciint amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, 89462306a36Sopenharmony_ci enum amd_dpm_forced_level level) 89562306a36Sopenharmony_ci{ 89662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 89762306a36Sopenharmony_ci enum amd_dpm_forced_level current_level; 89862306a36Sopenharmony_ci uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | 89962306a36Sopenharmony_ci AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | 90062306a36Sopenharmony_ci AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | 90162306a36Sopenharmony_ci AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci if (!pp_funcs || !pp_funcs->force_performance_level) 90462306a36Sopenharmony_ci return 0; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci if (adev->pm.dpm.thermal_active) 90762306a36Sopenharmony_ci return -EINVAL; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci current_level = amdgpu_dpm_get_performance_level(adev); 91062306a36Sopenharmony_ci if (current_level == level) 91162306a36Sopenharmony_ci return 0; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci if (adev->asic_type == CHIP_RAVEN) { 91462306a36Sopenharmony_ci if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { 91562306a36Sopenharmony_ci if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && 91662306a36Sopenharmony_ci level == AMD_DPM_FORCED_LEVEL_MANUAL) 91762306a36Sopenharmony_ci amdgpu_gfx_off_ctrl(adev, false); 91862306a36Sopenharmony_ci else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && 91962306a36Sopenharmony_ci level != AMD_DPM_FORCED_LEVEL_MANUAL) 92062306a36Sopenharmony_ci amdgpu_gfx_off_ctrl(adev, true); 92162306a36Sopenharmony_ci } 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci if (!(current_level & profile_mode_mask) && 92562306a36Sopenharmony_ci (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 92662306a36Sopenharmony_ci return -EINVAL; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (!(current_level & profile_mode_mask) && 92962306a36Sopenharmony_ci (level & profile_mode_mask)) { 93062306a36Sopenharmony_ci /* enter UMD Pstate */ 93162306a36Sopenharmony_ci amdgpu_device_ip_set_powergating_state(adev, 93262306a36Sopenharmony_ci AMD_IP_BLOCK_TYPE_GFX, 93362306a36Sopenharmony_ci AMD_PG_STATE_UNGATE); 93462306a36Sopenharmony_ci amdgpu_device_ip_set_clockgating_state(adev, 93562306a36Sopenharmony_ci AMD_IP_BLOCK_TYPE_GFX, 93662306a36Sopenharmony_ci AMD_CG_STATE_UNGATE); 93762306a36Sopenharmony_ci } else if ((current_level & profile_mode_mask) && 93862306a36Sopenharmony_ci !(level & profile_mode_mask)) { 93962306a36Sopenharmony_ci /* exit UMD Pstate */ 94062306a36Sopenharmony_ci amdgpu_device_ip_set_clockgating_state(adev, 94162306a36Sopenharmony_ci AMD_IP_BLOCK_TYPE_GFX, 94262306a36Sopenharmony_ci AMD_CG_STATE_GATE); 94362306a36Sopenharmony_ci amdgpu_device_ip_set_powergating_state(adev, 94462306a36Sopenharmony_ci AMD_IP_BLOCK_TYPE_GFX, 94562306a36Sopenharmony_ci AMD_PG_STATE_GATE); 94662306a36Sopenharmony_ci } 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, 95162306a36Sopenharmony_ci level)) { 95262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 95362306a36Sopenharmony_ci return -EINVAL; 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci adev->pm.dpm.forced_level = level; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci return 0; 96162306a36Sopenharmony_ci} 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ciint amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, 96462306a36Sopenharmony_ci struct pp_states_info *states) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 96762306a36Sopenharmony_ci int ret = 0; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci if (!pp_funcs->get_pp_num_states) 97062306a36Sopenharmony_ci return -EOPNOTSUPP; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 97362306a36Sopenharmony_ci ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, 97462306a36Sopenharmony_ci states); 97562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci return ret; 97862306a36Sopenharmony_ci} 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ciint amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, 98162306a36Sopenharmony_ci enum amd_pp_task task_id, 98262306a36Sopenharmony_ci enum amd_pm_state_type *user_state) 98362306a36Sopenharmony_ci{ 98462306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 98562306a36Sopenharmony_ci int ret = 0; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci if (!pp_funcs->dispatch_tasks) 98862306a36Sopenharmony_ci return -EOPNOTSUPP; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 99162306a36Sopenharmony_ci ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, 99262306a36Sopenharmony_ci task_id, 99362306a36Sopenharmony_ci user_state); 99462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci return ret; 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ciint amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 100262306a36Sopenharmony_ci int ret = 0; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci if (!pp_funcs->get_pp_table) 100562306a36Sopenharmony_ci return 0; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 100862306a36Sopenharmony_ci ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, 100962306a36Sopenharmony_ci table); 101062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci return ret; 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ciint amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, 101662306a36Sopenharmony_ci uint32_t type, 101762306a36Sopenharmony_ci long *input, 101862306a36Sopenharmony_ci uint32_t size) 101962306a36Sopenharmony_ci{ 102062306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 102162306a36Sopenharmony_ci int ret = 0; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci if (!pp_funcs->set_fine_grain_clk_vol) 102462306a36Sopenharmony_ci return 0; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 102762306a36Sopenharmony_ci ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, 102862306a36Sopenharmony_ci type, 102962306a36Sopenharmony_ci input, 103062306a36Sopenharmony_ci size); 103162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci return ret; 103462306a36Sopenharmony_ci} 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ciint amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, 103762306a36Sopenharmony_ci uint32_t type, 103862306a36Sopenharmony_ci long *input, 103962306a36Sopenharmony_ci uint32_t size) 104062306a36Sopenharmony_ci{ 104162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 104262306a36Sopenharmony_ci int ret = 0; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci if (!pp_funcs->odn_edit_dpm_table) 104562306a36Sopenharmony_ci return 0; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 104862306a36Sopenharmony_ci ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, 104962306a36Sopenharmony_ci type, 105062306a36Sopenharmony_ci input, 105162306a36Sopenharmony_ci size); 105262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci return ret; 105562306a36Sopenharmony_ci} 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ciint amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, 105862306a36Sopenharmony_ci enum pp_clock_type type, 105962306a36Sopenharmony_ci char *buf) 106062306a36Sopenharmony_ci{ 106162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 106262306a36Sopenharmony_ci int ret = 0; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci if (!pp_funcs->print_clock_levels) 106562306a36Sopenharmony_ci return 0; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 106862306a36Sopenharmony_ci ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle, 106962306a36Sopenharmony_ci type, 107062306a36Sopenharmony_ci buf); 107162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci return ret; 107462306a36Sopenharmony_ci} 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ciint amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, 107762306a36Sopenharmony_ci enum pp_clock_type type, 107862306a36Sopenharmony_ci char *buf, 107962306a36Sopenharmony_ci int *offset) 108062306a36Sopenharmony_ci{ 108162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 108262306a36Sopenharmony_ci int ret = 0; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci if (!pp_funcs->emit_clock_levels) 108562306a36Sopenharmony_ci return -ENOENT; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 108862306a36Sopenharmony_ci ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle, 108962306a36Sopenharmony_ci type, 109062306a36Sopenharmony_ci buf, 109162306a36Sopenharmony_ci offset); 109262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci return ret; 109562306a36Sopenharmony_ci} 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ciint amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, 109862306a36Sopenharmony_ci uint64_t ppfeature_masks) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 110162306a36Sopenharmony_ci int ret = 0; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci if (!pp_funcs->set_ppfeature_status) 110462306a36Sopenharmony_ci return 0; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 110762306a36Sopenharmony_ci ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, 110862306a36Sopenharmony_ci ppfeature_masks); 110962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci return ret; 111262306a36Sopenharmony_ci} 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ciint amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) 111562306a36Sopenharmony_ci{ 111662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 111762306a36Sopenharmony_ci int ret = 0; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci if (!pp_funcs->get_ppfeature_status) 112062306a36Sopenharmony_ci return 0; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 112362306a36Sopenharmony_ci ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, 112462306a36Sopenharmony_ci buf); 112562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci return ret; 112862306a36Sopenharmony_ci} 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ciint amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, 113162306a36Sopenharmony_ci enum pp_clock_type type, 113262306a36Sopenharmony_ci uint32_t mask) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 113562306a36Sopenharmony_ci int ret = 0; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci if (!pp_funcs->force_clock_level) 113862306a36Sopenharmony_ci return 0; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 114162306a36Sopenharmony_ci ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle, 114262306a36Sopenharmony_ci type, 114362306a36Sopenharmony_ci mask); 114462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci return ret; 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ciint amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 115262306a36Sopenharmony_ci int ret = 0; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci if (!pp_funcs->get_sclk_od) 115562306a36Sopenharmony_ci return 0; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 115862306a36Sopenharmony_ci ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle); 115962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci return ret; 116262306a36Sopenharmony_ci} 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ciint amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) 116562306a36Sopenharmony_ci{ 116662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci if (is_support_sw_smu(adev)) 116962306a36Sopenharmony_ci return 0; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 117262306a36Sopenharmony_ci if (pp_funcs->set_sclk_od) 117362306a36Sopenharmony_ci pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); 117462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci if (amdgpu_dpm_dispatch_task(adev, 117762306a36Sopenharmony_ci AMD_PP_TASK_READJUST_POWER_STATE, 117862306a36Sopenharmony_ci NULL) == -EOPNOTSUPP) { 117962306a36Sopenharmony_ci adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 118062306a36Sopenharmony_ci amdgpu_dpm_compute_clocks(adev); 118162306a36Sopenharmony_ci } 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci return 0; 118462306a36Sopenharmony_ci} 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ciint amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 118962306a36Sopenharmony_ci int ret = 0; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (!pp_funcs->get_mclk_od) 119262306a36Sopenharmony_ci return 0; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 119562306a36Sopenharmony_ci ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle); 119662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci return ret; 119962306a36Sopenharmony_ci} 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ciint amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) 120262306a36Sopenharmony_ci{ 120362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci if (is_support_sw_smu(adev)) 120662306a36Sopenharmony_ci return 0; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 120962306a36Sopenharmony_ci if (pp_funcs->set_mclk_od) 121062306a36Sopenharmony_ci pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); 121162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci if (amdgpu_dpm_dispatch_task(adev, 121462306a36Sopenharmony_ci AMD_PP_TASK_READJUST_POWER_STATE, 121562306a36Sopenharmony_ci NULL) == -EOPNOTSUPP) { 121662306a36Sopenharmony_ci adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 121762306a36Sopenharmony_ci amdgpu_dpm_compute_clocks(adev); 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci return 0; 122162306a36Sopenharmony_ci} 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ciint amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, 122462306a36Sopenharmony_ci char *buf) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 122762306a36Sopenharmony_ci int ret = 0; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci if (!pp_funcs->get_power_profile_mode) 123062306a36Sopenharmony_ci return -EOPNOTSUPP; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 123362306a36Sopenharmony_ci ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, 123462306a36Sopenharmony_ci buf); 123562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci return ret; 123862306a36Sopenharmony_ci} 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ciint amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, 124162306a36Sopenharmony_ci long *input, uint32_t size) 124262306a36Sopenharmony_ci{ 124362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 124462306a36Sopenharmony_ci int ret = 0; 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci if (!pp_funcs->set_power_profile_mode) 124762306a36Sopenharmony_ci return 0; 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 125062306a36Sopenharmony_ci ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, 125162306a36Sopenharmony_ci input, 125262306a36Sopenharmony_ci size); 125362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci return ret; 125662306a36Sopenharmony_ci} 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ciint amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) 125962306a36Sopenharmony_ci{ 126062306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 126162306a36Sopenharmony_ci int ret = 0; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci if (!pp_funcs->get_gpu_metrics) 126462306a36Sopenharmony_ci return 0; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 126762306a36Sopenharmony_ci ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, 126862306a36Sopenharmony_ci table); 126962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci return ret; 127262306a36Sopenharmony_ci} 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ciint amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, 127562306a36Sopenharmony_ci uint32_t *fan_mode) 127662306a36Sopenharmony_ci{ 127762306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 127862306a36Sopenharmony_ci int ret = 0; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci if (!pp_funcs->get_fan_control_mode) 128162306a36Sopenharmony_ci return -EOPNOTSUPP; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 128462306a36Sopenharmony_ci ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, 128562306a36Sopenharmony_ci fan_mode); 128662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci return ret; 128962306a36Sopenharmony_ci} 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ciint amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, 129262306a36Sopenharmony_ci uint32_t speed) 129362306a36Sopenharmony_ci{ 129462306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 129562306a36Sopenharmony_ci int ret = 0; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci if (!pp_funcs->set_fan_speed_pwm) 129862306a36Sopenharmony_ci return -EOPNOTSUPP; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 130162306a36Sopenharmony_ci ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, 130262306a36Sopenharmony_ci speed); 130362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci return ret; 130662306a36Sopenharmony_ci} 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ciint amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, 130962306a36Sopenharmony_ci uint32_t *speed) 131062306a36Sopenharmony_ci{ 131162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 131262306a36Sopenharmony_ci int ret = 0; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci if (!pp_funcs->get_fan_speed_pwm) 131562306a36Sopenharmony_ci return -EOPNOTSUPP; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 131862306a36Sopenharmony_ci ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, 131962306a36Sopenharmony_ci speed); 132062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci return ret; 132362306a36Sopenharmony_ci} 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ciint amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, 132662306a36Sopenharmony_ci uint32_t *speed) 132762306a36Sopenharmony_ci{ 132862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 132962306a36Sopenharmony_ci int ret = 0; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci if (!pp_funcs->get_fan_speed_rpm) 133262306a36Sopenharmony_ci return -EOPNOTSUPP; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 133562306a36Sopenharmony_ci ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, 133662306a36Sopenharmony_ci speed); 133762306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci return ret; 134062306a36Sopenharmony_ci} 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ciint amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, 134362306a36Sopenharmony_ci uint32_t speed) 134462306a36Sopenharmony_ci{ 134562306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 134662306a36Sopenharmony_ci int ret = 0; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci if (!pp_funcs->set_fan_speed_rpm) 134962306a36Sopenharmony_ci return -EOPNOTSUPP; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 135262306a36Sopenharmony_ci ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, 135362306a36Sopenharmony_ci speed); 135462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci return ret; 135762306a36Sopenharmony_ci} 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ciint amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, 136062306a36Sopenharmony_ci uint32_t mode) 136162306a36Sopenharmony_ci{ 136262306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 136362306a36Sopenharmony_ci int ret = 0; 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci if (!pp_funcs->set_fan_control_mode) 136662306a36Sopenharmony_ci return -EOPNOTSUPP; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 136962306a36Sopenharmony_ci ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, 137062306a36Sopenharmony_ci mode); 137162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci return ret; 137462306a36Sopenharmony_ci} 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ciint amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, 137762306a36Sopenharmony_ci uint32_t *limit, 137862306a36Sopenharmony_ci enum pp_power_limit_level pp_limit_level, 137962306a36Sopenharmony_ci enum pp_power_type power_type) 138062306a36Sopenharmony_ci{ 138162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 138262306a36Sopenharmony_ci int ret = 0; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci if (!pp_funcs->get_power_limit) 138562306a36Sopenharmony_ci return -ENODATA; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 138862306a36Sopenharmony_ci ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle, 138962306a36Sopenharmony_ci limit, 139062306a36Sopenharmony_ci pp_limit_level, 139162306a36Sopenharmony_ci power_type); 139262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci return ret; 139562306a36Sopenharmony_ci} 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ciint amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, 139862306a36Sopenharmony_ci uint32_t limit) 139962306a36Sopenharmony_ci{ 140062306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 140162306a36Sopenharmony_ci int ret = 0; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci if (!pp_funcs->set_power_limit) 140462306a36Sopenharmony_ci return -EINVAL; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 140762306a36Sopenharmony_ci ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle, 140862306a36Sopenharmony_ci limit); 140962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci return ret; 141262306a36Sopenharmony_ci} 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ciint amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) 141562306a36Sopenharmony_ci{ 141662306a36Sopenharmony_ci bool cclk_dpm_supported = false; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 141962306a36Sopenharmony_ci return false; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 142262306a36Sopenharmony_ci cclk_dpm_supported = is_support_cclk_dpm(adev); 142362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci return (int)cclk_dpm_supported; 142662306a36Sopenharmony_ci} 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ciint amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, 142962306a36Sopenharmony_ci struct seq_file *m) 143062306a36Sopenharmony_ci{ 143162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci if (!pp_funcs->debugfs_print_current_performance_level) 143462306a36Sopenharmony_ci return -EOPNOTSUPP; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 143762306a36Sopenharmony_ci pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, 143862306a36Sopenharmony_ci m); 143962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci return 0; 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ciint amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, 144562306a36Sopenharmony_ci void **addr, 144662306a36Sopenharmony_ci size_t *size) 144762306a36Sopenharmony_ci{ 144862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 144962306a36Sopenharmony_ci int ret = 0; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci if (!pp_funcs->get_smu_prv_buf_details) 145262306a36Sopenharmony_ci return -ENOSYS; 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 145562306a36Sopenharmony_ci ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, 145662306a36Sopenharmony_ci addr, 145762306a36Sopenharmony_ci size); 145862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci return ret; 146162306a36Sopenharmony_ci} 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ciint amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) 146462306a36Sopenharmony_ci{ 146562306a36Sopenharmony_ci if (is_support_sw_smu(adev)) { 146662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci return (smu->od_enabled || smu->is_apu); 146962306a36Sopenharmony_ci } else { 147062306a36Sopenharmony_ci struct pp_hwmgr *hwmgr; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci /* 147362306a36Sopenharmony_ci * dpm on some legacy asics don't carry od_enabled member 147462306a36Sopenharmony_ci * as its pp_handle is casted directly from adev. 147562306a36Sopenharmony_ci */ 147662306a36Sopenharmony_ci if (amdgpu_dpm_is_legacy_dpm(adev)) 147762306a36Sopenharmony_ci return false; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci hwmgr = (struct pp_hwmgr *)adev->powerplay.pp_handle; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci return hwmgr->od_enabled; 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_ci} 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ciint amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, 148662306a36Sopenharmony_ci const char *buf, 148762306a36Sopenharmony_ci size_t size) 148862306a36Sopenharmony_ci{ 148962306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 149062306a36Sopenharmony_ci int ret = 0; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci if (!pp_funcs->set_pp_table) 149362306a36Sopenharmony_ci return -EOPNOTSUPP; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 149662306a36Sopenharmony_ci ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle, 149762306a36Sopenharmony_ci buf, 149862306a36Sopenharmony_ci size); 149962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci return ret; 150262306a36Sopenharmony_ci} 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ciint amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) 150562306a36Sopenharmony_ci{ 150662306a36Sopenharmony_ci struct smu_context *smu = adev->powerplay.pp_handle; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 150962306a36Sopenharmony_ci return INT_MAX; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci return smu->cpu_core_num; 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_civoid amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) 151562306a36Sopenharmony_ci{ 151662306a36Sopenharmony_ci if (!is_support_sw_smu(adev)) 151762306a36Sopenharmony_ci return; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci amdgpu_smu_stb_debug_fs_init(adev); 152062306a36Sopenharmony_ci} 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ciint amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, 152362306a36Sopenharmony_ci const struct amd_pp_display_configuration *input) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 152662306a36Sopenharmony_ci int ret = 0; 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci if (!pp_funcs->display_configuration_change) 152962306a36Sopenharmony_ci return 0; 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 153262306a36Sopenharmony_ci ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle, 153362306a36Sopenharmony_ci input); 153462306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci return ret; 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ciint amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, 154062306a36Sopenharmony_ci enum amd_pp_clock_type type, 154162306a36Sopenharmony_ci struct amd_pp_clocks *clocks) 154262306a36Sopenharmony_ci{ 154362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 154462306a36Sopenharmony_ci int ret = 0; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci if (!pp_funcs->get_clock_by_type) 154762306a36Sopenharmony_ci return 0; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 155062306a36Sopenharmony_ci ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, 155162306a36Sopenharmony_ci type, 155262306a36Sopenharmony_ci clocks); 155362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci return ret; 155662306a36Sopenharmony_ci} 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ciint amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, 155962306a36Sopenharmony_ci struct amd_pp_simple_clock_info *clocks) 156062306a36Sopenharmony_ci{ 156162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 156262306a36Sopenharmony_ci int ret = 0; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci if (!pp_funcs->get_display_mode_validation_clocks) 156562306a36Sopenharmony_ci return 0; 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 156862306a36Sopenharmony_ci ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, 156962306a36Sopenharmony_ci clocks); 157062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci return ret; 157362306a36Sopenharmony_ci} 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ciint amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, 157662306a36Sopenharmony_ci enum amd_pp_clock_type type, 157762306a36Sopenharmony_ci struct pp_clock_levels_with_latency *clocks) 157862306a36Sopenharmony_ci{ 157962306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 158062306a36Sopenharmony_ci int ret = 0; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci if (!pp_funcs->get_clock_by_type_with_latency) 158362306a36Sopenharmony_ci return 0; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 158662306a36Sopenharmony_ci ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, 158762306a36Sopenharmony_ci type, 158862306a36Sopenharmony_ci clocks); 158962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci return ret; 159262306a36Sopenharmony_ci} 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ciint amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, 159562306a36Sopenharmony_ci enum amd_pp_clock_type type, 159662306a36Sopenharmony_ci struct pp_clock_levels_with_voltage *clocks) 159762306a36Sopenharmony_ci{ 159862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 159962306a36Sopenharmony_ci int ret = 0; 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci if (!pp_funcs->get_clock_by_type_with_voltage) 160262306a36Sopenharmony_ci return 0; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 160562306a36Sopenharmony_ci ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, 160662306a36Sopenharmony_ci type, 160762306a36Sopenharmony_ci clocks); 160862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci return ret; 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ciint amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, 161462306a36Sopenharmony_ci void *clock_ranges) 161562306a36Sopenharmony_ci{ 161662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 161762306a36Sopenharmony_ci int ret = 0; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci if (!pp_funcs->set_watermarks_for_clocks_ranges) 162062306a36Sopenharmony_ci return -EOPNOTSUPP; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 162362306a36Sopenharmony_ci ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, 162462306a36Sopenharmony_ci clock_ranges); 162562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci return ret; 162862306a36Sopenharmony_ci} 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ciint amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, 163162306a36Sopenharmony_ci struct pp_display_clock_request *clock) 163262306a36Sopenharmony_ci{ 163362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 163462306a36Sopenharmony_ci int ret = 0; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci if (!pp_funcs->display_clock_voltage_request) 163762306a36Sopenharmony_ci return -EOPNOTSUPP; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 164062306a36Sopenharmony_ci ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, 164162306a36Sopenharmony_ci clock); 164262306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci return ret; 164562306a36Sopenharmony_ci} 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ciint amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, 164862306a36Sopenharmony_ci struct amd_pp_clock_info *clocks) 164962306a36Sopenharmony_ci{ 165062306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 165162306a36Sopenharmony_ci int ret = 0; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci if (!pp_funcs->get_current_clocks) 165462306a36Sopenharmony_ci return -EOPNOTSUPP; 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 165762306a36Sopenharmony_ci ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle, 165862306a36Sopenharmony_ci clocks); 165962306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci return ret; 166262306a36Sopenharmony_ci} 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_civoid amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) 166562306a36Sopenharmony_ci{ 166662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci if (!pp_funcs->notify_smu_enable_pwe) 166962306a36Sopenharmony_ci return; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 167262306a36Sopenharmony_ci pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); 167362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 167462306a36Sopenharmony_ci} 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ciint amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, 167762306a36Sopenharmony_ci uint32_t count) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 168062306a36Sopenharmony_ci int ret = 0; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci if (!pp_funcs->set_active_display_count) 168362306a36Sopenharmony_ci return -EOPNOTSUPP; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 168662306a36Sopenharmony_ci ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle, 168762306a36Sopenharmony_ci count); 168862306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci return ret; 169162306a36Sopenharmony_ci} 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ciint amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, 169462306a36Sopenharmony_ci uint32_t clock) 169562306a36Sopenharmony_ci{ 169662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 169762306a36Sopenharmony_ci int ret = 0; 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci if (!pp_funcs->set_min_deep_sleep_dcefclk) 170062306a36Sopenharmony_ci return -EOPNOTSUPP; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 170362306a36Sopenharmony_ci ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, 170462306a36Sopenharmony_ci clock); 170562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci return ret; 170862306a36Sopenharmony_ci} 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_civoid amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, 171162306a36Sopenharmony_ci uint32_t clock) 171262306a36Sopenharmony_ci{ 171362306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci if (!pp_funcs->set_hard_min_dcefclk_by_freq) 171662306a36Sopenharmony_ci return; 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 171962306a36Sopenharmony_ci pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, 172062306a36Sopenharmony_ci clock); 172162306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 172262306a36Sopenharmony_ci} 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_civoid amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, 172562306a36Sopenharmony_ci uint32_t clock) 172662306a36Sopenharmony_ci{ 172762306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci if (!pp_funcs->set_hard_min_fclk_by_freq) 173062306a36Sopenharmony_ci return; 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 173362306a36Sopenharmony_ci pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, 173462306a36Sopenharmony_ci clock); 173562306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 173662306a36Sopenharmony_ci} 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ciint amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, 173962306a36Sopenharmony_ci bool disable_memory_clock_switch) 174062306a36Sopenharmony_ci{ 174162306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 174262306a36Sopenharmony_ci int ret = 0; 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_ci if (!pp_funcs->display_disable_memory_clock_switch) 174562306a36Sopenharmony_ci return 0; 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 174862306a36Sopenharmony_ci ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, 174962306a36Sopenharmony_ci disable_memory_clock_switch); 175062306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci return ret; 175362306a36Sopenharmony_ci} 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ciint amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, 175662306a36Sopenharmony_ci struct pp_smu_nv_clock_table *max_clocks) 175762306a36Sopenharmony_ci{ 175862306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 175962306a36Sopenharmony_ci int ret = 0; 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_ci if (!pp_funcs->get_max_sustainable_clocks_by_dc) 176262306a36Sopenharmony_ci return -EOPNOTSUPP; 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 176562306a36Sopenharmony_ci ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, 176662306a36Sopenharmony_ci max_clocks); 176762306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci return ret; 177062306a36Sopenharmony_ci} 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_cienum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, 177362306a36Sopenharmony_ci unsigned int *clock_values_in_khz, 177462306a36Sopenharmony_ci unsigned int *num_states) 177562306a36Sopenharmony_ci{ 177662306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 177762306a36Sopenharmony_ci int ret = 0; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci if (!pp_funcs->get_uclk_dpm_states) 178062306a36Sopenharmony_ci return -EOPNOTSUPP; 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 178362306a36Sopenharmony_ci ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, 178462306a36Sopenharmony_ci clock_values_in_khz, 178562306a36Sopenharmony_ci num_states); 178662306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci return ret; 178962306a36Sopenharmony_ci} 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ciint amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, 179262306a36Sopenharmony_ci struct dpm_clocks *clock_table) 179362306a36Sopenharmony_ci{ 179462306a36Sopenharmony_ci const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 179562306a36Sopenharmony_ci int ret = 0; 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci if (!pp_funcs->get_dpm_clock_table) 179862306a36Sopenharmony_ci return -EOPNOTSUPP; 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci mutex_lock(&adev->pm.mutex); 180162306a36Sopenharmony_ci ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, 180262306a36Sopenharmony_ci clock_table); 180362306a36Sopenharmony_ci mutex_unlock(&adev->pm.mutex); 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci return ret; 180662306a36Sopenharmony_ci} 1807