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 110e098bc96SEvan Quan int amdgpu_dpm_baco_enter(struct amdgpu_device *adev) 111e098bc96SEvan Quan { 112e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 113e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 114e098bc96SEvan Quan int ret = 0; 115e098bc96SEvan Quan 116e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->set_asic_baco_state) 117e098bc96SEvan Quan return -ENOENT; 118e098bc96SEvan Quan 1193712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1203712e7a4SEvan Quan 121e098bc96SEvan Quan /* enter BACO state */ 122e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 123e098bc96SEvan Quan 1243712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 1253712e7a4SEvan Quan 126e098bc96SEvan Quan return ret; 127e098bc96SEvan Quan } 128e098bc96SEvan Quan 129e098bc96SEvan Quan int amdgpu_dpm_baco_exit(struct amdgpu_device *adev) 130e098bc96SEvan Quan { 131e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 132e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 133e098bc96SEvan Quan int ret = 0; 134e098bc96SEvan Quan 135e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->set_asic_baco_state) 136e098bc96SEvan Quan return -ENOENT; 137e098bc96SEvan Quan 1383712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1393712e7a4SEvan Quan 140e098bc96SEvan Quan /* exit BACO state */ 141e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 142e098bc96SEvan Quan 1433712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 1443712e7a4SEvan Quan 145e098bc96SEvan Quan return ret; 146e098bc96SEvan Quan } 147e098bc96SEvan Quan 148e098bc96SEvan Quan int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, 149e098bc96SEvan Quan enum pp_mp1_state mp1_state) 150e098bc96SEvan Quan { 151e098bc96SEvan Quan int ret = 0; 152bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 153e098bc96SEvan Quan 154bab0f602SDarren Powell if (pp_funcs && pp_funcs->set_mp1_state) { 1553712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1563712e7a4SEvan Quan 157bab0f602SDarren Powell ret = pp_funcs->set_mp1_state( 158e098bc96SEvan Quan adev->powerplay.pp_handle, 159e098bc96SEvan Quan mp1_state); 1603712e7a4SEvan Quan 1613712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 162e098bc96SEvan Quan } 163e098bc96SEvan Quan 164e098bc96SEvan Quan return ret; 165e098bc96SEvan Quan } 166e098bc96SEvan Quan 167e098bc96SEvan Quan bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) 168e098bc96SEvan Quan { 169e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 170e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 171e098bc96SEvan Quan bool baco_cap; 1723712e7a4SEvan Quan int ret = 0; 173e098bc96SEvan Quan 174e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->get_asic_baco_capability) 175e098bc96SEvan Quan return false; 176*34452ac3SAlex Deucher /* Don't use baco for reset in S3. 177*34452ac3SAlex Deucher * This is a workaround for some platforms 178*34452ac3SAlex Deucher * where entering BACO during suspend 179*34452ac3SAlex Deucher * seems to cause reboots or hangs. 180*34452ac3SAlex Deucher * This might be related to the fact that BACO controls 181*34452ac3SAlex Deucher * power to the whole GPU including devices like audio and USB. 182*34452ac3SAlex Deucher * Powering down/up everything may adversely affect these other 183*34452ac3SAlex Deucher * devices. Needs more investigation. 184*34452ac3SAlex Deucher */ 185*34452ac3SAlex Deucher if (adev->in_s3) 186*34452ac3SAlex Deucher return false; 187e098bc96SEvan Quan 1883712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 189e098bc96SEvan Quan 1903712e7a4SEvan Quan ret = pp_funcs->get_asic_baco_capability(pp_handle, 1913712e7a4SEvan Quan &baco_cap); 1923712e7a4SEvan Quan 1933712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 1943712e7a4SEvan Quan 1953712e7a4SEvan Quan return ret ? false : baco_cap; 196e098bc96SEvan Quan } 197e098bc96SEvan Quan 198e098bc96SEvan Quan int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) 199e098bc96SEvan Quan { 200e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 201e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 2023712e7a4SEvan Quan int ret = 0; 203e098bc96SEvan Quan 204e098bc96SEvan Quan if (!pp_funcs || !pp_funcs->asic_reset_mode_2) 205e098bc96SEvan Quan return -ENOENT; 206e098bc96SEvan Quan 2073712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2083712e7a4SEvan Quan 2093712e7a4SEvan Quan ret = pp_funcs->asic_reset_mode_2(pp_handle); 2103712e7a4SEvan Quan 2113712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2123712e7a4SEvan Quan 2133712e7a4SEvan Quan return ret; 214e098bc96SEvan Quan } 215e098bc96SEvan Quan 216e098bc96SEvan Quan int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) 217e098bc96SEvan Quan { 218e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 219e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 220e098bc96SEvan Quan int ret = 0; 221e098bc96SEvan Quan 2229ab5001aSDarren Powell if (!pp_funcs || !pp_funcs->set_asic_baco_state) 223e098bc96SEvan Quan return -ENOENT; 224e098bc96SEvan Quan 2253712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2263712e7a4SEvan Quan 227e098bc96SEvan Quan /* enter BACO state */ 228e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 1); 229e098bc96SEvan Quan if (ret) 2303712e7a4SEvan Quan goto out; 231e098bc96SEvan Quan 232e098bc96SEvan Quan /* exit BACO state */ 233e098bc96SEvan Quan ret = pp_funcs->set_asic_baco_state(pp_handle, 0); 234e098bc96SEvan Quan 2353712e7a4SEvan Quan out: 2363712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2373712e7a4SEvan Quan return ret; 238e098bc96SEvan Quan } 239e098bc96SEvan Quan 240e098bc96SEvan Quan bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) 241e098bc96SEvan Quan { 242ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 2433712e7a4SEvan Quan bool support_mode1_reset = false; 244e098bc96SEvan Quan 2453712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 2463712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2473712e7a4SEvan Quan support_mode1_reset = smu_mode1_reset_is_support(smu); 2483712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2493712e7a4SEvan Quan } 250e098bc96SEvan Quan 2513712e7a4SEvan Quan return support_mode1_reset; 252e098bc96SEvan Quan } 253e098bc96SEvan Quan 254e098bc96SEvan Quan int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) 255e098bc96SEvan Quan { 256ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 2573712e7a4SEvan Quan int ret = -EOPNOTSUPP; 258e098bc96SEvan Quan 2593712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 2603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 2613712e7a4SEvan Quan ret = smu_mode1_reset(smu); 2623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2633712e7a4SEvan Quan } 264e098bc96SEvan Quan 2653712e7a4SEvan Quan return ret; 266e098bc96SEvan Quan } 267e098bc96SEvan Quan 268e098bc96SEvan Quan int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, 269e098bc96SEvan Quan enum PP_SMC_POWER_PROFILE type, 270e098bc96SEvan Quan bool en) 271e098bc96SEvan Quan { 272bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 273e098bc96SEvan Quan int ret = 0; 274e098bc96SEvan Quan 2757cf7a392SJingwen Chen if (amdgpu_sriov_vf(adev)) 2767cf7a392SJingwen Chen return 0; 2777cf7a392SJingwen Chen 2783712e7a4SEvan Quan if (pp_funcs && pp_funcs->switch_power_profile) { 2793712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 280bab0f602SDarren Powell ret = pp_funcs->switch_power_profile( 281e098bc96SEvan Quan adev->powerplay.pp_handle, type, en); 2823712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2833712e7a4SEvan Quan } 284e098bc96SEvan Quan 285e098bc96SEvan Quan return ret; 286e098bc96SEvan Quan } 287e098bc96SEvan Quan 288e098bc96SEvan Quan int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, 289e098bc96SEvan Quan uint32_t pstate) 290e098bc96SEvan Quan { 291bab0f602SDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 292e098bc96SEvan Quan int ret = 0; 293e098bc96SEvan Quan 2943712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_xgmi_pstate) { 2953712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 296bab0f602SDarren Powell ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, 297e098bc96SEvan Quan pstate); 2983712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 2993712e7a4SEvan Quan } 300e098bc96SEvan Quan 301e098bc96SEvan Quan return ret; 302e098bc96SEvan Quan } 303e098bc96SEvan Quan 304e098bc96SEvan Quan int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, 305e098bc96SEvan Quan uint32_t cstate) 306e098bc96SEvan Quan { 307e098bc96SEvan Quan int ret = 0; 308e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 309e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 310e098bc96SEvan Quan 3113712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_df_cstate) { 3123712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 313e098bc96SEvan Quan ret = pp_funcs->set_df_cstate(pp_handle, cstate); 3143712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3153712e7a4SEvan Quan } 316e098bc96SEvan Quan 317e098bc96SEvan Quan return ret; 318e098bc96SEvan Quan } 319e098bc96SEvan Quan 320e098bc96SEvan Quan int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) 321e098bc96SEvan Quan { 322ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 3233712e7a4SEvan Quan int ret = 0; 324e098bc96SEvan Quan 3253712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 3263712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 3273712e7a4SEvan Quan ret = smu_allow_xgmi_power_down(smu, en); 3283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3293712e7a4SEvan Quan } 330e098bc96SEvan Quan 3313712e7a4SEvan Quan return ret; 332e098bc96SEvan Quan } 333e098bc96SEvan Quan 334e098bc96SEvan Quan int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) 335e098bc96SEvan Quan { 336e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 337e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 338e098bc96SEvan Quan adev->powerplay.pp_funcs; 339e098bc96SEvan Quan int ret = 0; 340e098bc96SEvan Quan 3413712e7a4SEvan Quan if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) { 3423712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 343e098bc96SEvan Quan ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); 3443712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3453712e7a4SEvan Quan } 346e098bc96SEvan Quan 347e098bc96SEvan Quan return ret; 348e098bc96SEvan Quan } 349e098bc96SEvan Quan 350e098bc96SEvan Quan int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, 351e098bc96SEvan Quan uint32_t msg_id) 352e098bc96SEvan Quan { 353e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 354e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 355e098bc96SEvan Quan adev->powerplay.pp_funcs; 356e098bc96SEvan Quan int ret = 0; 357e098bc96SEvan Quan 3583712e7a4SEvan Quan if (pp_funcs && pp_funcs->set_clockgating_by_smu) { 3593712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 360e098bc96SEvan Quan ret = pp_funcs->set_clockgating_by_smu(pp_handle, 361e098bc96SEvan Quan msg_id); 3623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3633712e7a4SEvan Quan } 364e098bc96SEvan Quan 365e098bc96SEvan Quan return ret; 366e098bc96SEvan Quan } 367e098bc96SEvan Quan 368e098bc96SEvan Quan int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, 369e098bc96SEvan Quan bool acquire) 370e098bc96SEvan Quan { 371e098bc96SEvan Quan void *pp_handle = adev->powerplay.pp_handle; 372e098bc96SEvan Quan const struct amd_pm_funcs *pp_funcs = 373e098bc96SEvan Quan adev->powerplay.pp_funcs; 374e098bc96SEvan Quan int ret = -EOPNOTSUPP; 375e098bc96SEvan Quan 3763712e7a4SEvan Quan if (pp_funcs && pp_funcs->smu_i2c_bus_access) { 3773712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 378e098bc96SEvan Quan ret = pp_funcs->smu_i2c_bus_access(pp_handle, 379e098bc96SEvan Quan acquire); 3803712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 3813712e7a4SEvan Quan } 382e098bc96SEvan Quan 383e098bc96SEvan Quan return ret; 384e098bc96SEvan Quan } 385e098bc96SEvan Quan 386e098bc96SEvan Quan void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) 387e098bc96SEvan Quan { 388e098bc96SEvan Quan if (adev->pm.dpm_enabled) { 389e098bc96SEvan Quan mutex_lock(&adev->pm.mutex); 390e098bc96SEvan Quan if (power_supply_is_system_supplied() > 0) 391e098bc96SEvan Quan adev->pm.ac_power = true; 392e098bc96SEvan Quan else 393e098bc96SEvan Quan adev->pm.ac_power = false; 3943712e7a4SEvan Quan 395e098bc96SEvan Quan if (adev->powerplay.pp_funcs && 396e098bc96SEvan Quan adev->powerplay.pp_funcs->enable_bapm) 397e098bc96SEvan Quan amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); 398e098bc96SEvan Quan 399e098bc96SEvan Quan if (is_support_sw_smu(adev)) 400ebfc2533SEvan Quan smu_set_ac_dc(adev->powerplay.pp_handle); 4013712e7a4SEvan Quan 4023712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 403e098bc96SEvan Quan } 404e098bc96SEvan Quan } 405e098bc96SEvan Quan 406e098bc96SEvan Quan int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, 407e098bc96SEvan Quan void *data, uint32_t *size) 408e098bc96SEvan Quan { 4099ab5001aSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 4103712e7a4SEvan Quan int ret = -EINVAL; 411e098bc96SEvan Quan 412e098bc96SEvan Quan if (!data || !size) 413e098bc96SEvan Quan return -EINVAL; 414e098bc96SEvan Quan 4153712e7a4SEvan Quan if (pp_funcs && pp_funcs->read_sensor) { 4163712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4173712e7a4SEvan Quan ret = pp_funcs->read_sensor(adev->powerplay.pp_handle, 4183712e7a4SEvan Quan sensor, 4193712e7a4SEvan Quan data, 4203712e7a4SEvan Quan size); 4213712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 4223712e7a4SEvan Quan } 423e098bc96SEvan Quan 424e098bc96SEvan Quan return ret; 425e098bc96SEvan Quan } 426e098bc96SEvan Quan 42784176663SEvan Quan void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) 428e098bc96SEvan Quan { 4296ddbd37fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 430e098bc96SEvan Quan 431e098bc96SEvan Quan if (!adev->pm.dpm_enabled) 432e098bc96SEvan Quan return; 433e098bc96SEvan Quan 4346ddbd37fSEvan Quan if (!pp_funcs->pm_compute_clocks) 4356ddbd37fSEvan Quan return; 436e098bc96SEvan Quan 4373712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4386ddbd37fSEvan Quan pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); 4393712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 440e098bc96SEvan Quan } 441e098bc96SEvan Quan 442e098bc96SEvan Quan void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) 443e098bc96SEvan Quan { 444e098bc96SEvan Quan int ret = 0; 445e098bc96SEvan Quan 446e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 447e098bc96SEvan Quan if (ret) 448e098bc96SEvan Quan DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", 449e098bc96SEvan Quan enable ? "enable" : "disable", ret); 450e098bc96SEvan Quan } 451e098bc96SEvan Quan 452e098bc96SEvan Quan void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) 453e098bc96SEvan Quan { 454e098bc96SEvan Quan int ret = 0; 455e098bc96SEvan Quan 456e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); 457e098bc96SEvan Quan if (ret) 458e098bc96SEvan Quan DRM_ERROR("Dpm %s vce failed, ret = %d. \n", 459e098bc96SEvan Quan enable ? "enable" : "disable", ret); 460e098bc96SEvan Quan } 461e098bc96SEvan Quan 462e098bc96SEvan Quan void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) 463e098bc96SEvan Quan { 464e098bc96SEvan Quan int ret = 0; 465e098bc96SEvan Quan 466e098bc96SEvan Quan ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); 467e098bc96SEvan Quan if (ret) 468e098bc96SEvan Quan DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", 469e098bc96SEvan Quan enable ? "enable" : "disable", ret); 470e098bc96SEvan Quan } 471e098bc96SEvan Quan 472e098bc96SEvan Quan int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) 473e098bc96SEvan Quan { 4743712e7a4SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 4753712e7a4SEvan Quan int r = 0; 476e098bc96SEvan Quan 4771613f346SFlora Cui if (!pp_funcs || !pp_funcs->load_firmware) 4783712e7a4SEvan Quan return 0; 4793712e7a4SEvan Quan 4803712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 4813712e7a4SEvan Quan r = pp_funcs->load_firmware(adev->powerplay.pp_handle); 482e098bc96SEvan Quan if (r) { 483e098bc96SEvan Quan pr_err("smu firmware loading failed\n"); 4843712e7a4SEvan Quan goto out; 485e098bc96SEvan Quan } 4862e4b2f7bSEvan Quan 4872e4b2f7bSEvan Quan if (smu_version) 488e098bc96SEvan Quan *smu_version = adev->pm.fw_version; 4892e4b2f7bSEvan Quan 4903712e7a4SEvan Quan out: 4913712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 4923712e7a4SEvan Quan return r; 493e098bc96SEvan Quan } 494bc143d8bSEvan Quan 495bc143d8bSEvan Quan int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) 496bc143d8bSEvan Quan { 4973712e7a4SEvan Quan int ret = 0; 4983712e7a4SEvan Quan 4993712e7a4SEvan Quan if (is_support_sw_smu(adev)) { 5003712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5013712e7a4SEvan Quan ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle, 5023712e7a4SEvan Quan enable); 5033712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5043712e7a4SEvan Quan } 5053712e7a4SEvan Quan 5063712e7a4SEvan Quan return ret; 507bc143d8bSEvan Quan } 508bc143d8bSEvan Quan 509bc143d8bSEvan Quan int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) 510bc143d8bSEvan Quan { 511ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 5123712e7a4SEvan Quan int ret = 0; 513ebfc2533SEvan Quan 51493dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 51593dde6ccSStanley.Yang return -EOPNOTSUPP; 51693dde6ccSStanley.Yang 5173712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5183712e7a4SEvan Quan ret = smu_send_hbm_bad_pages_num(smu, size); 5193712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5203712e7a4SEvan Quan 5213712e7a4SEvan Quan return ret; 522bc143d8bSEvan Quan } 523bc143d8bSEvan Quan 524d510eccfSStanley.Yang int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size) 525d510eccfSStanley.Yang { 526d510eccfSStanley.Yang struct smu_context *smu = adev->powerplay.pp_handle; 527d510eccfSStanley.Yang int ret = 0; 528d510eccfSStanley.Yang 52993dde6ccSStanley.Yang if (!is_support_sw_smu(adev)) 53093dde6ccSStanley.Yang return -EOPNOTSUPP; 53193dde6ccSStanley.Yang 532d510eccfSStanley.Yang mutex_lock(&adev->pm.mutex); 533d510eccfSStanley.Yang ret = smu_send_hbm_bad_channel_flag(smu, size); 534d510eccfSStanley.Yang mutex_unlock(&adev->pm.mutex); 535d510eccfSStanley.Yang 536d510eccfSStanley.Yang return ret; 537d510eccfSStanley.Yang } 538d510eccfSStanley.Yang 539bc143d8bSEvan Quan int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, 540bc143d8bSEvan Quan enum pp_clock_type type, 541bc143d8bSEvan Quan uint32_t *min, 542bc143d8bSEvan Quan uint32_t *max) 543bc143d8bSEvan Quan { 5443712e7a4SEvan Quan int ret = 0; 5453712e7a4SEvan Quan 5463712e7a4SEvan Quan if (type != PP_SCLK) 5473712e7a4SEvan Quan return -EINVAL; 5483712e7a4SEvan Quan 549bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 550bc143d8bSEvan Quan return -EOPNOTSUPP; 551bc143d8bSEvan Quan 5523712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5533712e7a4SEvan Quan ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle, 5543712e7a4SEvan Quan SMU_SCLK, 5553712e7a4SEvan Quan min, 5563712e7a4SEvan Quan max); 5573712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5583712e7a4SEvan Quan 5593712e7a4SEvan Quan return ret; 560bc143d8bSEvan Quan } 561bc143d8bSEvan Quan 562bc143d8bSEvan Quan int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, 563bc143d8bSEvan Quan enum pp_clock_type type, 564bc143d8bSEvan Quan uint32_t min, 565bc143d8bSEvan Quan uint32_t max) 566bc143d8bSEvan Quan { 567ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 5683712e7a4SEvan Quan int ret = 0; 5693712e7a4SEvan Quan 5703712e7a4SEvan Quan if (type != PP_SCLK) 5713712e7a4SEvan Quan return -EINVAL; 572ebfc2533SEvan Quan 573bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 574bc143d8bSEvan Quan return -EOPNOTSUPP; 575bc143d8bSEvan Quan 5763712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5773712e7a4SEvan Quan ret = smu_set_soft_freq_range(smu, 5783712e7a4SEvan Quan SMU_SCLK, 5793712e7a4SEvan Quan min, 5803712e7a4SEvan Quan max); 5813712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5823712e7a4SEvan Quan 5833712e7a4SEvan Quan return ret; 584bc143d8bSEvan Quan } 585bc143d8bSEvan Quan 58613f5dbd6SEvan Quan int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) 58713f5dbd6SEvan Quan { 588ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 5893712e7a4SEvan Quan int ret = 0; 590ebfc2533SEvan Quan 59113f5dbd6SEvan Quan if (!is_support_sw_smu(adev)) 59213f5dbd6SEvan Quan return 0; 59313f5dbd6SEvan Quan 5943712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 5953712e7a4SEvan Quan ret = smu_write_watermarks_table(smu); 5963712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 5973712e7a4SEvan Quan 5983712e7a4SEvan Quan return ret; 59913f5dbd6SEvan Quan } 60013f5dbd6SEvan Quan 601bc143d8bSEvan Quan int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, 602bc143d8bSEvan Quan enum smu_event_type event, 603bc143d8bSEvan Quan uint64_t event_arg) 604bc143d8bSEvan Quan { 605ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6063712e7a4SEvan Quan int ret = 0; 607ebfc2533SEvan Quan 608bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 609bc143d8bSEvan Quan return -EOPNOTSUPP; 610bc143d8bSEvan Quan 6113712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6123712e7a4SEvan Quan ret = smu_wait_for_event(smu, event, event_arg); 6133712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6143712e7a4SEvan Quan 6153712e7a4SEvan Quan return ret; 616bc143d8bSEvan Quan } 617bc143d8bSEvan Quan 618bc143d8bSEvan Quan int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) 619bc143d8bSEvan Quan { 620ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 6213712e7a4SEvan Quan int ret = 0; 622ebfc2533SEvan Quan 623bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 624bc143d8bSEvan Quan return -EOPNOTSUPP; 625bc143d8bSEvan Quan 6263712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6273712e7a4SEvan Quan ret = smu_get_status_gfxoff(smu, value); 6283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6293712e7a4SEvan Quan 6303712e7a4SEvan Quan return ret; 631bc143d8bSEvan Quan } 632bc143d8bSEvan Quan 633bc143d8bSEvan Quan uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) 634bc143d8bSEvan Quan { 635ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 636ebfc2533SEvan Quan 6373712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 6383712e7a4SEvan Quan return 0; 6393712e7a4SEvan Quan 640ebfc2533SEvan Quan return atomic64_read(&smu->throttle_int_counter); 641bc143d8bSEvan Quan } 642bc143d8bSEvan Quan 643bc143d8bSEvan Quan /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set 644bc143d8bSEvan Quan * @adev: amdgpu_device pointer 645bc143d8bSEvan Quan * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) 646bc143d8bSEvan Quan * 647bc143d8bSEvan Quan */ 648bc143d8bSEvan Quan void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, 649bc143d8bSEvan Quan enum gfx_change_state state) 650bc143d8bSEvan Quan { 651bc143d8bSEvan Quan mutex_lock(&adev->pm.mutex); 652bc143d8bSEvan Quan if (adev->powerplay.pp_funcs && 653bc143d8bSEvan Quan adev->powerplay.pp_funcs->gfx_state_change_set) 654bc143d8bSEvan Quan ((adev)->powerplay.pp_funcs->gfx_state_change_set( 655bc143d8bSEvan Quan (adev)->powerplay.pp_handle, state)); 656bc143d8bSEvan Quan mutex_unlock(&adev->pm.mutex); 657bc143d8bSEvan Quan } 658bc143d8bSEvan Quan 659bc143d8bSEvan Quan int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, 660bc143d8bSEvan Quan void *umc_ecc) 661bc143d8bSEvan Quan { 662ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 663a29d44aeSStanley.Yang int ret = 0; 664ebfc2533SEvan Quan 665bc143d8bSEvan Quan if (!is_support_sw_smu(adev)) 666bc143d8bSEvan Quan return -EOPNOTSUPP; 667bc143d8bSEvan Quan 668a29d44aeSStanley.Yang mutex_lock(&adev->pm.mutex); 669a29d44aeSStanley.Yang ret = smu_get_ecc_info(smu, umc_ecc); 670a29d44aeSStanley.Yang mutex_unlock(&adev->pm.mutex); 671a29d44aeSStanley.Yang 672a29d44aeSStanley.Yang return ret; 673bc143d8bSEvan Quan } 67479c65f3fSEvan Quan 67579c65f3fSEvan Quan struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, 67679c65f3fSEvan Quan uint32_t idx) 67779c65f3fSEvan Quan { 67879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 6793712e7a4SEvan Quan struct amd_vce_state *vstate = NULL; 68079c65f3fSEvan Quan 68179c65f3fSEvan Quan if (!pp_funcs->get_vce_clock_state) 68279c65f3fSEvan Quan return NULL; 68379c65f3fSEvan Quan 6843712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6853712e7a4SEvan Quan vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, 68679c65f3fSEvan Quan idx); 6873712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 6883712e7a4SEvan Quan 6893712e7a4SEvan Quan return vstate; 69079c65f3fSEvan Quan } 69179c65f3fSEvan Quan 69279c65f3fSEvan Quan void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, 69379c65f3fSEvan Quan enum amd_pm_state_type *state) 69479c65f3fSEvan Quan { 69579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 69679c65f3fSEvan Quan 6973712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 6983712e7a4SEvan Quan 69979c65f3fSEvan Quan if (!pp_funcs->get_current_power_state) { 70079c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 7013712e7a4SEvan Quan goto out; 70279c65f3fSEvan Quan } 70379c65f3fSEvan Quan 70479c65f3fSEvan Quan *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); 70579c65f3fSEvan Quan if (*state < POWER_STATE_TYPE_DEFAULT || 70679c65f3fSEvan Quan *state > POWER_STATE_TYPE_INTERNAL_3DPERF) 70779c65f3fSEvan Quan *state = adev->pm.dpm.user_state; 7083712e7a4SEvan Quan 7093712e7a4SEvan Quan out: 7103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 71179c65f3fSEvan Quan } 71279c65f3fSEvan Quan 71379c65f3fSEvan Quan void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, 71479c65f3fSEvan Quan enum amd_pm_state_type state) 71579c65f3fSEvan Quan { 7163712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 71779c65f3fSEvan Quan adev->pm.dpm.user_state = state; 7183712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 71979c65f3fSEvan Quan 72079c65f3fSEvan Quan if (is_support_sw_smu(adev)) 72179c65f3fSEvan Quan return; 72279c65f3fSEvan Quan 72379c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 72479c65f3fSEvan Quan AMD_PP_TASK_ENABLE_USER_STATE, 72579c65f3fSEvan Quan &state) == -EOPNOTSUPP) 72684176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 72779c65f3fSEvan Quan } 72879c65f3fSEvan Quan 72975513bf5SEvan Quan enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) 73079c65f3fSEvan Quan { 73179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 73279c65f3fSEvan Quan enum amd_dpm_forced_level level; 73379c65f3fSEvan Quan 73475513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 73579c65f3fSEvan Quan if (pp_funcs->get_performance_level) 73679c65f3fSEvan Quan level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); 73779c65f3fSEvan Quan else 73879c65f3fSEvan Quan level = adev->pm.dpm.forced_level; 7393712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 74079c65f3fSEvan Quan 74179c65f3fSEvan Quan return level; 74279c65f3fSEvan Quan } 74379c65f3fSEvan Quan 74479c65f3fSEvan Quan int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, 74579c65f3fSEvan Quan enum amd_dpm_forced_level level) 74679c65f3fSEvan Quan { 74779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 74854c73b51SAlex Deucher enum amd_dpm_forced_level current_level; 74954c73b51SAlex Deucher uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | 75054c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | 75154c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | 75254c73b51SAlex Deucher AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; 75379c65f3fSEvan Quan 7543712e7a4SEvan Quan if (!pp_funcs->force_performance_level) 7553712e7a4SEvan Quan return 0; 7563712e7a4SEvan Quan 75775513bf5SEvan Quan if (adev->pm.dpm.thermal_active) 75875513bf5SEvan Quan return -EINVAL; 7593712e7a4SEvan Quan 76075513bf5SEvan Quan current_level = amdgpu_dpm_get_performance_level(adev); 76175513bf5SEvan Quan if (current_level == level) 76275513bf5SEvan Quan return 0; 76354c73b51SAlex Deucher 76454c73b51SAlex Deucher if (adev->asic_type == CHIP_RAVEN) { 76554c73b51SAlex Deucher if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { 76654c73b51SAlex Deucher if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && 76754c73b51SAlex Deucher level == AMD_DPM_FORCED_LEVEL_MANUAL) 76854c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, false); 76954c73b51SAlex Deucher else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && 77054c73b51SAlex Deucher level != AMD_DPM_FORCED_LEVEL_MANUAL) 77154c73b51SAlex Deucher amdgpu_gfx_off_ctrl(adev, true); 77254c73b51SAlex Deucher } 77354c73b51SAlex Deucher } 77454c73b51SAlex Deucher 77554c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 77675513bf5SEvan Quan (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) 77775513bf5SEvan Quan return -EINVAL; 77854c73b51SAlex Deucher 77954c73b51SAlex Deucher if (!(current_level & profile_mode_mask) && 78054c73b51SAlex Deucher (level & profile_mode_mask)) { 78154c73b51SAlex Deucher /* enter UMD Pstate */ 78254c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 78354c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 78454c73b51SAlex Deucher AMD_PG_STATE_UNGATE); 78554c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 78654c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 78754c73b51SAlex Deucher AMD_CG_STATE_UNGATE); 78854c73b51SAlex Deucher } else if ((current_level & profile_mode_mask) && 78954c73b51SAlex Deucher !(level & profile_mode_mask)) { 79054c73b51SAlex Deucher /* exit UMD Pstate */ 79154c73b51SAlex Deucher amdgpu_device_ip_set_clockgating_state(adev, 79254c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 79354c73b51SAlex Deucher AMD_CG_STATE_GATE); 79454c73b51SAlex Deucher amdgpu_device_ip_set_powergating_state(adev, 79554c73b51SAlex Deucher AMD_IP_BLOCK_TYPE_GFX, 79654c73b51SAlex Deucher AMD_PG_STATE_GATE); 79754c73b51SAlex Deucher } 79854c73b51SAlex Deucher 79975513bf5SEvan Quan mutex_lock(&adev->pm.mutex); 80079c65f3fSEvan Quan 80175513bf5SEvan Quan if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, 80275513bf5SEvan Quan level)) { 80375513bf5SEvan Quan mutex_unlock(&adev->pm.mutex); 80475513bf5SEvan Quan return -EINVAL; 80575513bf5SEvan Quan } 80675513bf5SEvan Quan 80779c65f3fSEvan Quan adev->pm.dpm.forced_level = level; 80879c65f3fSEvan Quan 8093712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8103712e7a4SEvan Quan 81175513bf5SEvan Quan return 0; 81279c65f3fSEvan Quan } 81379c65f3fSEvan Quan 81479c65f3fSEvan Quan int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, 81579c65f3fSEvan Quan struct pp_states_info *states) 81679c65f3fSEvan Quan { 81779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 8183712e7a4SEvan Quan int ret = 0; 81979c65f3fSEvan Quan 82079c65f3fSEvan Quan if (!pp_funcs->get_pp_num_states) 82179c65f3fSEvan Quan return -EOPNOTSUPP; 82279c65f3fSEvan Quan 8233712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8243712e7a4SEvan Quan ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, 8253712e7a4SEvan Quan states); 8263712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8273712e7a4SEvan Quan 8283712e7a4SEvan Quan return ret; 82979c65f3fSEvan Quan } 83079c65f3fSEvan Quan 83179c65f3fSEvan Quan int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, 83279c65f3fSEvan Quan enum amd_pp_task task_id, 83379c65f3fSEvan Quan enum amd_pm_state_type *user_state) 83479c65f3fSEvan Quan { 83579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 8363712e7a4SEvan Quan int ret = 0; 83779c65f3fSEvan Quan 83879c65f3fSEvan Quan if (!pp_funcs->dispatch_tasks) 83979c65f3fSEvan Quan return -EOPNOTSUPP; 84079c65f3fSEvan Quan 8413712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8423712e7a4SEvan Quan ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, 8433712e7a4SEvan Quan task_id, 8443712e7a4SEvan Quan user_state); 8453712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8463712e7a4SEvan Quan 8473712e7a4SEvan Quan return ret; 84879c65f3fSEvan Quan } 84979c65f3fSEvan Quan 85079c65f3fSEvan Quan int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) 85179c65f3fSEvan Quan { 85279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 8533712e7a4SEvan Quan int ret = 0; 85479c65f3fSEvan Quan 85579c65f3fSEvan Quan if (!pp_funcs->get_pp_table) 85679c65f3fSEvan Quan return 0; 85779c65f3fSEvan Quan 8583712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8593712e7a4SEvan Quan ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, 8603712e7a4SEvan Quan table); 8613712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8623712e7a4SEvan Quan 8633712e7a4SEvan Quan return ret; 86479c65f3fSEvan Quan } 86579c65f3fSEvan Quan 86679c65f3fSEvan Quan int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, 86779c65f3fSEvan Quan uint32_t type, 86879c65f3fSEvan Quan long *input, 86979c65f3fSEvan Quan uint32_t size) 87079c65f3fSEvan Quan { 87179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 8723712e7a4SEvan Quan int ret = 0; 87379c65f3fSEvan Quan 87479c65f3fSEvan Quan if (!pp_funcs->set_fine_grain_clk_vol) 87579c65f3fSEvan Quan return 0; 87679c65f3fSEvan Quan 8773712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8783712e7a4SEvan Quan ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, 87979c65f3fSEvan Quan type, 88079c65f3fSEvan Quan input, 88179c65f3fSEvan Quan size); 8823712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 8833712e7a4SEvan Quan 8843712e7a4SEvan Quan return ret; 88579c65f3fSEvan Quan } 88679c65f3fSEvan Quan 88779c65f3fSEvan Quan int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, 88879c65f3fSEvan Quan uint32_t type, 88979c65f3fSEvan Quan long *input, 89079c65f3fSEvan Quan uint32_t size) 89179c65f3fSEvan Quan { 89279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 8933712e7a4SEvan Quan int ret = 0; 89479c65f3fSEvan Quan 89579c65f3fSEvan Quan if (!pp_funcs->odn_edit_dpm_table) 89679c65f3fSEvan Quan return 0; 89779c65f3fSEvan Quan 8983712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 8993712e7a4SEvan Quan ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, 90079c65f3fSEvan Quan type, 90179c65f3fSEvan Quan input, 90279c65f3fSEvan Quan size); 9033712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9043712e7a4SEvan Quan 9053712e7a4SEvan Quan return ret; 90679c65f3fSEvan Quan } 90779c65f3fSEvan Quan 90879c65f3fSEvan Quan int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, 90979c65f3fSEvan Quan enum pp_clock_type type, 91079c65f3fSEvan Quan char *buf) 91179c65f3fSEvan Quan { 91279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9133712e7a4SEvan Quan int ret = 0; 91479c65f3fSEvan Quan 91579c65f3fSEvan Quan if (!pp_funcs->print_clock_levels) 91679c65f3fSEvan Quan return 0; 91779c65f3fSEvan Quan 9183712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9193712e7a4SEvan Quan ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle, 92079c65f3fSEvan Quan type, 92179c65f3fSEvan Quan buf); 9223712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9233712e7a4SEvan Quan 9243712e7a4SEvan Quan return ret; 92579c65f3fSEvan Quan } 92679c65f3fSEvan Quan 9275d64f9bbSDarren Powell int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, 9285d64f9bbSDarren Powell enum pp_clock_type type, 9295d64f9bbSDarren Powell char *buf, 9305d64f9bbSDarren Powell int *offset) 9315d64f9bbSDarren Powell { 9325d64f9bbSDarren Powell const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9335d64f9bbSDarren Powell int ret = 0; 9345d64f9bbSDarren Powell 9355d64f9bbSDarren Powell if (!pp_funcs->emit_clock_levels) 9365d64f9bbSDarren Powell return -ENOENT; 9375d64f9bbSDarren Powell 9385d64f9bbSDarren Powell mutex_lock(&adev->pm.mutex); 9395d64f9bbSDarren Powell ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle, 9405d64f9bbSDarren Powell type, 9415d64f9bbSDarren Powell buf, 9425d64f9bbSDarren Powell offset); 9435d64f9bbSDarren Powell mutex_unlock(&adev->pm.mutex); 9445d64f9bbSDarren Powell 9455d64f9bbSDarren Powell return ret; 9465d64f9bbSDarren Powell } 9475d64f9bbSDarren Powell 94879c65f3fSEvan Quan int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, 94979c65f3fSEvan Quan uint64_t ppfeature_masks) 95079c65f3fSEvan Quan { 95179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9523712e7a4SEvan Quan int ret = 0; 95379c65f3fSEvan Quan 95479c65f3fSEvan Quan if (!pp_funcs->set_ppfeature_status) 95579c65f3fSEvan Quan return 0; 95679c65f3fSEvan Quan 9573712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9583712e7a4SEvan Quan ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, 95979c65f3fSEvan Quan ppfeature_masks); 9603712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9613712e7a4SEvan Quan 9623712e7a4SEvan Quan return ret; 96379c65f3fSEvan Quan } 96479c65f3fSEvan Quan 96579c65f3fSEvan Quan int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) 96679c65f3fSEvan Quan { 96779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9683712e7a4SEvan Quan int ret = 0; 96979c65f3fSEvan Quan 97079c65f3fSEvan Quan if (!pp_funcs->get_ppfeature_status) 97179c65f3fSEvan Quan return 0; 97279c65f3fSEvan Quan 9733712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9743712e7a4SEvan Quan ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, 97579c65f3fSEvan Quan buf); 9763712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9773712e7a4SEvan Quan 9783712e7a4SEvan Quan return ret; 97979c65f3fSEvan Quan } 98079c65f3fSEvan Quan 98179c65f3fSEvan Quan int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, 98279c65f3fSEvan Quan enum pp_clock_type type, 98379c65f3fSEvan Quan uint32_t mask) 98479c65f3fSEvan Quan { 98579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 9863712e7a4SEvan Quan int ret = 0; 98779c65f3fSEvan Quan 98879c65f3fSEvan Quan if (!pp_funcs->force_clock_level) 98979c65f3fSEvan Quan return 0; 99079c65f3fSEvan Quan 9913712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 9923712e7a4SEvan Quan ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle, 99379c65f3fSEvan Quan type, 99479c65f3fSEvan Quan mask); 9953712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 9963712e7a4SEvan Quan 9973712e7a4SEvan Quan return ret; 99879c65f3fSEvan Quan } 99979c65f3fSEvan Quan 100079c65f3fSEvan Quan int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) 100179c65f3fSEvan Quan { 100279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10033712e7a4SEvan Quan int ret = 0; 100479c65f3fSEvan Quan 100579c65f3fSEvan Quan if (!pp_funcs->get_sclk_od) 100679c65f3fSEvan Quan return 0; 100779c65f3fSEvan Quan 10083712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10093712e7a4SEvan Quan ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle); 10103712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10113712e7a4SEvan Quan 10123712e7a4SEvan Quan return ret; 101379c65f3fSEvan Quan } 101479c65f3fSEvan Quan 101579c65f3fSEvan Quan int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) 101679c65f3fSEvan Quan { 101779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 101879c65f3fSEvan Quan 101979c65f3fSEvan Quan if (is_support_sw_smu(adev)) 102079c65f3fSEvan Quan return 0; 102179c65f3fSEvan Quan 10223712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 102379c65f3fSEvan Quan if (pp_funcs->set_sclk_od) 102479c65f3fSEvan Quan pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); 10253712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 102679c65f3fSEvan Quan 102779c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 102879c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 102979c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 103079c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 103184176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 103279c65f3fSEvan Quan } 103379c65f3fSEvan Quan 103479c65f3fSEvan Quan return 0; 103579c65f3fSEvan Quan } 103679c65f3fSEvan Quan 103779c65f3fSEvan Quan int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) 103879c65f3fSEvan Quan { 103979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10403712e7a4SEvan Quan int ret = 0; 104179c65f3fSEvan Quan 104279c65f3fSEvan Quan if (!pp_funcs->get_mclk_od) 104379c65f3fSEvan Quan return 0; 104479c65f3fSEvan Quan 10453712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10463712e7a4SEvan Quan ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle); 10473712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10483712e7a4SEvan Quan 10493712e7a4SEvan Quan return ret; 105079c65f3fSEvan Quan } 105179c65f3fSEvan Quan 105279c65f3fSEvan Quan int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) 105379c65f3fSEvan Quan { 105479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 105579c65f3fSEvan Quan 105679c65f3fSEvan Quan if (is_support_sw_smu(adev)) 105779c65f3fSEvan Quan return 0; 105879c65f3fSEvan Quan 10593712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 106079c65f3fSEvan Quan if (pp_funcs->set_mclk_od) 106179c65f3fSEvan Quan pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); 10623712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 106379c65f3fSEvan Quan 106479c65f3fSEvan Quan if (amdgpu_dpm_dispatch_task(adev, 106579c65f3fSEvan Quan AMD_PP_TASK_READJUST_POWER_STATE, 106679c65f3fSEvan Quan NULL) == -EOPNOTSUPP) { 106779c65f3fSEvan Quan adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 106884176663SEvan Quan amdgpu_dpm_compute_clocks(adev); 106979c65f3fSEvan Quan } 107079c65f3fSEvan Quan 107179c65f3fSEvan Quan return 0; 107279c65f3fSEvan Quan } 107379c65f3fSEvan Quan 107479c65f3fSEvan Quan int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, 107579c65f3fSEvan Quan char *buf) 107679c65f3fSEvan Quan { 107779c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10783712e7a4SEvan Quan int ret = 0; 107979c65f3fSEvan Quan 108079c65f3fSEvan Quan if (!pp_funcs->get_power_profile_mode) 108179c65f3fSEvan Quan return -EOPNOTSUPP; 108279c65f3fSEvan Quan 10833712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 10843712e7a4SEvan Quan ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, 108579c65f3fSEvan Quan buf); 10863712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 10873712e7a4SEvan Quan 10883712e7a4SEvan Quan return ret; 108979c65f3fSEvan Quan } 109079c65f3fSEvan Quan 109179c65f3fSEvan Quan int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, 109279c65f3fSEvan Quan long *input, uint32_t size) 109379c65f3fSEvan Quan { 109479c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 10953712e7a4SEvan Quan int ret = 0; 109679c65f3fSEvan Quan 109779c65f3fSEvan Quan if (!pp_funcs->set_power_profile_mode) 109879c65f3fSEvan Quan return 0; 109979c65f3fSEvan Quan 11003712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11013712e7a4SEvan Quan ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, 110279c65f3fSEvan Quan input, 110379c65f3fSEvan Quan size); 11043712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11053712e7a4SEvan Quan 11063712e7a4SEvan Quan return ret; 110779c65f3fSEvan Quan } 110879c65f3fSEvan Quan 110979c65f3fSEvan Quan int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) 111079c65f3fSEvan Quan { 111179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11123712e7a4SEvan Quan int ret = 0; 111379c65f3fSEvan Quan 111479c65f3fSEvan Quan if (!pp_funcs->get_gpu_metrics) 111579c65f3fSEvan Quan return 0; 111679c65f3fSEvan Quan 11173712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11183712e7a4SEvan Quan ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, 11193712e7a4SEvan Quan table); 11203712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11213712e7a4SEvan Quan 11223712e7a4SEvan Quan return ret; 112379c65f3fSEvan Quan } 112479c65f3fSEvan Quan 112579c65f3fSEvan Quan int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, 112679c65f3fSEvan Quan uint32_t *fan_mode) 112779c65f3fSEvan Quan { 112879c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1129685fae24SEvan Quan int ret = 0; 113079c65f3fSEvan Quan 113179c65f3fSEvan Quan if (!pp_funcs->get_fan_control_mode) 113279c65f3fSEvan Quan return -EOPNOTSUPP; 113379c65f3fSEvan Quan 11343712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1135685fae24SEvan Quan ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, 1136685fae24SEvan Quan fan_mode); 11373712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 113879c65f3fSEvan Quan 1139685fae24SEvan Quan return ret; 114079c65f3fSEvan Quan } 114179c65f3fSEvan Quan 114279c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, 114379c65f3fSEvan Quan uint32_t speed) 114479c65f3fSEvan Quan { 114579c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11463712e7a4SEvan Quan int ret = 0; 114779c65f3fSEvan Quan 114879c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_pwm) 1149685fae24SEvan Quan return -EOPNOTSUPP; 115079c65f3fSEvan Quan 11513712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11523712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, 11533712e7a4SEvan Quan speed); 11543712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11553712e7a4SEvan Quan 11563712e7a4SEvan Quan return ret; 115779c65f3fSEvan Quan } 115879c65f3fSEvan Quan 115979c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, 116079c65f3fSEvan Quan uint32_t *speed) 116179c65f3fSEvan Quan { 116279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11633712e7a4SEvan Quan int ret = 0; 116479c65f3fSEvan Quan 116579c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_pwm) 1166685fae24SEvan Quan return -EOPNOTSUPP; 116779c65f3fSEvan Quan 11683712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11693712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, 11703712e7a4SEvan Quan speed); 11713712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11723712e7a4SEvan Quan 11733712e7a4SEvan Quan return ret; 117479c65f3fSEvan Quan } 117579c65f3fSEvan Quan 117679c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, 117779c65f3fSEvan Quan uint32_t *speed) 117879c65f3fSEvan Quan { 117979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11803712e7a4SEvan Quan int ret = 0; 118179c65f3fSEvan Quan 118279c65f3fSEvan Quan if (!pp_funcs->get_fan_speed_rpm) 1183685fae24SEvan Quan return -EOPNOTSUPP; 118479c65f3fSEvan Quan 11853712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 11863712e7a4SEvan Quan ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, 11873712e7a4SEvan Quan speed); 11883712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 11893712e7a4SEvan Quan 11903712e7a4SEvan Quan return ret; 119179c65f3fSEvan Quan } 119279c65f3fSEvan Quan 119379c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, 119479c65f3fSEvan Quan uint32_t speed) 119579c65f3fSEvan Quan { 119679c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 11973712e7a4SEvan Quan int ret = 0; 119879c65f3fSEvan Quan 119979c65f3fSEvan Quan if (!pp_funcs->set_fan_speed_rpm) 1200685fae24SEvan Quan return -EOPNOTSUPP; 120179c65f3fSEvan Quan 12023712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12033712e7a4SEvan Quan ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, 12043712e7a4SEvan Quan speed); 12053712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12063712e7a4SEvan Quan 12073712e7a4SEvan Quan return ret; 120879c65f3fSEvan Quan } 120979c65f3fSEvan Quan 121079c65f3fSEvan Quan int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, 121179c65f3fSEvan Quan uint32_t mode) 121279c65f3fSEvan Quan { 121379c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1214685fae24SEvan Quan int ret = 0; 121579c65f3fSEvan Quan 121679c65f3fSEvan Quan if (!pp_funcs->set_fan_control_mode) 121779c65f3fSEvan Quan return -EOPNOTSUPP; 121879c65f3fSEvan Quan 12193712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 1220685fae24SEvan Quan ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, 12213712e7a4SEvan Quan mode); 12223712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 122379c65f3fSEvan Quan 1224685fae24SEvan Quan return ret; 122579c65f3fSEvan Quan } 122679c65f3fSEvan Quan 122779c65f3fSEvan Quan int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, 122879c65f3fSEvan Quan uint32_t *limit, 122979c65f3fSEvan Quan enum pp_power_limit_level pp_limit_level, 123079c65f3fSEvan Quan enum pp_power_type power_type) 123179c65f3fSEvan Quan { 123279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12333712e7a4SEvan Quan int ret = 0; 123479c65f3fSEvan Quan 123579c65f3fSEvan Quan if (!pp_funcs->get_power_limit) 123679c65f3fSEvan Quan return -ENODATA; 123779c65f3fSEvan Quan 12383712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12393712e7a4SEvan Quan ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle, 124079c65f3fSEvan Quan limit, 124179c65f3fSEvan Quan pp_limit_level, 124279c65f3fSEvan Quan power_type); 12433712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12443712e7a4SEvan Quan 12453712e7a4SEvan Quan return ret; 124679c65f3fSEvan Quan } 124779c65f3fSEvan Quan 124879c65f3fSEvan Quan int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, 124979c65f3fSEvan Quan uint32_t limit) 125079c65f3fSEvan Quan { 125179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 12523712e7a4SEvan Quan int ret = 0; 125379c65f3fSEvan Quan 125479c65f3fSEvan Quan if (!pp_funcs->set_power_limit) 125579c65f3fSEvan Quan return -EINVAL; 125679c65f3fSEvan Quan 12573712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12583712e7a4SEvan Quan ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle, 12593712e7a4SEvan Quan limit); 12603712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12613712e7a4SEvan Quan 12623712e7a4SEvan Quan return ret; 126379c65f3fSEvan Quan } 126479c65f3fSEvan Quan 126579c65f3fSEvan Quan int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) 126679c65f3fSEvan Quan { 12673712e7a4SEvan Quan bool cclk_dpm_supported = false; 12683712e7a4SEvan Quan 126979c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 127079c65f3fSEvan Quan return false; 127179c65f3fSEvan Quan 12723712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 12733712e7a4SEvan Quan cclk_dpm_supported = is_support_cclk_dpm(adev); 12743712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 12753712e7a4SEvan Quan 12763712e7a4SEvan Quan return (int)cclk_dpm_supported; 127779c65f3fSEvan Quan } 127879c65f3fSEvan Quan 127979c65f3fSEvan Quan int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, 128079c65f3fSEvan Quan struct seq_file *m) 128179c65f3fSEvan Quan { 128279c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 128379c65f3fSEvan Quan 128479c65f3fSEvan Quan if (!pp_funcs->debugfs_print_current_performance_level) 128579c65f3fSEvan Quan return -EOPNOTSUPP; 128679c65f3fSEvan Quan 12873712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 128879c65f3fSEvan Quan pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, 128979c65f3fSEvan Quan m); 12903712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 129179c65f3fSEvan Quan 129279c65f3fSEvan Quan return 0; 129379c65f3fSEvan Quan } 129479c65f3fSEvan Quan 129579c65f3fSEvan Quan int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, 129679c65f3fSEvan Quan void **addr, 129779c65f3fSEvan Quan size_t *size) 129879c65f3fSEvan Quan { 129979c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13003712e7a4SEvan Quan int ret = 0; 130179c65f3fSEvan Quan 130279c65f3fSEvan Quan if (!pp_funcs->get_smu_prv_buf_details) 130379c65f3fSEvan Quan return -ENOSYS; 130479c65f3fSEvan Quan 13053712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13063712e7a4SEvan Quan ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, 130779c65f3fSEvan Quan addr, 130879c65f3fSEvan Quan size); 13093712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13103712e7a4SEvan Quan 13113712e7a4SEvan Quan return ret; 131279c65f3fSEvan Quan } 131379c65f3fSEvan Quan 131479c65f3fSEvan Quan int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) 131579c65f3fSEvan Quan { 131679c65f3fSEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; 1317ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 131879c65f3fSEvan Quan 1319ebfc2533SEvan Quan if ((is_support_sw_smu(adev) && smu->od_enabled) || 1320ebfc2533SEvan Quan (is_support_sw_smu(adev) && smu->is_apu) || 132179c65f3fSEvan Quan (!is_support_sw_smu(adev) && hwmgr->od_enabled)) 132279c65f3fSEvan Quan return true; 132379c65f3fSEvan Quan 132479c65f3fSEvan Quan return false; 132579c65f3fSEvan Quan } 132679c65f3fSEvan Quan 132779c65f3fSEvan Quan int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, 132879c65f3fSEvan Quan const char *buf, 132979c65f3fSEvan Quan size_t size) 133079c65f3fSEvan Quan { 133179c65f3fSEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13323712e7a4SEvan Quan int ret = 0; 133379c65f3fSEvan Quan 133479c65f3fSEvan Quan if (!pp_funcs->set_pp_table) 133579c65f3fSEvan Quan return -EOPNOTSUPP; 133679c65f3fSEvan Quan 13373712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13383712e7a4SEvan Quan ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle, 133979c65f3fSEvan Quan buf, 134079c65f3fSEvan Quan size); 13413712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13423712e7a4SEvan Quan 13433712e7a4SEvan Quan return ret; 134479c65f3fSEvan Quan } 134579c65f3fSEvan Quan 134679c65f3fSEvan Quan int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) 134779c65f3fSEvan Quan { 1348ebfc2533SEvan Quan struct smu_context *smu = adev->powerplay.pp_handle; 1349ebfc2533SEvan Quan 13503712e7a4SEvan Quan if (!is_support_sw_smu(adev)) 13513712e7a4SEvan Quan return INT_MAX; 13523712e7a4SEvan Quan 1353ebfc2533SEvan Quan return smu->cpu_core_num; 135479c65f3fSEvan Quan } 135579c65f3fSEvan Quan 135679c65f3fSEvan Quan void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) 135779c65f3fSEvan Quan { 135879c65f3fSEvan Quan if (!is_support_sw_smu(adev)) 135979c65f3fSEvan Quan return; 136079c65f3fSEvan Quan 136179c65f3fSEvan Quan amdgpu_smu_stb_debug_fs_init(adev); 136279c65f3fSEvan Quan } 136313f5dbd6SEvan Quan 136413f5dbd6SEvan Quan int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, 136513f5dbd6SEvan Quan const struct amd_pp_display_configuration *input) 136613f5dbd6SEvan Quan { 136713f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13683712e7a4SEvan Quan int ret = 0; 136913f5dbd6SEvan Quan 137013f5dbd6SEvan Quan if (!pp_funcs->display_configuration_change) 137113f5dbd6SEvan Quan return 0; 137213f5dbd6SEvan Quan 13733712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13743712e7a4SEvan Quan ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle, 137513f5dbd6SEvan Quan input); 13763712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13773712e7a4SEvan Quan 13783712e7a4SEvan Quan return ret; 137913f5dbd6SEvan Quan } 138013f5dbd6SEvan Quan 138113f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, 138213f5dbd6SEvan Quan enum amd_pp_clock_type type, 138313f5dbd6SEvan Quan struct amd_pp_clocks *clocks) 138413f5dbd6SEvan Quan { 138513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 13863712e7a4SEvan Quan int ret = 0; 138713f5dbd6SEvan Quan 138813f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type) 138913f5dbd6SEvan Quan return 0; 139013f5dbd6SEvan Quan 13913712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 13923712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, 139313f5dbd6SEvan Quan type, 139413f5dbd6SEvan Quan clocks); 13953712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 13963712e7a4SEvan Quan 13973712e7a4SEvan Quan return ret; 139813f5dbd6SEvan Quan } 139913f5dbd6SEvan Quan 140013f5dbd6SEvan Quan int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, 140113f5dbd6SEvan Quan struct amd_pp_simple_clock_info *clocks) 140213f5dbd6SEvan Quan { 140313f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14043712e7a4SEvan Quan int ret = 0; 140513f5dbd6SEvan Quan 140613f5dbd6SEvan Quan if (!pp_funcs->get_display_mode_validation_clocks) 140713f5dbd6SEvan Quan return 0; 140813f5dbd6SEvan Quan 14093712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14103712e7a4SEvan Quan ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, 141113f5dbd6SEvan Quan clocks); 14123712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14133712e7a4SEvan Quan 14143712e7a4SEvan Quan return ret; 141513f5dbd6SEvan Quan } 141613f5dbd6SEvan Quan 141713f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, 141813f5dbd6SEvan Quan enum amd_pp_clock_type type, 141913f5dbd6SEvan Quan struct pp_clock_levels_with_latency *clocks) 142013f5dbd6SEvan Quan { 142113f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14223712e7a4SEvan Quan int ret = 0; 142313f5dbd6SEvan Quan 142413f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_latency) 142513f5dbd6SEvan Quan return 0; 142613f5dbd6SEvan Quan 14273712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14283712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, 142913f5dbd6SEvan Quan type, 143013f5dbd6SEvan Quan clocks); 14313712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14323712e7a4SEvan Quan 14333712e7a4SEvan Quan return ret; 143413f5dbd6SEvan Quan } 143513f5dbd6SEvan Quan 143613f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, 143713f5dbd6SEvan Quan enum amd_pp_clock_type type, 143813f5dbd6SEvan Quan struct pp_clock_levels_with_voltage *clocks) 143913f5dbd6SEvan Quan { 144013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14413712e7a4SEvan Quan int ret = 0; 144213f5dbd6SEvan Quan 144313f5dbd6SEvan Quan if (!pp_funcs->get_clock_by_type_with_voltage) 144413f5dbd6SEvan Quan return 0; 144513f5dbd6SEvan Quan 14463712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14473712e7a4SEvan Quan ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, 144813f5dbd6SEvan Quan type, 144913f5dbd6SEvan Quan clocks); 14503712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14513712e7a4SEvan Quan 14523712e7a4SEvan Quan return ret; 145313f5dbd6SEvan Quan } 145413f5dbd6SEvan Quan 145513f5dbd6SEvan Quan int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, 145613f5dbd6SEvan Quan void *clock_ranges) 145713f5dbd6SEvan Quan { 145813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14593712e7a4SEvan Quan int ret = 0; 146013f5dbd6SEvan Quan 146113f5dbd6SEvan Quan if (!pp_funcs->set_watermarks_for_clocks_ranges) 146213f5dbd6SEvan Quan return -EOPNOTSUPP; 146313f5dbd6SEvan Quan 14643712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14653712e7a4SEvan Quan ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, 146613f5dbd6SEvan Quan clock_ranges); 14673712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14683712e7a4SEvan Quan 14693712e7a4SEvan Quan return ret; 147013f5dbd6SEvan Quan } 147113f5dbd6SEvan Quan 147213f5dbd6SEvan Quan int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, 147313f5dbd6SEvan Quan struct pp_display_clock_request *clock) 147413f5dbd6SEvan Quan { 147513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14763712e7a4SEvan Quan int ret = 0; 147713f5dbd6SEvan Quan 147813f5dbd6SEvan Quan if (!pp_funcs->display_clock_voltage_request) 147913f5dbd6SEvan Quan return -EOPNOTSUPP; 148013f5dbd6SEvan Quan 14813712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14823712e7a4SEvan Quan ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, 148313f5dbd6SEvan Quan clock); 14843712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 14853712e7a4SEvan Quan 14863712e7a4SEvan Quan return ret; 148713f5dbd6SEvan Quan } 148813f5dbd6SEvan Quan 148913f5dbd6SEvan Quan int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, 149013f5dbd6SEvan Quan struct amd_pp_clock_info *clocks) 149113f5dbd6SEvan Quan { 149213f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 14933712e7a4SEvan Quan int ret = 0; 149413f5dbd6SEvan Quan 149513f5dbd6SEvan Quan if (!pp_funcs->get_current_clocks) 149613f5dbd6SEvan Quan return -EOPNOTSUPP; 149713f5dbd6SEvan Quan 14983712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 14993712e7a4SEvan Quan ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle, 150013f5dbd6SEvan Quan clocks); 15013712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15023712e7a4SEvan Quan 15033712e7a4SEvan Quan return ret; 150413f5dbd6SEvan Quan } 150513f5dbd6SEvan Quan 150613f5dbd6SEvan Quan void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) 150713f5dbd6SEvan Quan { 150813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 150913f5dbd6SEvan Quan 151013f5dbd6SEvan Quan if (!pp_funcs->notify_smu_enable_pwe) 151113f5dbd6SEvan Quan return; 151213f5dbd6SEvan Quan 15133712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 151413f5dbd6SEvan Quan pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); 15153712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 151613f5dbd6SEvan Quan } 151713f5dbd6SEvan Quan 151813f5dbd6SEvan Quan int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, 151913f5dbd6SEvan Quan uint32_t count) 152013f5dbd6SEvan Quan { 152113f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15223712e7a4SEvan Quan int ret = 0; 152313f5dbd6SEvan Quan 152413f5dbd6SEvan Quan if (!pp_funcs->set_active_display_count) 152513f5dbd6SEvan Quan return -EOPNOTSUPP; 152613f5dbd6SEvan Quan 15273712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15283712e7a4SEvan Quan ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle, 152913f5dbd6SEvan Quan count); 15303712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15313712e7a4SEvan Quan 15323712e7a4SEvan Quan return ret; 153313f5dbd6SEvan Quan } 153413f5dbd6SEvan Quan 153513f5dbd6SEvan Quan int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, 153613f5dbd6SEvan Quan uint32_t clock) 153713f5dbd6SEvan Quan { 153813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15393712e7a4SEvan Quan int ret = 0; 154013f5dbd6SEvan Quan 154113f5dbd6SEvan Quan if (!pp_funcs->set_min_deep_sleep_dcefclk) 154213f5dbd6SEvan Quan return -EOPNOTSUPP; 154313f5dbd6SEvan Quan 15443712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15453712e7a4SEvan Quan ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, 154613f5dbd6SEvan Quan clock); 15473712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15483712e7a4SEvan Quan 15493712e7a4SEvan Quan return ret; 155013f5dbd6SEvan Quan } 155113f5dbd6SEvan Quan 155213f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, 155313f5dbd6SEvan Quan uint32_t clock) 155413f5dbd6SEvan Quan { 155513f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 155613f5dbd6SEvan Quan 155713f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_dcefclk_by_freq) 155813f5dbd6SEvan Quan return; 155913f5dbd6SEvan Quan 15603712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 156113f5dbd6SEvan Quan pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, 156213f5dbd6SEvan Quan clock); 15633712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 156413f5dbd6SEvan Quan } 156513f5dbd6SEvan Quan 156613f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, 156713f5dbd6SEvan Quan uint32_t clock) 156813f5dbd6SEvan Quan { 156913f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 157013f5dbd6SEvan Quan 157113f5dbd6SEvan Quan if (!pp_funcs->set_hard_min_fclk_by_freq) 157213f5dbd6SEvan Quan return; 157313f5dbd6SEvan Quan 15743712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 157513f5dbd6SEvan Quan pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, 157613f5dbd6SEvan Quan clock); 15773712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 157813f5dbd6SEvan Quan } 157913f5dbd6SEvan Quan 158013f5dbd6SEvan Quan int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, 158113f5dbd6SEvan Quan bool disable_memory_clock_switch) 158213f5dbd6SEvan Quan { 158313f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 15843712e7a4SEvan Quan int ret = 0; 158513f5dbd6SEvan Quan 158613f5dbd6SEvan Quan if (!pp_funcs->display_disable_memory_clock_switch) 158713f5dbd6SEvan Quan return 0; 158813f5dbd6SEvan Quan 15893712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 15903712e7a4SEvan Quan ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, 159113f5dbd6SEvan Quan disable_memory_clock_switch); 15923712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 15933712e7a4SEvan Quan 15943712e7a4SEvan Quan return ret; 159513f5dbd6SEvan Quan } 159613f5dbd6SEvan Quan 159713f5dbd6SEvan Quan int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, 159813f5dbd6SEvan Quan struct pp_smu_nv_clock_table *max_clocks) 159913f5dbd6SEvan Quan { 160013f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16013712e7a4SEvan Quan int ret = 0; 160213f5dbd6SEvan Quan 160313f5dbd6SEvan Quan if (!pp_funcs->get_max_sustainable_clocks_by_dc) 160413f5dbd6SEvan Quan return -EOPNOTSUPP; 160513f5dbd6SEvan Quan 16063712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16073712e7a4SEvan Quan ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, 160813f5dbd6SEvan Quan max_clocks); 16093712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16103712e7a4SEvan Quan 16113712e7a4SEvan Quan return ret; 161213f5dbd6SEvan Quan } 161313f5dbd6SEvan Quan 161413f5dbd6SEvan Quan enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, 161513f5dbd6SEvan Quan unsigned int *clock_values_in_khz, 161613f5dbd6SEvan Quan unsigned int *num_states) 161713f5dbd6SEvan Quan { 161813f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16193712e7a4SEvan Quan int ret = 0; 162013f5dbd6SEvan Quan 162113f5dbd6SEvan Quan if (!pp_funcs->get_uclk_dpm_states) 162213f5dbd6SEvan Quan return -EOPNOTSUPP; 162313f5dbd6SEvan Quan 16243712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16253712e7a4SEvan Quan ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, 162613f5dbd6SEvan Quan clock_values_in_khz, 162713f5dbd6SEvan Quan num_states); 16283712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16293712e7a4SEvan Quan 16303712e7a4SEvan Quan return ret; 163113f5dbd6SEvan Quan } 163213f5dbd6SEvan Quan 163313f5dbd6SEvan Quan int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, 163413f5dbd6SEvan Quan struct dpm_clocks *clock_table) 163513f5dbd6SEvan Quan { 163613f5dbd6SEvan Quan const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 16373712e7a4SEvan Quan int ret = 0; 163813f5dbd6SEvan Quan 163913f5dbd6SEvan Quan if (!pp_funcs->get_dpm_clock_table) 164013f5dbd6SEvan Quan return -EOPNOTSUPP; 164113f5dbd6SEvan Quan 16423712e7a4SEvan Quan mutex_lock(&adev->pm.mutex); 16433712e7a4SEvan Quan ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, 164413f5dbd6SEvan Quan clock_table); 16453712e7a4SEvan Quan mutex_unlock(&adev->pm.mutex); 16463712e7a4SEvan Quan 16473712e7a4SEvan Quan return ret; 164813f5dbd6SEvan Quan } 1649