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 230e098bc96SEvan Quan int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) 231e098bc96SEvan Quan { 232e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 233e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 234e098bc96SEvan Quan int ret = 0; 235e098bc96SEvan Quan 2369ab5001aSDarren Powell if (!pp_funcs || !pp_funcs->set_asic_baco_state) 237e098bc96SEvan Quan return -ENOENT; 238e098bc96SEvan Quan 2393712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2403712e7a4SEvan Quan 241e098bc96SEvan Quan /* enter BACO state */ 242e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 243e098bc96SEvan Quan if (ret) 2443712e7a4SEvan Quan goto out; 245e098bc96SEvan Quan 246e098bc96SEvan Quan /* exit BACO state */ 247e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 248e098bc96SEvan Quan 2493712e7a4SEvan Quan out: 2503712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2513712e7a4SEvan Quan return ret; 252e098bc96SEvan Quan } 253e098bc96SEvan Quan 254e098bc96SEvan Quan bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) 255e098bc96SEvan Quan { 256ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 2573712e7a4SEvan Quan bool support_mode1_reset = false; 258e098bc96SEvan Quan 2593712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 2603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2613712e7a4SEvan Quan support_mode1_reset = smu_mode1_reset_is_support(smu); 2623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2633712e7a4SEvan Quan } 264e098bc96SEvan Quan 2653712e7a4SEvan Quan return support_mode1_reset; 266e098bc96SEvan Quan } 267e098bc96SEvan Quan 268e098bc96SEvan Quan int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) 269e098bc96SEvan Quan { 270ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 2713712e7a4SEvan Quan int ret = -EOPNOTSUPP; 272e098bc96SEvan Quan 2733712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 2743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2753712e7a4SEvan Quan ret = smu_mode1_reset(smu); 2763712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2773712e7a4SEvan Quan } 278e098bc96SEvan Quan 2793712e7a4SEvan Quan return ret; 280e098bc96SEvan Quan } 281e098bc96SEvan Quan 282e098bc96SEvan Quan int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, 283e098bc96SEvan Quan enum PP_SMC_POWER_PROFILE type, 284e098bc96SEvan Quan bool en) 285e098bc96SEvan Quan { 286bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 287e098bc96SEvan Quan int ret = 0; 288e098bc96SEvan Quan 2897cf7a392SJingwen Chen if (amdgpu_sriov_vf(adev)) 2907cf7a392SJingwen Chen return 0; 2917cf7a392SJingwen Chen 2923712e7a4SEvan Quan if (pp_funcs && pp_funcs->switch_power_profile) { 2933712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 294bab0f602SDarren Powell ret = pp_funcs->switch_power_profile( 295e098bc96SEvan Quan adev->powerplay.pp_handle, type, en); 2963712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2973712e7a4SEvan Quan } 298e098bc96SEvan Quan 299e098bc96SEvan Quan return ret; 300e098bc96SEvan Quan } 301e098bc96SEvan Quan 302e098bc96SEvan Quan int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, 303e098bc96SEvan Quan uint32_t pstate) 304e098bc96SEvan Quan { 305bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 306e098bc96SEvan Quan int ret = 0; 307e098bc96SEvan Quan 3083712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_xgmi_pstate) { 3093712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 310bab0f602SDarren Powell ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, 311e098bc96SEvan Quan pstate); 3123712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3133712e7a4SEvan Quan } 314e098bc96SEvan Quan 315e098bc96SEvan Quan return ret; 316e098bc96SEvan Quan } 317e098bc96SEvan Quan 318e098bc96SEvan Quan int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, 319e098bc96SEvan Quan uint32_t cstate) 320e098bc96SEvan Quan { 321e098bc96SEvan Quan int ret = 0; 322e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 323e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 324e098bc96SEvan Quan 3253712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_df_cstate) { 3263712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 327e098bc96SEvan Quan ret = pp_funcs->set_df_cstate(pp_handle, cstate); 3283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3293712e7a4SEvan Quan } 330e098bc96SEvan Quan 331e098bc96SEvan Quan return ret; 332e098bc96SEvan Quan } 333e098bc96SEvan Quan 334e098bc96SEvan Quan int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) 335e098bc96SEvan Quan { 336ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 3373712e7a4SEvan Quan int ret = 0; 338e098bc96SEvan Quan 3393712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 3403712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 3413712e7a4SEvan Quan ret = smu_allow_xgmi_power_down(smu, en); 3423712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3433712e7a4SEvan Quan } 344e098bc96SEvan Quan 3453712e7a4SEvan Quan return ret; 346e098bc96SEvan Quan } 347e098bc96SEvan Quan 348e098bc96SEvan Quan int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) 349e098bc96SEvan Quan { 350e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 351e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 352e098bc96SEvan Quan adev->powerplay.pp_funcs; 353e098bc96SEvan Quan int ret = 0; 354e098bc96SEvan Quan 3553712e7a4SEvan Quan if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) { 3563712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 357e098bc96SEvan Quan ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); 3583712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3593712e7a4SEvan Quan } 360e098bc96SEvan Quan 361e098bc96SEvan Quan return ret; 362e098bc96SEvan Quan } 363e098bc96SEvan Quan 364e098bc96SEvan Quan int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, 365e098bc96SEvan Quan uint32_t msg_id) 366e098bc96SEvan Quan { 367e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 368e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 369e098bc96SEvan Quan adev->powerplay.pp_funcs; 370e098bc96SEvan Quan int ret = 0; 371e098bc96SEvan Quan 3723712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_clockgating_by_smu) { 3733712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 374e098bc96SEvan Quan ret = pp_funcs->set_clockgating_by_smu(pp_handle, 375e098bc96SEvan Quan msg_id); 3763712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3773712e7a4SEvan Quan } 378e098bc96SEvan Quan 379e098bc96SEvan Quan return ret; 380e098bc96SEvan Quan } 381e098bc96SEvan Quan 382e098bc96SEvan Quan int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, 383e098bc96SEvan Quan bool acquire) 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 = -EOPNOTSUPP; 389e098bc96SEvan Quan 3903712e7a4SEvan Quan if (pp_funcs && pp_funcs->smu_i2c_bus_access) { 3913712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 392e098bc96SEvan Quan ret = pp_funcs->smu_i2c_bus_access(pp_handle, 393e098bc96SEvan Quan acquire); 3943712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3953712e7a4SEvan Quan } 396e098bc96SEvan Quan 397e098bc96SEvan Quan return ret; 398e098bc96SEvan Quan } 399e098bc96SEvan Quan 400e098bc96SEvan Quan void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) 401e098bc96SEvan Quan { 402e098bc96SEvan Quan if (adev->pm.dpm_enabled) { 403e098bc96SEvan Quan mutex_lock(&adev->pm.mutex); 404e098bc96SEvan Quan if (power_supply_is_system_supplied() > 0) 405e098bc96SEvan Quan adev->pm.ac_power = true; 406e098bc96SEvan Quan else 407e098bc96SEvan Quan adev->pm.ac_power = false; 4083712e7a4SEvan Quan 409e098bc96SEvan Quan if (adev->powerplay.pp_funcs && 410e098bc96SEvan Quan adev->powerplay.pp_funcs->enable_bapm) 411e098bc96SEvan Quan amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); 412e098bc96SEvan Quan 413e098bc96SEvan Quan if (is_support_sw_smu(adev)) 414ebfc2533SEvan Quan smu_set_ac_dc(adev->powerplay.pp_handle); 4153712e7a4SEvan Quan 4163712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 417e098bc96SEvan Quan } 418e098bc96SEvan Quan } 419e098bc96SEvan Quan 420e098bc96SEvan Quan int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, 421e098bc96SEvan Quan void *data, uint32_t *size) 422e098bc96SEvan Quan { 4239ab5001aSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 4243712e7a4SEvan Quan int ret = -EINVAL; 425e098bc96SEvan Quan 426e098bc96SEvan Quan if (!data || !size) 427e098bc96SEvan Quan return -EINVAL; 428e098bc96SEvan Quan 4293712e7a4SEvan Quan if (pp_funcs && pp_funcs->read_sensor) { 4303712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4313712e7a4SEvan Quan ret = pp_funcs->read_sensor(adev->powerplay.pp_handle, 4323712e7a4SEvan Quan sensor, 4333712e7a4SEvan Quan data, 4343712e7a4SEvan Quan size); 4353712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 4363712e7a4SEvan Quan } 437e098bc96SEvan Quan 438e098bc96SEvan Quan return ret; 439e098bc96SEvan Quan } 440e098bc96SEvan Quan 44184176663SEvan Quan void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) 442e098bc96SEvan Quan { 4436ddbd37fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 444a71849cdSEvan Quan int i; 445e098bc96SEvan Quan 446e098bc96SEvan Quan if (!adev->pm.dpm_enabled) 447e098bc96SEvan Quan return; 448e098bc96SEvan Quan 4496ddbd37fSEvan Quan if (!pp_funcs->pm_compute_clocks) 4506ddbd37fSEvan Quan return; 451e098bc96SEvan Quan 452a71849cdSEvan Quan if (adev->mode_info.num_crtc) 453a71849cdSEvan Quan amdgpu_display_bandwidth_update(adev); 454a71849cdSEvan Quan 455a71849cdSEvan Quan for (i = 0; i < AMDGPU_MAX_RINGS; i++) { 456a71849cdSEvan Quan struct amdgpu_ring *ring = adev->rings[i]; 457a71849cdSEvan Quan if (ring && ring->sched.ready) 458a71849cdSEvan Quan amdgpu_fence_wait_empty(ring); 459a71849cdSEvan Quan } 460a71849cdSEvan Quan 4613712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4626ddbd37fSEvan Quan pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); 4633712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 464e098bc96SEvan Quan } 465e098bc96SEvan Quan 466e098bc96SEvan Quan void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) 467e098bc96SEvan Quan { 468e098bc96SEvan Quan int ret = 0; 469e098bc96SEvan Quan 470a71849cdSEvan Quan if (adev->family == AMDGPU_FAMILY_SI) { 471a71849cdSEvan Quan mutex_lock(&adev->pm.mutex); 472a71849cdSEvan Quan if (enable) { 473a71849cdSEvan Quan adev->pm.dpm.uvd_active = true; 474a71849cdSEvan Quan adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; 475a71849cdSEvan Quan } else { 476a71849cdSEvan Quan adev->pm.dpm.uvd_active = false; 477a71849cdSEvan Quan } 478a71849cdSEvan Quan mutex_unlock(&adev->pm.mutex); 479a71849cdSEvan Quan 480a71849cdSEvan Quan amdgpu_dpm_compute_clocks(adev); 481a71849cdSEvan Quan return; 482a71849cdSEvan Quan } 483a71849cdSEvan Quan 484e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 485e098bc96SEvan Quan if (ret) 486e098bc96SEvan Quan DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", 487e098bc96SEvan Quan enable ? "enable" : "disable", ret); 488e098bc96SEvan Quan } 489e098bc96SEvan Quan 490e098bc96SEvan Quan void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) 491e098bc96SEvan Quan { 492e098bc96SEvan Quan int ret = 0; 493e098bc96SEvan Quan 494a71849cdSEvan Quan if (adev->family == AMDGPU_FAMILY_SI) { 495a71849cdSEvan Quan mutex_lock(&adev->pm.mutex); 496a71849cdSEvan Quan if (enable) { 497a71849cdSEvan Quan adev->pm.dpm.vce_active = true; 498a71849cdSEvan Quan /* XXX select vce level based on ring/task */ 499a71849cdSEvan Quan adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; 500a71849cdSEvan Quan } else { 501a71849cdSEvan Quan adev->pm.dpm.vce_active = false; 502a71849cdSEvan Quan } 503a71849cdSEvan Quan mutex_unlock(&adev->pm.mutex); 504a71849cdSEvan Quan 505a71849cdSEvan Quan amdgpu_dpm_compute_clocks(adev); 506a71849cdSEvan Quan return; 507a71849cdSEvan Quan } 508a71849cdSEvan Quan 509e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); 510e098bc96SEvan Quan if (ret) 511e098bc96SEvan Quan DRM_ERROR("Dpm %s vce failed, ret = %d. \n", 512e098bc96SEvan Quan enable ? "enable" : "disable", ret); 513e098bc96SEvan Quan } 514e098bc96SEvan Quan 515e098bc96SEvan Quan void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) 516e098bc96SEvan Quan { 517e098bc96SEvan Quan int ret = 0; 518e098bc96SEvan Quan 519e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); 520e098bc96SEvan Quan if (ret) 521e098bc96SEvan Quan DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", 522e098bc96SEvan Quan enable ? "enable" : "disable", ret); 523e098bc96SEvan Quan } 524e098bc96SEvan Quan 525e098bc96SEvan Quan int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) 526e098bc96SEvan Quan { 5273712e7a4SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 5283712e7a4SEvan Quan int r = 0; 529e098bc96SEvan Quan 5301613f346SFlora Cui if (!pp_funcs || !pp_funcs->load_firmware) 5313712e7a4SEvan Quan return 0; 5323712e7a4SEvan Quan 5333712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5343712e7a4SEvan Quan r = pp_funcs->load_firmware(adev->powerplay.pp_handle); 535e098bc96SEvan Quan if (r) { 536e098bc96SEvan Quan pr_err("smu firmware loading failed\n"); 5373712e7a4SEvan Quan goto out; 538e098bc96SEvan Quan } 5392e4b2f7bSEvan Quan 5402e4b2f7bSEvan Quan if (smu_version) 541e098bc96SEvan Quan *smu_version = adev->pm.fw_version; 5422e4b2f7bSEvan Quan 5433712e7a4SEvan Quan out: 5443712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5453712e7a4SEvan Quan return r; 546e098bc96SEvan Quan } 547bc143d8bSEvan Quan 548bc143d8bSEvan Quan int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) 549bc143d8bSEvan Quan { 5503712e7a4SEvan Quan int ret = 0; 5513712e7a4SEvan Quan 5523712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 5533712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5543712e7a4SEvan Quan ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle, 5553712e7a4SEvan Quan enable); 5563712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5573712e7a4SEvan Quan } 5583712e7a4SEvan Quan 5593712e7a4SEvan Quan return ret; 560bc143d8bSEvan Quan } 561bc143d8bSEvan Quan 562bc143d8bSEvan Quan int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) 563bc143d8bSEvan Quan { 564ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 5653712e7a4SEvan Quan int ret = 0; 566ebfc2533SEvan Quan 56793dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 56893dde6ccSStanley.Yang return -EOPNOTSUPP; 56993dde6ccSStanley.Yang 5703712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5713712e7a4SEvan Quan ret = smu_send_hbm_bad_pages_num(smu, size); 5723712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5733712e7a4SEvan Quan 5743712e7a4SEvan Quan return ret; 575bc143d8bSEvan Quan } 576bc143d8bSEvan Quan 577d510eccfSStanley.Yang int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size) 578d510eccfSStanley.Yang { 579d510eccfSStanley.Yang struct smu_context *smu = adev->powerplay.pp_handle; 580d510eccfSStanley.Yang int ret = 0; 581d510eccfSStanley.Yang 58293dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 58393dde6ccSStanley.Yang return -EOPNOTSUPP; 58493dde6ccSStanley.Yang 585d510eccfSStanley.Yang mutex_lock(&adev->pm.mutex); 586d510eccfSStanley.Yang ret = smu_send_hbm_bad_channel_flag(smu, size); 587d510eccfSStanley.Yang mutex_unlock(&adev->pm.mutex); 588d510eccfSStanley.Yang 589d510eccfSStanley.Yang return ret; 590d510eccfSStanley.Yang } 591d510eccfSStanley.Yang 592bc143d8bSEvan Quan int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, 593bc143d8bSEvan Quan enum pp_clock_type type, 594bc143d8bSEvan Quan uint32_t *min, 595bc143d8bSEvan Quan uint32_t *max) 596bc143d8bSEvan Quan { 5973712e7a4SEvan Quan int ret = 0; 5983712e7a4SEvan Quan 5993712e7a4SEvan Quan if (type != PP_SCLK) 6003712e7a4SEvan Quan return -EINVAL; 6013712e7a4SEvan Quan 602bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 603bc143d8bSEvan Quan return -EOPNOTSUPP; 604bc143d8bSEvan Quan 6053712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6063712e7a4SEvan Quan ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle, 6073712e7a4SEvan Quan SMU_SCLK, 6083712e7a4SEvan Quan min, 6093712e7a4SEvan Quan max); 6103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6113712e7a4SEvan Quan 6123712e7a4SEvan Quan return ret; 613bc143d8bSEvan Quan } 614bc143d8bSEvan Quan 615bc143d8bSEvan Quan int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, 616bc143d8bSEvan Quan enum pp_clock_type type, 617bc143d8bSEvan Quan uint32_t min, 618bc143d8bSEvan Quan uint32_t max) 619bc143d8bSEvan Quan { 620ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6213712e7a4SEvan Quan int ret = 0; 6223712e7a4SEvan Quan 6233712e7a4SEvan Quan if (type != PP_SCLK) 6243712e7a4SEvan Quan return -EINVAL; 625ebfc2533SEvan Quan 626bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 627bc143d8bSEvan Quan return -EOPNOTSUPP; 628bc143d8bSEvan Quan 6293712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6303712e7a4SEvan Quan ret = smu_set_soft_freq_range(smu, 6313712e7a4SEvan Quan SMU_SCLK, 6323712e7a4SEvan Quan min, 6333712e7a4SEvan Quan max); 6343712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6353712e7a4SEvan Quan 6363712e7a4SEvan Quan return ret; 637bc143d8bSEvan Quan } 638bc143d8bSEvan Quan 63913f5dbd6SEvan Quan int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) 64013f5dbd6SEvan Quan { 641ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6423712e7a4SEvan Quan int ret = 0; 643ebfc2533SEvan Quan 64413f5dbd6SEvan Quan if (!is_support_sw_smu(adev)) 64513f5dbd6SEvan Quan return 0; 64613f5dbd6SEvan Quan 6473712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6483712e7a4SEvan Quan ret = smu_write_watermarks_table(smu); 6493712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6503712e7a4SEvan Quan 6513712e7a4SEvan Quan return ret; 65213f5dbd6SEvan Quan } 65313f5dbd6SEvan Quan 654bc143d8bSEvan Quan int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, 655bc143d8bSEvan Quan enum smu_event_type event, 656bc143d8bSEvan Quan uint64_t event_arg) 657bc143d8bSEvan Quan { 658ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6593712e7a4SEvan Quan int ret = 0; 660ebfc2533SEvan Quan 661bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 662bc143d8bSEvan Quan return -EOPNOTSUPP; 663bc143d8bSEvan Quan 6643712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6653712e7a4SEvan Quan ret = smu_wait_for_event(smu, event, event_arg); 6663712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6673712e7a4SEvan Quan 6683712e7a4SEvan Quan return ret; 669bc143d8bSEvan Quan } 670bc143d8bSEvan Quan 671*0ad7347aSAndré Almeida int amdgpu_dpm_set_residency_gfxoff(struct amdgpu_device *adev, bool value) 672*0ad7347aSAndré Almeida { 673*0ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 674*0ad7347aSAndré Almeida int ret = 0; 675*0ad7347aSAndré Almeida 676*0ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 677*0ad7347aSAndré Almeida return -EOPNOTSUPP; 678*0ad7347aSAndré Almeida 679*0ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 680*0ad7347aSAndré Almeida ret = smu_set_residency_gfxoff(smu, value); 681*0ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 682*0ad7347aSAndré Almeida 683*0ad7347aSAndré Almeida return ret; 684*0ad7347aSAndré Almeida } 685*0ad7347aSAndré Almeida 686*0ad7347aSAndré Almeida int amdgpu_dpm_get_residency_gfxoff(struct amdgpu_device *adev, u32 *value) 687*0ad7347aSAndré Almeida { 688*0ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 689*0ad7347aSAndré Almeida int ret = 0; 690*0ad7347aSAndré Almeida 691*0ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 692*0ad7347aSAndré Almeida return -EOPNOTSUPP; 693*0ad7347aSAndré Almeida 694*0ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 695*0ad7347aSAndré Almeida ret = smu_get_residency_gfxoff(smu, value); 696*0ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 697*0ad7347aSAndré Almeida 698*0ad7347aSAndré Almeida return ret; 699*0ad7347aSAndré Almeida } 700*0ad7347aSAndré Almeida 701*0ad7347aSAndré Almeida int amdgpu_dpm_get_entrycount_gfxoff(struct amdgpu_device *adev, u64 *value) 702*0ad7347aSAndré Almeida { 703*0ad7347aSAndré Almeida struct smu_context *smu = adev->powerplay.pp_handle; 704*0ad7347aSAndré Almeida int ret = 0; 705*0ad7347aSAndré Almeida 706*0ad7347aSAndré Almeida if (!is_support_sw_smu(adev)) 707*0ad7347aSAndré Almeida return -EOPNOTSUPP; 708*0ad7347aSAndré Almeida 709*0ad7347aSAndré Almeida mutex_lock(&adev->pm.mutex); 710*0ad7347aSAndré Almeida ret = smu_get_entrycount_gfxoff(smu, value); 711*0ad7347aSAndré Almeida mutex_unlock(&adev->pm.mutex); 712*0ad7347aSAndré Almeida 713*0ad7347aSAndré Almeida return ret; 714*0ad7347aSAndré Almeida } 715*0ad7347aSAndré Almeida 716bc143d8bSEvan Quan int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) 717bc143d8bSEvan Quan { 718ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 7193712e7a4SEvan Quan int ret = 0; 720ebfc2533SEvan Quan 721bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 722bc143d8bSEvan Quan return -EOPNOTSUPP; 723bc143d8bSEvan Quan 7243712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 7253712e7a4SEvan Quan ret = smu_get_status_gfxoff(smu, value); 7263712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 7273712e7a4SEvan Quan 7283712e7a4SEvan Quan return ret; 729bc143d8bSEvan Quan } 730bc143d8bSEvan Quan 731bc143d8bSEvan Quan uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) 732bc143d8bSEvan Quan { 733ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 734ebfc2533SEvan Quan 7353712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 7363712e7a4SEvan Quan return 0; 7373712e7a4SEvan Quan 738ebfc2533SEvan Quan return atomic64_read(&smu->throttle_int_counter); 739bc143d8bSEvan Quan } 740bc143d8bSEvan Quan 741bc143d8bSEvan Quan /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set 742bc143d8bSEvan Quan * @adev: amdgpu_device pointer 743bc143d8bSEvan Quan * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) 744bc143d8bSEvan Quan * 745bc143d8bSEvan Quan */ 746bc143d8bSEvan Quan void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, 747bc143d8bSEvan Quan enum gfx_change_state state) 748bc143d8bSEvan Quan { 749bc143d8bSEvan Quan mutex_lock(&adev->pm.mutex); 750bc143d8bSEvan Quan if (adev->powerplay.pp_funcs && 751bc143d8bSEvan Quan adev->powerplay.pp_funcs->gfx_state_change_set) 752bc143d8bSEvan Quan ((adev)->powerplay.pp_funcs->gfx_state_change_set( 753bc143d8bSEvan Quan (adev)->powerplay.pp_handle, state)); 754bc143d8bSEvan Quan mutex_unlock(&adev->pm.mutex); 755bc143d8bSEvan Quan } 756bc143d8bSEvan Quan 757bc143d8bSEvan Quan int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, 758bc143d8bSEvan Quan void *umc_ecc) 759bc143d8bSEvan Quan { 760ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 761a29d44aeSStanley.Yang int ret = 0; 762ebfc2533SEvan Quan 763bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 764bc143d8bSEvan Quan return -EOPNOTSUPP; 765bc143d8bSEvan Quan 766a29d44aeSStanley.Yang mutex_lock(&adev->pm.mutex); 767a29d44aeSStanley.Yang ret = smu_get_ecc_info(smu, umc_ecc); 768a29d44aeSStanley.Yang mutex_unlock(&adev->pm.mutex); 769a29d44aeSStanley.Yang 770a29d44aeSStanley.Yang return ret; 771bc143d8bSEvan Quan } 77279c65f3fSEvan Quan 77379c65f3fSEvan Quan struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, 77479c65f3fSEvan Quan uint32_t idx) 77579c65f3fSEvan Quan { 77679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 7773712e7a4SEvan Quan struct amd_vce_state *vstate = NULL; 77879c65f3fSEvan Quan 77979c65f3fSEvan Quan if (!pp_funcs->get_vce_clock_state) 78079c65f3fSEvan Quan return NULL; 78179c65f3fSEvan Quan 7823712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 7833712e7a4SEvan Quan vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, 78479c65f3fSEvan Quan idx); 7853712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 7863712e7a4SEvan Quan 7873712e7a4SEvan Quan return vstate; 78879c65f3fSEvan Quan } 78979c65f3fSEvan Quan 79079c65f3fSEvan Quan void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, 79179c65f3fSEvan Quan enum amd_pm_state_type *state) 79279c65f3fSEvan Quan { 79379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 79479c65f3fSEvan Quan 7953712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 7963712e7a4SEvan Quan 79779c65f3fSEvan Quan if (!pp_funcs->get_current_power_state) { 79879c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 7993712e7a4SEvan Quan goto out; 80079c65f3fSEvan Quan } 80179c65f3fSEvan Quan 80279c65f3fSEvan Quan *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); 80379c65f3fSEvan Quan if (*state < POWER_STATE_TYPE_DEFAULT || 80479c65f3fSEvan Quan *state > POWER_STATE_TYPE_INTERNAL_3DPERF) 80579c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 8063712e7a4SEvan Quan 8073712e7a4SEvan Quan out: 8083712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 80979c65f3fSEvan Quan } 81079c65f3fSEvan Quan 81179c65f3fSEvan Quan void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, 81279c65f3fSEvan Quan enum amd_pm_state_type state) 81379c65f3fSEvan Quan { 8143712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 81579c65f3fSEvan Quan adev->pm.dpm.user_state = state; 8163712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 81779c65f3fSEvan Quan 81879c65f3fSEvan Quan if (is_support_sw_smu(adev)) 81979c65f3fSEvan Quan return; 82079c65f3fSEvan Quan 82179c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 82279c65f3fSEvan Quan AMD_PP_TASK_ENABLE_USER_STATE, 82379c65f3fSEvan Quan &state) == -EOPNOTSUPP) 82484176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 82579c65f3fSEvan Quan } 82679c65f3fSEvan Quan 82775513bf5SEvan Quan enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) 82879c65f3fSEvan Quan { 82979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 83079c65f3fSEvan Quan enum amd_dpm_forced_level level; 83179c65f3fSEvan Quan 83239dbde65SLijo Lazar if (!pp_funcs) 83339dbde65SLijo Lazar return AMD_DPM_FORCED_LEVEL_AUTO; 83439dbde65SLijo Lazar 83575513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 83679c65f3fSEvan Quan if (pp_funcs->get_performance_level) 83779c65f3fSEvan Quan level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); 83879c65f3fSEvan Quan else 83979c65f3fSEvan Quan level = adev->pm.dpm.forced_level; 8403712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 84179c65f3fSEvan Quan 84279c65f3fSEvan Quan return level; 84379c65f3fSEvan Quan } 84479c65f3fSEvan Quan 84579c65f3fSEvan Quan int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, 84679c65f3fSEvan Quan enum amd_dpm_forced_level level) 84779c65f3fSEvan Quan { 84879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 84954c73b51SAlex Deucher enum amd_dpm_forced_level current_level; 85054c73b51SAlex Deucher uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | 85154c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | 85254c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | 85354c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; 85479c65f3fSEvan Quan 855eea5c7b3SHuang Rui if (!pp_funcs || !pp_funcs->force_performance_level) 8563712e7a4SEvan Quan return 0; 8573712e7a4SEvan Quan 85875513bf5SEvan Quan if (adev->pm.dpm.thermal_active) 85975513bf5SEvan Quan return -EINVAL; 8603712e7a4SEvan Quan 86175513bf5SEvan Quan current_level = amdgpu_dpm_get_performance_level(adev); 86275513bf5SEvan Quan if (current_level == level) 86375513bf5SEvan Quan return 0; 86454c73b51SAlex Deucher 86554c73b51SAlex Deucher if (adev->asic_type == CHIP_RAVEN) { 86654c73b51SAlex Deucher if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { 86754c73b51SAlex Deucher if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && 86854c73b51SAlex Deucher level == AMD_DPM_FORCED_LEVEL_MANUAL) 86954c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, false); 87054c73b51SAlex Deucher else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && 87154c73b51SAlex Deucher level != AMD_DPM_FORCED_LEVEL_MANUAL) 87254c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, true); 87354c73b51SAlex Deucher } 87454c73b51SAlex Deucher } 87554c73b51SAlex Deucher 87654c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 87775513bf5SEvan Quan (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 87875513bf5SEvan Quan return -EINVAL; 87954c73b51SAlex Deucher 88054c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 88154c73b51SAlex Deucher (level & profile_mode_mask)) { 88254c73b51SAlex Deucher /* enter UMD Pstate */ 88354c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 88454c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 88554c73b51SAlex Deucher AMD_PG_STATE_UNGATE); 88654c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 88754c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 88854c73b51SAlex Deucher AMD_CG_STATE_UNGATE); 88954c73b51SAlex Deucher } else if ((current_level & profile_mode_mask) && 89054c73b51SAlex Deucher !(level & profile_mode_mask)) { 89154c73b51SAlex Deucher /* exit UMD Pstate */ 89254c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 89354c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 89454c73b51SAlex Deucher AMD_CG_STATE_GATE); 89554c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 89654c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 89754c73b51SAlex Deucher AMD_PG_STATE_GATE); 89854c73b51SAlex Deucher } 89954c73b51SAlex Deucher 90075513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 90179c65f3fSEvan Quan 90275513bf5SEvan Quan if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, 90375513bf5SEvan Quan level)) { 90475513bf5SEvan Quan mutex_unlock(&adev->pm.mutex); 90575513bf5SEvan Quan return -EINVAL; 90675513bf5SEvan Quan } 90775513bf5SEvan Quan 90879c65f3fSEvan Quan adev->pm.dpm.forced_level = level; 90979c65f3fSEvan Quan 9103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9113712e7a4SEvan Quan 91275513bf5SEvan Quan return 0; 91379c65f3fSEvan Quan } 91479c65f3fSEvan Quan 91579c65f3fSEvan Quan int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, 91679c65f3fSEvan Quan struct pp_states_info *states) 91779c65f3fSEvan Quan { 91879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9193712e7a4SEvan Quan int ret = 0; 92079c65f3fSEvan Quan 92179c65f3fSEvan Quan if (!pp_funcs->get_pp_num_states) 92279c65f3fSEvan Quan return -EOPNOTSUPP; 92379c65f3fSEvan Quan 9243712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9253712e7a4SEvan Quan ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, 9263712e7a4SEvan Quan states); 9273712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9283712e7a4SEvan Quan 9293712e7a4SEvan Quan return ret; 93079c65f3fSEvan Quan } 93179c65f3fSEvan Quan 93279c65f3fSEvan Quan int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, 93379c65f3fSEvan Quan enum amd_pp_task task_id, 93479c65f3fSEvan Quan enum amd_pm_state_type *user_state) 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->dispatch_tasks) 94079c65f3fSEvan Quan return -EOPNOTSUPP; 94179c65f3fSEvan Quan 9423712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9433712e7a4SEvan Quan ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, 9443712e7a4SEvan Quan task_id, 9453712e7a4SEvan Quan user_state); 9463712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9473712e7a4SEvan Quan 9483712e7a4SEvan Quan return ret; 94979c65f3fSEvan Quan } 95079c65f3fSEvan Quan 95179c65f3fSEvan Quan int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) 95279c65f3fSEvan Quan { 95379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9543712e7a4SEvan Quan int ret = 0; 95579c65f3fSEvan Quan 95679c65f3fSEvan Quan if (!pp_funcs->get_pp_table) 95779c65f3fSEvan Quan return 0; 95879c65f3fSEvan Quan 9593712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9603712e7a4SEvan Quan ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, 9613712e7a4SEvan Quan table); 9623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9633712e7a4SEvan Quan 9643712e7a4SEvan Quan return ret; 96579c65f3fSEvan Quan } 96679c65f3fSEvan Quan 96779c65f3fSEvan Quan int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, 96879c65f3fSEvan Quan uint32_t type, 96979c65f3fSEvan Quan long *input, 97079c65f3fSEvan Quan uint32_t size) 97179c65f3fSEvan Quan { 97279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9733712e7a4SEvan Quan int ret = 0; 97479c65f3fSEvan Quan 97579c65f3fSEvan Quan if (!pp_funcs->set_fine_grain_clk_vol) 97679c65f3fSEvan Quan return 0; 97779c65f3fSEvan Quan 9783712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9793712e7a4SEvan Quan ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, 98079c65f3fSEvan Quan type, 98179c65f3fSEvan Quan input, 98279c65f3fSEvan Quan size); 9833712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9843712e7a4SEvan Quan 9853712e7a4SEvan Quan return ret; 98679c65f3fSEvan Quan } 98779c65f3fSEvan Quan 98879c65f3fSEvan Quan int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, 98979c65f3fSEvan Quan uint32_t type, 99079c65f3fSEvan Quan long *input, 99179c65f3fSEvan Quan uint32_t size) 99279c65f3fSEvan Quan { 99379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9943712e7a4SEvan Quan int ret = 0; 99579c65f3fSEvan Quan 99679c65f3fSEvan Quan if (!pp_funcs->odn_edit_dpm_table) 99779c65f3fSEvan Quan return 0; 99879c65f3fSEvan Quan 9993712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10003712e7a4SEvan Quan ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, 100179c65f3fSEvan Quan type, 100279c65f3fSEvan Quan input, 100379c65f3fSEvan Quan size); 10043712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10053712e7a4SEvan Quan 10063712e7a4SEvan Quan return ret; 100779c65f3fSEvan Quan } 100879c65f3fSEvan Quan 100979c65f3fSEvan Quan int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, 101079c65f3fSEvan Quan enum pp_clock_type type, 101179c65f3fSEvan Quan char *buf) 101279c65f3fSEvan Quan { 101379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10143712e7a4SEvan Quan int ret = 0; 101579c65f3fSEvan Quan 101679c65f3fSEvan Quan if (!pp_funcs->print_clock_levels) 101779c65f3fSEvan Quan return 0; 101879c65f3fSEvan Quan 10193712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10203712e7a4SEvan Quan ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle, 102179c65f3fSEvan Quan type, 102279c65f3fSEvan Quan buf); 10233712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10243712e7a4SEvan Quan 10253712e7a4SEvan Quan return ret; 102679c65f3fSEvan Quan } 102779c65f3fSEvan Quan 10285d64f9bbSDarren Powell int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, 10295d64f9bbSDarren Powell enum pp_clock_type type, 10305d64f9bbSDarren Powell char *buf, 10315d64f9bbSDarren Powell int *offset) 10325d64f9bbSDarren Powell { 10335d64f9bbSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10345d64f9bbSDarren Powell int ret = 0; 10355d64f9bbSDarren Powell 10365d64f9bbSDarren Powell if (!pp_funcs->emit_clock_levels) 10375d64f9bbSDarren Powell return -ENOENT; 10385d64f9bbSDarren Powell 10395d64f9bbSDarren Powell mutex_lock(&adev->pm.mutex); 10405d64f9bbSDarren Powell ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle, 10415d64f9bbSDarren Powell type, 10425d64f9bbSDarren Powell buf, 10435d64f9bbSDarren Powell offset); 10445d64f9bbSDarren Powell mutex_unlock(&adev->pm.mutex); 10455d64f9bbSDarren Powell 10465d64f9bbSDarren Powell return ret; 10475d64f9bbSDarren Powell } 10485d64f9bbSDarren Powell 104979c65f3fSEvan Quan int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, 105079c65f3fSEvan Quan uint64_t ppfeature_masks) 105179c65f3fSEvan Quan { 105279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10533712e7a4SEvan Quan int ret = 0; 105479c65f3fSEvan Quan 105579c65f3fSEvan Quan if (!pp_funcs->set_ppfeature_status) 105679c65f3fSEvan Quan return 0; 105779c65f3fSEvan Quan 10583712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10593712e7a4SEvan Quan ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, 106079c65f3fSEvan Quan ppfeature_masks); 10613712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10623712e7a4SEvan Quan 10633712e7a4SEvan Quan return ret; 106479c65f3fSEvan Quan } 106579c65f3fSEvan Quan 106679c65f3fSEvan Quan int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) 106779c65f3fSEvan Quan { 106879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10693712e7a4SEvan Quan int ret = 0; 107079c65f3fSEvan Quan 107179c65f3fSEvan Quan if (!pp_funcs->get_ppfeature_status) 107279c65f3fSEvan Quan return 0; 107379c65f3fSEvan Quan 10743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10753712e7a4SEvan Quan ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, 107679c65f3fSEvan Quan buf); 10773712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10783712e7a4SEvan Quan 10793712e7a4SEvan Quan return ret; 108079c65f3fSEvan Quan } 108179c65f3fSEvan Quan 108279c65f3fSEvan Quan int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, 108379c65f3fSEvan Quan enum pp_clock_type type, 108479c65f3fSEvan Quan uint32_t mask) 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->force_clock_level) 109079c65f3fSEvan Quan return 0; 109179c65f3fSEvan Quan 10923712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10933712e7a4SEvan Quan ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle, 109479c65f3fSEvan Quan type, 109579c65f3fSEvan Quan mask); 10963712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10973712e7a4SEvan Quan 10983712e7a4SEvan Quan return ret; 109979c65f3fSEvan Quan } 110079c65f3fSEvan Quan 110179c65f3fSEvan Quan int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) 110279c65f3fSEvan Quan { 110379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11043712e7a4SEvan Quan int ret = 0; 110579c65f3fSEvan Quan 110679c65f3fSEvan Quan if (!pp_funcs->get_sclk_od) 110779c65f3fSEvan Quan return 0; 110879c65f3fSEvan Quan 11093712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11103712e7a4SEvan Quan ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle); 11113712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11123712e7a4SEvan Quan 11133712e7a4SEvan Quan return ret; 111479c65f3fSEvan Quan } 111579c65f3fSEvan Quan 111679c65f3fSEvan Quan int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) 111779c65f3fSEvan Quan { 111879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 111979c65f3fSEvan Quan 112079c65f3fSEvan Quan if (is_support_sw_smu(adev)) 112179c65f3fSEvan Quan return 0; 112279c65f3fSEvan Quan 11233712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 112479c65f3fSEvan Quan if (pp_funcs->set_sclk_od) 112579c65f3fSEvan Quan pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); 11263712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 112779c65f3fSEvan Quan 112879c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 112979c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 113079c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 113179c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 113284176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 113379c65f3fSEvan Quan } 113479c65f3fSEvan Quan 113579c65f3fSEvan Quan return 0; 113679c65f3fSEvan Quan } 113779c65f3fSEvan Quan 113879c65f3fSEvan Quan int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) 113979c65f3fSEvan Quan { 114079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11413712e7a4SEvan Quan int ret = 0; 114279c65f3fSEvan Quan 114379c65f3fSEvan Quan if (!pp_funcs->get_mclk_od) 114479c65f3fSEvan Quan return 0; 114579c65f3fSEvan Quan 11463712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11473712e7a4SEvan Quan ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle); 11483712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11493712e7a4SEvan Quan 11503712e7a4SEvan Quan return ret; 115179c65f3fSEvan Quan } 115279c65f3fSEvan Quan 115379c65f3fSEvan Quan int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) 115479c65f3fSEvan Quan { 115579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 115679c65f3fSEvan Quan 115779c65f3fSEvan Quan if (is_support_sw_smu(adev)) 115879c65f3fSEvan Quan return 0; 115979c65f3fSEvan Quan 11603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 116179c65f3fSEvan Quan if (pp_funcs->set_mclk_od) 116279c65f3fSEvan Quan pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); 11633712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 116479c65f3fSEvan Quan 116579c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 116679c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 116779c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 116879c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 116984176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 117079c65f3fSEvan Quan } 117179c65f3fSEvan Quan 117279c65f3fSEvan Quan return 0; 117379c65f3fSEvan Quan } 117479c65f3fSEvan Quan 117579c65f3fSEvan Quan int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, 117679c65f3fSEvan Quan char *buf) 117779c65f3fSEvan Quan { 117879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11793712e7a4SEvan Quan int ret = 0; 118079c65f3fSEvan Quan 118179c65f3fSEvan Quan if (!pp_funcs->get_power_profile_mode) 118279c65f3fSEvan Quan return -EOPNOTSUPP; 118379c65f3fSEvan Quan 11843712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11853712e7a4SEvan Quan ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, 118679c65f3fSEvan Quan buf); 11873712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11883712e7a4SEvan Quan 11893712e7a4SEvan Quan return ret; 119079c65f3fSEvan Quan } 119179c65f3fSEvan Quan 119279c65f3fSEvan Quan int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, 119379c65f3fSEvan Quan long *input, uint32_t size) 119479c65f3fSEvan Quan { 119579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11963712e7a4SEvan Quan int ret = 0; 119779c65f3fSEvan Quan 119879c65f3fSEvan Quan if (!pp_funcs->set_power_profile_mode) 119979c65f3fSEvan Quan return 0; 120079c65f3fSEvan Quan 12013712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12023712e7a4SEvan Quan ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, 120379c65f3fSEvan Quan input, 120479c65f3fSEvan Quan size); 12053712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12063712e7a4SEvan Quan 12073712e7a4SEvan Quan return ret; 120879c65f3fSEvan Quan } 120979c65f3fSEvan Quan 121079c65f3fSEvan Quan int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) 121179c65f3fSEvan Quan { 121279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12133712e7a4SEvan Quan int ret = 0; 121479c65f3fSEvan Quan 121579c65f3fSEvan Quan if (!pp_funcs->get_gpu_metrics) 121679c65f3fSEvan Quan return 0; 121779c65f3fSEvan Quan 12183712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12193712e7a4SEvan Quan ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, 12203712e7a4SEvan Quan table); 12213712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12223712e7a4SEvan Quan 12233712e7a4SEvan Quan return ret; 122479c65f3fSEvan Quan } 122579c65f3fSEvan Quan 122679c65f3fSEvan Quan int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, 122779c65f3fSEvan Quan uint32_t *fan_mode) 122879c65f3fSEvan Quan { 122979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1230685fae24SEvan Quan int ret = 0; 123179c65f3fSEvan Quan 123279c65f3fSEvan Quan if (!pp_funcs->get_fan_control_mode) 123379c65f3fSEvan Quan return -EOPNOTSUPP; 123479c65f3fSEvan Quan 12353712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1236685fae24SEvan Quan ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, 1237685fae24SEvan Quan fan_mode); 12383712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 123979c65f3fSEvan Quan 1240685fae24SEvan Quan return ret; 124179c65f3fSEvan Quan } 124279c65f3fSEvan Quan 124379c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, 124479c65f3fSEvan Quan uint32_t speed) 124579c65f3fSEvan Quan { 124679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12473712e7a4SEvan Quan int ret = 0; 124879c65f3fSEvan Quan 124979c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_pwm) 1250685fae24SEvan Quan return -EOPNOTSUPP; 125179c65f3fSEvan Quan 12523712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12533712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, 12543712e7a4SEvan Quan speed); 12553712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12563712e7a4SEvan Quan 12573712e7a4SEvan Quan return ret; 125879c65f3fSEvan Quan } 125979c65f3fSEvan Quan 126079c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, 126179c65f3fSEvan Quan uint32_t *speed) 126279c65f3fSEvan Quan { 126379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12643712e7a4SEvan Quan int ret = 0; 126579c65f3fSEvan Quan 126679c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_pwm) 1267685fae24SEvan Quan return -EOPNOTSUPP; 126879c65f3fSEvan Quan 12693712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12703712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, 12713712e7a4SEvan Quan speed); 12723712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12733712e7a4SEvan Quan 12743712e7a4SEvan Quan return ret; 127579c65f3fSEvan Quan } 127679c65f3fSEvan Quan 127779c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, 127879c65f3fSEvan Quan uint32_t *speed) 127979c65f3fSEvan Quan { 128079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12813712e7a4SEvan Quan int ret = 0; 128279c65f3fSEvan Quan 128379c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_rpm) 1284685fae24SEvan Quan return -EOPNOTSUPP; 128579c65f3fSEvan Quan 12863712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12873712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, 12883712e7a4SEvan Quan speed); 12893712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12903712e7a4SEvan Quan 12913712e7a4SEvan Quan return ret; 129279c65f3fSEvan Quan } 129379c65f3fSEvan Quan 129479c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, 129579c65f3fSEvan Quan uint32_t speed) 129679c65f3fSEvan Quan { 129779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12983712e7a4SEvan Quan int ret = 0; 129979c65f3fSEvan Quan 130079c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_rpm) 1301685fae24SEvan Quan return -EOPNOTSUPP; 130279c65f3fSEvan Quan 13033712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13043712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, 13053712e7a4SEvan Quan speed); 13063712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13073712e7a4SEvan Quan 13083712e7a4SEvan Quan return ret; 130979c65f3fSEvan Quan } 131079c65f3fSEvan Quan 131179c65f3fSEvan Quan int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, 131279c65f3fSEvan Quan uint32_t mode) 131379c65f3fSEvan Quan { 131479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1315685fae24SEvan Quan int ret = 0; 131679c65f3fSEvan Quan 131779c65f3fSEvan Quan if (!pp_funcs->set_fan_control_mode) 131879c65f3fSEvan Quan return -EOPNOTSUPP; 131979c65f3fSEvan Quan 13203712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1321685fae24SEvan Quan ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, 13223712e7a4SEvan Quan mode); 13233712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 132479c65f3fSEvan Quan 1325685fae24SEvan Quan return ret; 132679c65f3fSEvan Quan } 132779c65f3fSEvan Quan 132879c65f3fSEvan Quan int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, 132979c65f3fSEvan Quan uint32_t *limit, 133079c65f3fSEvan Quan enum pp_power_limit_level pp_limit_level, 133179c65f3fSEvan Quan enum pp_power_type power_type) 133279c65f3fSEvan Quan { 133379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13343712e7a4SEvan Quan int ret = 0; 133579c65f3fSEvan Quan 133679c65f3fSEvan Quan if (!pp_funcs->get_power_limit) 133779c65f3fSEvan Quan return -ENODATA; 133879c65f3fSEvan Quan 13393712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13403712e7a4SEvan Quan ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle, 134179c65f3fSEvan Quan limit, 134279c65f3fSEvan Quan pp_limit_level, 134379c65f3fSEvan Quan power_type); 13443712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13453712e7a4SEvan Quan 13463712e7a4SEvan Quan return ret; 134779c65f3fSEvan Quan } 134879c65f3fSEvan Quan 134979c65f3fSEvan Quan int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, 135079c65f3fSEvan Quan uint32_t limit) 135179c65f3fSEvan Quan { 135279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13533712e7a4SEvan Quan int ret = 0; 135479c65f3fSEvan Quan 135579c65f3fSEvan Quan if (!pp_funcs->set_power_limit) 135679c65f3fSEvan Quan return -EINVAL; 135779c65f3fSEvan Quan 13583712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13593712e7a4SEvan Quan ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle, 13603712e7a4SEvan Quan limit); 13613712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13623712e7a4SEvan Quan 13633712e7a4SEvan Quan return ret; 136479c65f3fSEvan Quan } 136579c65f3fSEvan Quan 136679c65f3fSEvan Quan int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) 136779c65f3fSEvan Quan { 13683712e7a4SEvan Quan bool cclk_dpm_supported = false; 13693712e7a4SEvan Quan 137079c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 137179c65f3fSEvan Quan return false; 137279c65f3fSEvan Quan 13733712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13743712e7a4SEvan Quan cclk_dpm_supported = is_support_cclk_dpm(adev); 13753712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13763712e7a4SEvan Quan 13773712e7a4SEvan Quan return (int)cclk_dpm_supported; 137879c65f3fSEvan Quan } 137979c65f3fSEvan Quan 138079c65f3fSEvan Quan int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, 138179c65f3fSEvan Quan struct seq_file *m) 138279c65f3fSEvan Quan { 138379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 138479c65f3fSEvan Quan 138579c65f3fSEvan Quan if (!pp_funcs->debugfs_print_current_performance_level) 138679c65f3fSEvan Quan return -EOPNOTSUPP; 138779c65f3fSEvan Quan 13883712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 138979c65f3fSEvan Quan pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, 139079c65f3fSEvan Quan m); 13913712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 139279c65f3fSEvan Quan 139379c65f3fSEvan Quan return 0; 139479c65f3fSEvan Quan } 139579c65f3fSEvan Quan 139679c65f3fSEvan Quan int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, 139779c65f3fSEvan Quan void **addr, 139879c65f3fSEvan Quan size_t *size) 139979c65f3fSEvan Quan { 140079c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14013712e7a4SEvan Quan int ret = 0; 140279c65f3fSEvan Quan 140379c65f3fSEvan Quan if (!pp_funcs->get_smu_prv_buf_details) 140479c65f3fSEvan Quan return -ENOSYS; 140579c65f3fSEvan Quan 14063712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14073712e7a4SEvan Quan ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, 140879c65f3fSEvan Quan addr, 140979c65f3fSEvan Quan size); 14103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14113712e7a4SEvan Quan 14123712e7a4SEvan Quan return ret; 141379c65f3fSEvan Quan } 141479c65f3fSEvan Quan 141579c65f3fSEvan Quan int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) 141679c65f3fSEvan Quan { 141779c65f3fSEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; 1418ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 141979c65f3fSEvan Quan 1420ebfc2533SEvan Quan if ((is_support_sw_smu(adev) && smu->od_enabled) || 1421ebfc2533SEvan Quan (is_support_sw_smu(adev) && smu->is_apu) || 142279c65f3fSEvan Quan (!is_support_sw_smu(adev) && hwmgr->od_enabled)) 142379c65f3fSEvan Quan return true; 142479c65f3fSEvan Quan 142579c65f3fSEvan Quan return false; 142679c65f3fSEvan Quan } 142779c65f3fSEvan Quan 142879c65f3fSEvan Quan int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, 142979c65f3fSEvan Quan const char *buf, 143079c65f3fSEvan Quan size_t size) 143179c65f3fSEvan Quan { 143279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14333712e7a4SEvan Quan int ret = 0; 143479c65f3fSEvan Quan 143579c65f3fSEvan Quan if (!pp_funcs->set_pp_table) 143679c65f3fSEvan Quan return -EOPNOTSUPP; 143779c65f3fSEvan Quan 14383712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14393712e7a4SEvan Quan ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle, 144079c65f3fSEvan Quan buf, 144179c65f3fSEvan Quan size); 14423712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14433712e7a4SEvan Quan 14443712e7a4SEvan Quan return ret; 144579c65f3fSEvan Quan } 144679c65f3fSEvan Quan 144779c65f3fSEvan Quan int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) 144879c65f3fSEvan Quan { 1449ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 1450ebfc2533SEvan Quan 14513712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 14523712e7a4SEvan Quan return INT_MAX; 14533712e7a4SEvan Quan 1454ebfc2533SEvan Quan return smu->cpu_core_num; 145579c65f3fSEvan Quan } 145679c65f3fSEvan Quan 145779c65f3fSEvan Quan void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) 145879c65f3fSEvan Quan { 145979c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 146079c65f3fSEvan Quan return; 146179c65f3fSEvan Quan 146279c65f3fSEvan Quan amdgpu_smu_stb_debug_fs_init(adev); 146379c65f3fSEvan Quan } 146413f5dbd6SEvan Quan 146513f5dbd6SEvan Quan int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, 146613f5dbd6SEvan Quan const struct amd_pp_display_configuration *input) 146713f5dbd6SEvan Quan { 146813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14693712e7a4SEvan Quan int ret = 0; 147013f5dbd6SEvan Quan 147113f5dbd6SEvan Quan if (!pp_funcs->display_configuration_change) 147213f5dbd6SEvan Quan return 0; 147313f5dbd6SEvan Quan 14743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14753712e7a4SEvan Quan ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle, 147613f5dbd6SEvan Quan input); 14773712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14783712e7a4SEvan Quan 14793712e7a4SEvan Quan return ret; 148013f5dbd6SEvan Quan } 148113f5dbd6SEvan Quan 148213f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, 148313f5dbd6SEvan Quan enum amd_pp_clock_type type, 148413f5dbd6SEvan Quan struct amd_pp_clocks *clocks) 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->get_clock_by_type) 149013f5dbd6SEvan Quan return 0; 149113f5dbd6SEvan Quan 14923712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14933712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, 149413f5dbd6SEvan Quan type, 149513f5dbd6SEvan Quan clocks); 14963712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14973712e7a4SEvan Quan 14983712e7a4SEvan Quan return ret; 149913f5dbd6SEvan Quan } 150013f5dbd6SEvan Quan 150113f5dbd6SEvan Quan int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, 150213f5dbd6SEvan Quan struct amd_pp_simple_clock_info *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_display_mode_validation_clocks) 150813f5dbd6SEvan Quan return 0; 150913f5dbd6SEvan Quan 15103712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15113712e7a4SEvan Quan ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, 151213f5dbd6SEvan Quan clocks); 15133712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15143712e7a4SEvan Quan 15153712e7a4SEvan Quan return ret; 151613f5dbd6SEvan Quan } 151713f5dbd6SEvan Quan 151813f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, 151913f5dbd6SEvan Quan enum amd_pp_clock_type type, 152013f5dbd6SEvan Quan struct pp_clock_levels_with_latency *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_clock_by_type_with_latency) 152613f5dbd6SEvan Quan return 0; 152713f5dbd6SEvan Quan 15283712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15293712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, 153013f5dbd6SEvan Quan type, 153113f5dbd6SEvan Quan clocks); 15323712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15333712e7a4SEvan Quan 15343712e7a4SEvan Quan return ret; 153513f5dbd6SEvan Quan } 153613f5dbd6SEvan Quan 153713f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, 153813f5dbd6SEvan Quan enum amd_pp_clock_type type, 153913f5dbd6SEvan Quan struct pp_clock_levels_with_voltage *clocks) 154013f5dbd6SEvan Quan { 154113f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15423712e7a4SEvan Quan int ret = 0; 154313f5dbd6SEvan Quan 154413f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_voltage) 154513f5dbd6SEvan Quan return 0; 154613f5dbd6SEvan Quan 15473712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15483712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, 154913f5dbd6SEvan Quan type, 155013f5dbd6SEvan Quan clocks); 15513712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15523712e7a4SEvan Quan 15533712e7a4SEvan Quan return ret; 155413f5dbd6SEvan Quan } 155513f5dbd6SEvan Quan 155613f5dbd6SEvan Quan int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, 155713f5dbd6SEvan Quan void *clock_ranges) 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->set_watermarks_for_clocks_ranges) 156313f5dbd6SEvan Quan return -EOPNOTSUPP; 156413f5dbd6SEvan Quan 15653712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15663712e7a4SEvan Quan ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, 156713f5dbd6SEvan Quan clock_ranges); 15683712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15693712e7a4SEvan Quan 15703712e7a4SEvan Quan return ret; 157113f5dbd6SEvan Quan } 157213f5dbd6SEvan Quan 157313f5dbd6SEvan Quan int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, 157413f5dbd6SEvan Quan struct pp_display_clock_request *clock) 157513f5dbd6SEvan Quan { 157613f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15773712e7a4SEvan Quan int ret = 0; 157813f5dbd6SEvan Quan 157913f5dbd6SEvan Quan if (!pp_funcs->display_clock_voltage_request) 158013f5dbd6SEvan Quan return -EOPNOTSUPP; 158113f5dbd6SEvan Quan 15823712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15833712e7a4SEvan Quan ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, 158413f5dbd6SEvan Quan clock); 15853712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15863712e7a4SEvan Quan 15873712e7a4SEvan Quan return ret; 158813f5dbd6SEvan Quan } 158913f5dbd6SEvan Quan 159013f5dbd6SEvan Quan int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, 159113f5dbd6SEvan Quan struct amd_pp_clock_info *clocks) 159213f5dbd6SEvan Quan { 159313f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15943712e7a4SEvan Quan int ret = 0; 159513f5dbd6SEvan Quan 159613f5dbd6SEvan Quan if (!pp_funcs->get_current_clocks) 159713f5dbd6SEvan Quan return -EOPNOTSUPP; 159813f5dbd6SEvan Quan 15993712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16003712e7a4SEvan Quan ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle, 160113f5dbd6SEvan Quan clocks); 16023712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16033712e7a4SEvan Quan 16043712e7a4SEvan Quan return ret; 160513f5dbd6SEvan Quan } 160613f5dbd6SEvan Quan 160713f5dbd6SEvan Quan void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) 160813f5dbd6SEvan Quan { 160913f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 161013f5dbd6SEvan Quan 161113f5dbd6SEvan Quan if (!pp_funcs->notify_smu_enable_pwe) 161213f5dbd6SEvan Quan return; 161313f5dbd6SEvan Quan 16143712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 161513f5dbd6SEvan Quan pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); 16163712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 161713f5dbd6SEvan Quan } 161813f5dbd6SEvan Quan 161913f5dbd6SEvan Quan int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, 162013f5dbd6SEvan Quan uint32_t count) 162113f5dbd6SEvan Quan { 162213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16233712e7a4SEvan Quan int ret = 0; 162413f5dbd6SEvan Quan 162513f5dbd6SEvan Quan if (!pp_funcs->set_active_display_count) 162613f5dbd6SEvan Quan return -EOPNOTSUPP; 162713f5dbd6SEvan Quan 16283712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16293712e7a4SEvan Quan ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle, 163013f5dbd6SEvan Quan count); 16313712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16323712e7a4SEvan Quan 16333712e7a4SEvan Quan return ret; 163413f5dbd6SEvan Quan } 163513f5dbd6SEvan Quan 163613f5dbd6SEvan Quan int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, 163713f5dbd6SEvan Quan uint32_t clock) 163813f5dbd6SEvan Quan { 163913f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16403712e7a4SEvan Quan int ret = 0; 164113f5dbd6SEvan Quan 164213f5dbd6SEvan Quan if (!pp_funcs->set_min_deep_sleep_dcefclk) 164313f5dbd6SEvan Quan return -EOPNOTSUPP; 164413f5dbd6SEvan Quan 16453712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16463712e7a4SEvan Quan ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, 164713f5dbd6SEvan Quan clock); 16483712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16493712e7a4SEvan Quan 16503712e7a4SEvan Quan return ret; 165113f5dbd6SEvan Quan } 165213f5dbd6SEvan Quan 165313f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, 165413f5dbd6SEvan Quan uint32_t clock) 165513f5dbd6SEvan Quan { 165613f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 165713f5dbd6SEvan Quan 165813f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_dcefclk_by_freq) 165913f5dbd6SEvan Quan return; 166013f5dbd6SEvan Quan 16613712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 166213f5dbd6SEvan Quan pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, 166313f5dbd6SEvan Quan clock); 16643712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 166513f5dbd6SEvan Quan } 166613f5dbd6SEvan Quan 166713f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, 166813f5dbd6SEvan Quan uint32_t clock) 166913f5dbd6SEvan Quan { 167013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 167113f5dbd6SEvan Quan 167213f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_fclk_by_freq) 167313f5dbd6SEvan Quan return; 167413f5dbd6SEvan Quan 16753712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 167613f5dbd6SEvan Quan pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, 167713f5dbd6SEvan Quan clock); 16783712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 167913f5dbd6SEvan Quan } 168013f5dbd6SEvan Quan 168113f5dbd6SEvan Quan int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, 168213f5dbd6SEvan Quan bool disable_memory_clock_switch) 168313f5dbd6SEvan Quan { 168413f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16853712e7a4SEvan Quan int ret = 0; 168613f5dbd6SEvan Quan 168713f5dbd6SEvan Quan if (!pp_funcs->display_disable_memory_clock_switch) 168813f5dbd6SEvan Quan return 0; 168913f5dbd6SEvan Quan 16903712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16913712e7a4SEvan Quan ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, 169213f5dbd6SEvan Quan disable_memory_clock_switch); 16933712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16943712e7a4SEvan Quan 16953712e7a4SEvan Quan return ret; 169613f5dbd6SEvan Quan } 169713f5dbd6SEvan Quan 169813f5dbd6SEvan Quan int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, 169913f5dbd6SEvan Quan struct pp_smu_nv_clock_table *max_clocks) 170013f5dbd6SEvan Quan { 170113f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 17023712e7a4SEvan Quan int ret = 0; 170313f5dbd6SEvan Quan 170413f5dbd6SEvan Quan if (!pp_funcs->get_max_sustainable_clocks_by_dc) 170513f5dbd6SEvan Quan return -EOPNOTSUPP; 170613f5dbd6SEvan Quan 17073712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17083712e7a4SEvan Quan ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, 170913f5dbd6SEvan Quan max_clocks); 17103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17113712e7a4SEvan Quan 17123712e7a4SEvan Quan return ret; 171313f5dbd6SEvan Quan } 171413f5dbd6SEvan Quan 171513f5dbd6SEvan Quan enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, 171613f5dbd6SEvan Quan unsigned int *clock_values_in_khz, 171713f5dbd6SEvan Quan unsigned int *num_states) 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_uclk_dpm_states) 172313f5dbd6SEvan Quan return -EOPNOTSUPP; 172413f5dbd6SEvan Quan 17253712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17263712e7a4SEvan Quan ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, 172713f5dbd6SEvan Quan clock_values_in_khz, 172813f5dbd6SEvan Quan num_states); 17293712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17303712e7a4SEvan Quan 17313712e7a4SEvan Quan return ret; 173213f5dbd6SEvan Quan } 173313f5dbd6SEvan Quan 173413f5dbd6SEvan Quan int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, 173513f5dbd6SEvan Quan struct dpm_clocks *clock_table) 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_dpm_clock_table) 174113f5dbd6SEvan Quan return -EOPNOTSUPP; 174213f5dbd6SEvan Quan 17433712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 17443712e7a4SEvan Quan ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, 174513f5dbd6SEvan Quan clock_table); 17463712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 17473712e7a4SEvan Quan 17483712e7a4SEvan Quan return ret; 174913f5dbd6SEvan Quan } 1750