Path: blob/master/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
51654 views
/*1* Copyright 2015 Advanced Micro Devices, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21*/22#include <linux/types.h>23#include <linux/kernel.h>24#include <linux/gfp.h>25#include <linux/slab.h>26#include <linux/firmware.h>27#include <linux/reboot.h>28#include "amd_shared.h"29#include "power_state.h"30#include "amdgpu.h"31#include "hwmgr.h"32#include "amdgpu_dpm_internal.h"3334static const struct amd_pm_funcs pp_dpm_funcs;3536static int amd_powerplay_create(struct amdgpu_device *adev)37{38struct pp_hwmgr *hwmgr;3940if (adev == NULL)41return -EINVAL;4243hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);44if (hwmgr == NULL)45return -ENOMEM;4647hwmgr->adev = adev;48hwmgr->not_vf = !amdgpu_sriov_vf(adev);49hwmgr->device = amdgpu_cgs_create_device(adev);50if (!hwmgr->device) {51kfree(hwmgr);52return -ENOMEM;53}5455mutex_init(&hwmgr->msg_lock);56hwmgr->chip_family = adev->family;57hwmgr->chip_id = adev->asic_type;58hwmgr->feature_mask = adev->pm.pp_feature;59hwmgr->display_config = &adev->pm.pm_display_cfg;60adev->powerplay.pp_handle = hwmgr;61adev->powerplay.pp_funcs = &pp_dpm_funcs;62return 0;63}646566static void amd_powerplay_destroy(struct amdgpu_device *adev)67{68struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;6970mutex_destroy(&hwmgr->msg_lock);7172kfree(hwmgr->hardcode_pp_table);73hwmgr->hardcode_pp_table = NULL;7475kfree(hwmgr);76hwmgr = NULL;77}7879static int pp_early_init(struct amdgpu_ip_block *ip_block)80{81int ret;82struct amdgpu_device *adev = ip_block->adev;83ret = amd_powerplay_create(adev);8485if (ret != 0)86return ret;8788ret = hwmgr_early_init(adev->powerplay.pp_handle);89if (ret)90return -EINVAL;9192return 0;93}9495static void pp_swctf_delayed_work_handler(struct work_struct *work)96{97struct pp_hwmgr *hwmgr =98container_of(work, struct pp_hwmgr, swctf_delayed_work.work);99struct amdgpu_device *adev = hwmgr->adev;100struct amdgpu_dpm_thermal *range =101&adev->pm.dpm.thermal;102uint32_t gpu_temperature, size = sizeof(gpu_temperature);103int ret;104105/*106* If the hotspot/edge temperature is confirmed as below SW CTF setting point107* after the delay enforced, nothing will be done.108* Otherwise, a graceful shutdown will be performed to prevent further damage.109*/110if (range->sw_ctf_threshold &&111hwmgr->hwmgr_func->read_sensor) {112ret = hwmgr->hwmgr_func->read_sensor(hwmgr,113AMDGPU_PP_SENSOR_HOTSPOT_TEMP,114&gpu_temperature,115&size);116/*117* For some legacy ASICs, hotspot temperature retrieving might be not118* supported. Check the edge temperature instead then.119*/120if (ret == -EOPNOTSUPP)121ret = hwmgr->hwmgr_func->read_sensor(hwmgr,122AMDGPU_PP_SENSOR_EDGE_TEMP,123&gpu_temperature,124&size);125if (!ret && gpu_temperature / 1000 < range->sw_ctf_threshold)126return;127}128129dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");130dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");131orderly_poweroff(true);132}133134static int pp_sw_init(struct amdgpu_ip_block *ip_block)135{136struct amdgpu_device *adev = ip_block->adev;137struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;138int ret = 0;139140ret = hwmgr_sw_init(hwmgr);141142pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");143144if (!ret)145INIT_DELAYED_WORK(&hwmgr->swctf_delayed_work,146pp_swctf_delayed_work_handler);147148return ret;149}150151static int pp_sw_fini(struct amdgpu_ip_block *ip_block)152{153struct amdgpu_device *adev = ip_block->adev;154struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;155156hwmgr_sw_fini(hwmgr);157158amdgpu_ucode_release(&adev->pm.fw);159160return 0;161}162163static int pp_hw_init(struct amdgpu_ip_block *ip_block)164{165int ret = 0;166struct amdgpu_device *adev = ip_block->adev;167struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;168169ret = hwmgr_hw_init(hwmgr);170171if (ret)172pr_err("powerplay hw init failed\n");173174return ret;175}176177static int pp_hw_fini(struct amdgpu_ip_block *ip_block)178{179struct pp_hwmgr *hwmgr = ip_block->adev->powerplay.pp_handle;180181cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);182183hwmgr_hw_fini(hwmgr);184185return 0;186}187188static void pp_reserve_vram_for_smu(struct amdgpu_device *adev)189{190int r = -EINVAL;191void *cpu_ptr = NULL;192uint64_t gpu_addr;193struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;194195if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size,196PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,197&adev->pm.smu_prv_buffer,198&gpu_addr,199&cpu_ptr)) {200drm_err(adev_to_drm(adev), "failed to create smu prv buffer\n");201return;202}203204if (hwmgr->hwmgr_func->notify_cac_buffer_info)205r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr,206lower_32_bits((unsigned long)cpu_ptr),207upper_32_bits((unsigned long)cpu_ptr),208lower_32_bits(gpu_addr),209upper_32_bits(gpu_addr),210adev->pm.smu_prv_buffer_size);211212if (r) {213amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);214adev->pm.smu_prv_buffer = NULL;215drm_err(adev_to_drm(adev), "failed to notify SMU buffer address\n");216}217}218219static int pp_late_init(struct amdgpu_ip_block *ip_block)220{221struct amdgpu_device *adev = ip_block->adev;222struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;223224if (hwmgr && hwmgr->pm_en)225hwmgr_handle_task(hwmgr,226AMD_PP_TASK_COMPLETE_INIT, NULL);227if (adev->pm.smu_prv_buffer_size != 0)228pp_reserve_vram_for_smu(adev);229230return 0;231}232233static void pp_late_fini(struct amdgpu_ip_block *ip_block)234{235struct amdgpu_device *adev = ip_block->adev;236237if (adev->pm.smu_prv_buffer)238amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);239amd_powerplay_destroy(adev);240}241242243static bool pp_is_idle(struct amdgpu_ip_block *ip_block)244{245return false;246}247248static int pp_set_powergating_state(struct amdgpu_ip_block *ip_block,249enum amd_powergating_state state)250{251return 0;252}253254static int pp_suspend(struct amdgpu_ip_block *ip_block)255{256struct amdgpu_device *adev = ip_block->adev;257struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;258259cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);260261return hwmgr_suspend(hwmgr);262}263264static int pp_resume(struct amdgpu_ip_block *ip_block)265{266struct pp_hwmgr *hwmgr = ip_block->adev->powerplay.pp_handle;267268return hwmgr_resume(hwmgr);269}270271static int pp_set_clockgating_state(struct amdgpu_ip_block *ip_block,272enum amd_clockgating_state state)273{274return 0;275}276277static const struct amd_ip_funcs pp_ip_funcs = {278.name = "powerplay",279.early_init = pp_early_init,280.late_init = pp_late_init,281.sw_init = pp_sw_init,282.sw_fini = pp_sw_fini,283.hw_init = pp_hw_init,284.hw_fini = pp_hw_fini,285.late_fini = pp_late_fini,286.suspend = pp_suspend,287.resume = pp_resume,288.is_idle = pp_is_idle,289.set_clockgating_state = pp_set_clockgating_state,290.set_powergating_state = pp_set_powergating_state,291};292293const struct amdgpu_ip_block_version pp_smu_ip_block =294{295.type = AMD_IP_BLOCK_TYPE_SMC,296.major = 1,297.minor = 0,298.rev = 0,299.funcs = &pp_ip_funcs,300};301302/* This interface only be supported On Vi,303* because only smu7/8 can help to load gfx/sdma fw,304* smu need to be enabled before load other ip's fw.305* so call start smu to load smu7 fw and other ip's fw306*/307static int pp_dpm_load_fw(void *handle)308{309struct pp_hwmgr *hwmgr = handle;310311if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu)312return -EINVAL;313314if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {315pr_err("fw load failed\n");316return -EINVAL;317}318319return 0;320}321322static int pp_dpm_fw_loading_complete(void *handle)323{324return 0;325}326327static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)328{329struct pp_hwmgr *hwmgr = handle;330331if (!hwmgr || !hwmgr->pm_en)332return -EINVAL;333334if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {335pr_info_ratelimited("%s was not implemented.\n", __func__);336return 0;337}338339return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);340}341342static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,343enum amd_dpm_forced_level *level)344{345uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |346AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |347AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |348AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;349350if (!(hwmgr->dpm_level & profile_mode_mask)) {351/* enter umd pstate, save current level, disable gfx cg*/352if (*level & profile_mode_mask) {353hwmgr->saved_dpm_level = hwmgr->dpm_level;354hwmgr->en_umd_pstate = true;355}356} else {357/* exit umd pstate, restore level, enable gfx cg*/358if (!(*level & profile_mode_mask)) {359if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)360*level = hwmgr->saved_dpm_level;361hwmgr->en_umd_pstate = false;362}363}364}365366static int pp_dpm_force_performance_level(void *handle,367enum amd_dpm_forced_level level)368{369struct pp_hwmgr *hwmgr = handle;370371if (!hwmgr || !hwmgr->pm_en)372return -EINVAL;373374if (level == hwmgr->dpm_level)375return 0;376377pp_dpm_en_umd_pstate(hwmgr, &level);378hwmgr->request_dpm_level = level;379hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);380381return 0;382}383384static enum amd_dpm_forced_level pp_dpm_get_performance_level(385void *handle)386{387struct pp_hwmgr *hwmgr = handle;388389if (!hwmgr || !hwmgr->pm_en)390return -EINVAL;391392return hwmgr->dpm_level;393}394395static uint32_t pp_dpm_get_sclk(void *handle, bool low)396{397struct pp_hwmgr *hwmgr = handle;398399if (!hwmgr || !hwmgr->pm_en)400return 0;401402if (hwmgr->hwmgr_func->get_sclk == NULL) {403pr_info_ratelimited("%s was not implemented.\n", __func__);404return 0;405}406return hwmgr->hwmgr_func->get_sclk(hwmgr, low);407}408409static uint32_t pp_dpm_get_mclk(void *handle, bool low)410{411struct pp_hwmgr *hwmgr = handle;412413if (!hwmgr || !hwmgr->pm_en)414return 0;415416if (hwmgr->hwmgr_func->get_mclk == NULL) {417pr_info_ratelimited("%s was not implemented.\n", __func__);418return 0;419}420return hwmgr->hwmgr_func->get_mclk(hwmgr, low);421}422423static void pp_dpm_powergate_vce(void *handle, bool gate)424{425struct pp_hwmgr *hwmgr = handle;426427if (!hwmgr || !hwmgr->pm_en)428return;429430if (hwmgr->hwmgr_func->powergate_vce == NULL) {431pr_info_ratelimited("%s was not implemented.\n", __func__);432return;433}434hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);435}436437static void pp_dpm_powergate_uvd(void *handle, bool gate)438{439struct pp_hwmgr *hwmgr = handle;440441if (!hwmgr || !hwmgr->pm_en)442return;443444if (hwmgr->hwmgr_func->powergate_uvd == NULL) {445pr_info_ratelimited("%s was not implemented.\n", __func__);446return;447}448hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);449}450451static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,452enum amd_pm_state_type *user_state)453{454struct pp_hwmgr *hwmgr = handle;455456if (!hwmgr || !hwmgr->pm_en)457return -EINVAL;458459return hwmgr_handle_task(hwmgr, task_id, user_state);460}461462static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)463{464struct pp_hwmgr *hwmgr = handle;465struct pp_power_state *state;466enum amd_pm_state_type pm_type;467468if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)469return -EINVAL;470471state = hwmgr->current_ps;472473switch (state->classification.ui_label) {474case PP_StateUILabel_Battery:475pm_type = POWER_STATE_TYPE_BATTERY;476break;477case PP_StateUILabel_Balanced:478pm_type = POWER_STATE_TYPE_BALANCED;479break;480case PP_StateUILabel_Performance:481pm_type = POWER_STATE_TYPE_PERFORMANCE;482break;483default:484if (state->classification.flags & PP_StateClassificationFlag_Boot)485pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;486else487pm_type = POWER_STATE_TYPE_DEFAULT;488break;489}490491return pm_type;492}493494static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)495{496struct pp_hwmgr *hwmgr = handle;497498if (!hwmgr || !hwmgr->pm_en)499return -EOPNOTSUPP;500501if (hwmgr->hwmgr_func->set_fan_control_mode == NULL)502return -EOPNOTSUPP;503504if (mode == U32_MAX)505return -EINVAL;506507hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);508509return 0;510}511512static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode)513{514struct pp_hwmgr *hwmgr = handle;515516if (!hwmgr || !hwmgr->pm_en)517return -EOPNOTSUPP;518519if (hwmgr->hwmgr_func->get_fan_control_mode == NULL)520return -EOPNOTSUPP;521522if (!fan_mode)523return -EINVAL;524525*fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);526return 0;527}528529static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed)530{531struct pp_hwmgr *hwmgr = handle;532533if (!hwmgr || !hwmgr->pm_en)534return -EOPNOTSUPP;535536if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL)537return -EOPNOTSUPP;538539if (speed == U32_MAX)540return -EINVAL;541542return hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed);543}544545static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed)546{547struct pp_hwmgr *hwmgr = handle;548549if (!hwmgr || !hwmgr->pm_en)550return -EOPNOTSUPP;551552if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL)553return -EOPNOTSUPP;554555if (!speed)556return -EINVAL;557558return hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed);559}560561static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)562{563struct pp_hwmgr *hwmgr = handle;564565if (!hwmgr || !hwmgr->pm_en)566return -EOPNOTSUPP;567568if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)569return -EOPNOTSUPP;570571if (!rpm)572return -EINVAL;573574return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);575}576577static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm)578{579struct pp_hwmgr *hwmgr = handle;580581if (!hwmgr || !hwmgr->pm_en)582return -EOPNOTSUPP;583584if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL)585return -EOPNOTSUPP;586587if (rpm == U32_MAX)588return -EINVAL;589590return hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm);591}592593static int pp_dpm_get_pp_num_states(void *handle,594struct pp_states_info *data)595{596struct pp_hwmgr *hwmgr = handle;597int i;598599memset(data, 0, sizeof(*data));600601if (!hwmgr || !hwmgr->pm_en || !hwmgr->ps)602return -EINVAL;603604data->nums = hwmgr->num_ps;605606for (i = 0; i < hwmgr->num_ps; i++) {607struct pp_power_state *state = (struct pp_power_state *)608((unsigned long)hwmgr->ps + i * hwmgr->ps_size);609switch (state->classification.ui_label) {610case PP_StateUILabel_Battery:611data->states[i] = POWER_STATE_TYPE_BATTERY;612break;613case PP_StateUILabel_Balanced:614data->states[i] = POWER_STATE_TYPE_BALANCED;615break;616case PP_StateUILabel_Performance:617data->states[i] = POWER_STATE_TYPE_PERFORMANCE;618break;619default:620if (state->classification.flags & PP_StateClassificationFlag_Boot)621data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;622else623data->states[i] = POWER_STATE_TYPE_DEFAULT;624}625}626return 0;627}628629static int pp_dpm_get_pp_table(void *handle, char **table)630{631struct pp_hwmgr *hwmgr = handle;632633if (!hwmgr || !hwmgr->pm_en || !table)634return -EINVAL;635636if (!hwmgr->soft_pp_table)637return -EOPNOTSUPP;638639*table = (char *)hwmgr->soft_pp_table;640return hwmgr->soft_pp_table_size;641}642643static int amd_powerplay_reset(void *handle)644{645struct pp_hwmgr *hwmgr = handle;646int ret;647648ret = hwmgr_hw_fini(hwmgr);649if (ret)650return ret;651652ret = hwmgr_hw_init(hwmgr);653if (ret)654return ret;655656return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL);657}658659static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)660{661struct pp_hwmgr *hwmgr = handle;662int ret = -ENOMEM;663664if (!hwmgr || !hwmgr->pm_en)665return -EINVAL;666667if (!hwmgr->hardcode_pp_table) {668hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,669hwmgr->soft_pp_table_size,670GFP_KERNEL);671if (!hwmgr->hardcode_pp_table)672return ret;673}674675memcpy(hwmgr->hardcode_pp_table, buf, size);676677hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;678679ret = amd_powerplay_reset(handle);680if (ret)681return ret;682683if (hwmgr->hwmgr_func->avfs_control)684ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);685686return ret;687}688689static int pp_dpm_force_clock_level(void *handle,690enum pp_clock_type type, uint32_t mask)691{692struct pp_hwmgr *hwmgr = handle;693694if (!hwmgr || !hwmgr->pm_en)695return -EINVAL;696697if (hwmgr->hwmgr_func->force_clock_level == NULL) {698pr_info_ratelimited("%s was not implemented.\n", __func__);699return 0;700}701702if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {703pr_debug("force clock level is for dpm manual mode only.\n");704return -EINVAL;705}706707return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);708}709710static int pp_dpm_emit_clock_levels(void *handle,711enum pp_clock_type type,712char *buf,713int *offset)714{715struct pp_hwmgr *hwmgr = handle;716717if (!hwmgr || !hwmgr->pm_en)718return -EOPNOTSUPP;719720if (!hwmgr->hwmgr_func->emit_clock_levels)721return -ENOENT;722723return hwmgr->hwmgr_func->emit_clock_levels(hwmgr, type, buf, offset);724}725726static int pp_dpm_get_sclk_od(void *handle)727{728struct pp_hwmgr *hwmgr = handle;729730if (!hwmgr || !hwmgr->pm_en)731return -EINVAL;732733if (hwmgr->hwmgr_func->get_sclk_od == NULL) {734pr_info_ratelimited("%s was not implemented.\n", __func__);735return 0;736}737return hwmgr->hwmgr_func->get_sclk_od(hwmgr);738}739740static int pp_dpm_set_sclk_od(void *handle, uint32_t value)741{742struct pp_hwmgr *hwmgr = handle;743744if (!hwmgr || !hwmgr->pm_en)745return -EINVAL;746747if (hwmgr->hwmgr_func->set_sclk_od == NULL) {748pr_info_ratelimited("%s was not implemented.\n", __func__);749return 0;750}751752return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);753}754755static int pp_dpm_get_mclk_od(void *handle)756{757struct pp_hwmgr *hwmgr = handle;758759if (!hwmgr || !hwmgr->pm_en)760return -EINVAL;761762if (hwmgr->hwmgr_func->get_mclk_od == NULL) {763pr_info_ratelimited("%s was not implemented.\n", __func__);764return 0;765}766return hwmgr->hwmgr_func->get_mclk_od(hwmgr);767}768769static int pp_dpm_set_mclk_od(void *handle, uint32_t value)770{771struct pp_hwmgr *hwmgr = handle;772773if (!hwmgr || !hwmgr->pm_en)774return -EINVAL;775776if (hwmgr->hwmgr_func->set_mclk_od == NULL) {777pr_info_ratelimited("%s was not implemented.\n", __func__);778return 0;779}780return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);781}782783static int pp_dpm_read_sensor(void *handle, int idx,784void *value, int *size)785{786struct pp_hwmgr *hwmgr = handle;787788if (!hwmgr || !hwmgr->pm_en || !value)789return -EINVAL;790791switch (idx) {792case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:793*((uint32_t *)value) = hwmgr->pstate_sclk * 100;794return 0;795case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:796*((uint32_t *)value) = hwmgr->pstate_mclk * 100;797return 0;798case AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK:799*((uint32_t *)value) = hwmgr->pstate_sclk_peak * 100;800return 0;801case AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK:802*((uint32_t *)value) = hwmgr->pstate_mclk_peak * 100;803return 0;804case AMDGPU_PP_SENSOR_MIN_FAN_RPM:805*((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM;806return 0;807case AMDGPU_PP_SENSOR_MAX_FAN_RPM:808*((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM;809return 0;810default:811return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);812}813}814815static struct amd_vce_state*816pp_dpm_get_vce_clock_state(void *handle, unsigned idx)817{818struct pp_hwmgr *hwmgr = handle;819820if (!hwmgr || !hwmgr->pm_en)821return NULL;822823if (idx < hwmgr->num_vce_state_tables)824return &hwmgr->vce_states[idx];825return NULL;826}827828static int pp_get_power_profile_mode(void *handle, char *buf)829{830struct pp_hwmgr *hwmgr = handle;831832if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->get_power_profile_mode)833return -EOPNOTSUPP;834if (!buf)835return -EINVAL;836837return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);838}839840static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)841{842struct pp_hwmgr *hwmgr = handle;843844if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->set_power_profile_mode)845return -EOPNOTSUPP;846847if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {848pr_debug("power profile setting is for manual dpm mode only.\n");849return -EINVAL;850}851852return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);853}854855static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size)856{857struct pp_hwmgr *hwmgr = handle;858859if (!hwmgr || !hwmgr->pm_en)860return -EINVAL;861862if (hwmgr->hwmgr_func->set_fine_grain_clk_vol == NULL)863return 0;864865return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size);866}867868static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type,869long *input, uint32_t size)870{871struct pp_hwmgr *hwmgr = handle;872873if (!hwmgr || !hwmgr->pm_en)874return -EINVAL;875876if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {877pr_info_ratelimited("%s was not implemented.\n", __func__);878return 0;879}880881return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);882}883884static int pp_dpm_set_mp1_state(void *handle, enum pp_mp1_state mp1_state)885{886struct pp_hwmgr *hwmgr = handle;887888if (!hwmgr)889return -EINVAL;890891if (!hwmgr->pm_en)892return 0;893894if (hwmgr->hwmgr_func->set_mp1_state)895return hwmgr->hwmgr_func->set_mp1_state(hwmgr, mp1_state);896897return 0;898}899900static int pp_dpm_switch_power_profile(void *handle,901enum PP_SMC_POWER_PROFILE type, bool en)902{903struct pp_hwmgr *hwmgr = handle;904long workload[1];905uint32_t index;906907if (!hwmgr || !hwmgr->pm_en)908return -EINVAL;909910if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {911pr_info_ratelimited("%s was not implemented.\n", __func__);912return -EINVAL;913}914915if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))916return -EINVAL;917918if (!en) {919hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);920index = fls(hwmgr->workload_mask);921index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;922workload[0] = hwmgr->workload_setting[index];923} else {924hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);925index = fls(hwmgr->workload_mask);926index = index <= Workload_Policy_Max ? index - 1 : 0;927workload[0] = hwmgr->workload_setting[index];928}929930if (type == PP_SMC_POWER_PROFILE_COMPUTE &&931hwmgr->hwmgr_func->disable_power_features_for_compute_performance) {932if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en))933return -EINVAL;934}935936if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)937hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);938939return 0;940}941942static int pp_set_power_limit(void *handle, uint32_t limit_type, uint32_t limit)943{944struct pp_hwmgr *hwmgr = handle;945uint32_t max_power_limit;946947if (!hwmgr || !hwmgr->pm_en)948return -EINVAL;949950if (hwmgr->hwmgr_func->set_power_limit == NULL) {951pr_info_ratelimited("%s was not implemented.\n", __func__);952return -EINVAL;953}954955if (limit == 0)956limit = hwmgr->default_power_limit;957958max_power_limit = hwmgr->default_power_limit;959if (hwmgr->od_enabled) {960max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);961max_power_limit /= 100;962}963964if (limit > max_power_limit)965return -EINVAL;966967hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);968hwmgr->power_limit = limit;969return 0;970}971972static int pp_get_power_limit(void *handle, uint32_t *limit,973enum pp_power_limit_level pp_limit_level,974enum pp_power_type power_type)975{976struct pp_hwmgr *hwmgr = handle;977int ret = 0;978979if (!hwmgr || !hwmgr->pm_en || !limit)980return -EINVAL;981982if (power_type != PP_PWR_TYPE_SUSTAINED)983return -EOPNOTSUPP;984985switch (pp_limit_level) {986case PP_PWR_LIMIT_CURRENT:987*limit = hwmgr->power_limit;988break;989case PP_PWR_LIMIT_DEFAULT:990*limit = hwmgr->default_power_limit;991break;992case PP_PWR_LIMIT_MAX:993*limit = hwmgr->default_power_limit;994if (hwmgr->od_enabled) {995*limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);996*limit /= 100;997}998break;999case PP_PWR_LIMIT_MIN:1000*limit = 0;1001break;1002default:1003ret = -EOPNOTSUPP;1004break;1005}10061007return ret;1008}10091010static int pp_display_configuration_change(void *handle,1011const struct amd_pp_display_configuration *display_config)1012{1013struct pp_hwmgr *hwmgr = handle;10141015if (!hwmgr || !hwmgr->pm_en)1016return -EINVAL;10171018phm_store_dal_configuration_data(hwmgr, display_config);1019return 0;1020}10211022static int pp_get_display_power_level(void *handle,1023struct amd_pp_simple_clock_info *output)1024{1025struct pp_hwmgr *hwmgr = handle;10261027if (!hwmgr || !hwmgr->pm_en || !output)1028return -EINVAL;10291030return phm_get_dal_power_level(hwmgr, output);1031}10321033static int pp_get_current_clocks(void *handle,1034struct amd_pp_clock_info *clocks)1035{1036struct amd_pp_simple_clock_info simple_clocks = { 0 };1037struct pp_clock_info hw_clocks;1038struct pp_hwmgr *hwmgr = handle;1039int ret = 0;10401041if (!hwmgr || !hwmgr->pm_en)1042return -EINVAL;10431044phm_get_dal_power_level(hwmgr, &simple_clocks);10451046if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,1047PHM_PlatformCaps_PowerContainment))1048ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,1049&hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);1050else1051ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,1052&hw_clocks, PHM_PerformanceLevelDesignation_Activity);10531054if (ret) {1055drm_err(adev_to_drm(hwmgr->adev),1056"Error in phm_get_clock_info\n");1057return -EINVAL;1058}10591060clocks->min_engine_clock = hw_clocks.min_eng_clk;1061clocks->max_engine_clock = hw_clocks.max_eng_clk;1062clocks->min_memory_clock = hw_clocks.min_mem_clk;1063clocks->max_memory_clock = hw_clocks.max_mem_clk;1064clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;1065clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;10661067clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;1068clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;10691070if (simple_clocks.level == 0)1071clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;1072else1073clocks->max_clocks_state = simple_clocks.level;10741075if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {1076clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;1077clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;1078}1079return 0;1080}10811082static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)1083{1084struct pp_hwmgr *hwmgr = handle;10851086if (!hwmgr || !hwmgr->pm_en)1087return -EINVAL;10881089if (clocks == NULL)1090return -EINVAL;10911092return phm_get_clock_by_type(hwmgr, type, clocks);1093}10941095static int pp_get_clock_by_type_with_latency(void *handle,1096enum amd_pp_clock_type type,1097struct pp_clock_levels_with_latency *clocks)1098{1099struct pp_hwmgr *hwmgr = handle;11001101if (!hwmgr || !hwmgr->pm_en || !clocks)1102return -EINVAL;11031104return phm_get_clock_by_type_with_latency(hwmgr, type, clocks);1105}11061107static int pp_get_clock_by_type_with_voltage(void *handle,1108enum amd_pp_clock_type type,1109struct pp_clock_levels_with_voltage *clocks)1110{1111struct pp_hwmgr *hwmgr = handle;11121113if (!hwmgr || !hwmgr->pm_en || !clocks)1114return -EINVAL;11151116return phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);1117}11181119static int pp_set_watermarks_for_clocks_ranges(void *handle,1120void *clock_ranges)1121{1122struct pp_hwmgr *hwmgr = handle;11231124if (!hwmgr || !hwmgr->pm_en || !clock_ranges)1125return -EINVAL;11261127return phm_set_watermarks_for_clocks_ranges(hwmgr,1128clock_ranges);1129}11301131static int pp_display_clock_voltage_request(void *handle,1132struct pp_display_clock_request *clock)1133{1134struct pp_hwmgr *hwmgr = handle;11351136if (!hwmgr || !hwmgr->pm_en || !clock)1137return -EINVAL;11381139return phm_display_clock_voltage_request(hwmgr, clock);1140}11411142static int pp_get_display_mode_validation_clocks(void *handle,1143struct amd_pp_simple_clock_info *clocks)1144{1145struct pp_hwmgr *hwmgr = handle;1146int ret = 0;11471148if (!hwmgr || !hwmgr->pm_en || !clocks)1149return -EINVAL;11501151clocks->level = PP_DAL_POWERLEVEL_7;11521153if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))1154ret = phm_get_max_high_clocks(hwmgr, clocks);11551156return ret;1157}11581159static int pp_dpm_powergate_mmhub(void *handle)1160{1161struct pp_hwmgr *hwmgr = handle;11621163if (!hwmgr || !hwmgr->pm_en)1164return -EINVAL;11651166if (hwmgr->hwmgr_func->powergate_mmhub == NULL) {1167pr_info_ratelimited("%s was not implemented.\n", __func__);1168return 0;1169}11701171return hwmgr->hwmgr_func->powergate_mmhub(hwmgr);1172}11731174static int pp_dpm_powergate_gfx(void *handle, bool gate)1175{1176struct pp_hwmgr *hwmgr = handle;11771178if (!hwmgr || !hwmgr->pm_en)1179return 0;11801181if (hwmgr->hwmgr_func->powergate_gfx == NULL) {1182pr_info_ratelimited("%s was not implemented.\n", __func__);1183return 0;1184}11851186return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate);1187}11881189static void pp_dpm_powergate_acp(void *handle, bool gate)1190{1191struct pp_hwmgr *hwmgr = handle;11921193if (!hwmgr || !hwmgr->pm_en)1194return;11951196if (hwmgr->hwmgr_func->powergate_acp == NULL) {1197pr_info_ratelimited("%s was not implemented.\n", __func__);1198return;1199}12001201hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);1202}12031204static void pp_dpm_powergate_sdma(void *handle, bool gate)1205{1206struct pp_hwmgr *hwmgr = handle;12071208if (!hwmgr)1209return;12101211if (hwmgr->hwmgr_func->powergate_sdma == NULL) {1212pr_info_ratelimited("%s was not implemented.\n", __func__);1213return;1214}12151216hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);1217}12181219static int pp_set_powergating_by_smu(void *handle,1220uint32_t block_type,1221bool gate,1222int inst)1223{1224int ret = 0;12251226switch (block_type) {1227case AMD_IP_BLOCK_TYPE_UVD:1228case AMD_IP_BLOCK_TYPE_VCN:1229pp_dpm_powergate_uvd(handle, gate);1230break;1231case AMD_IP_BLOCK_TYPE_VCE:1232pp_dpm_powergate_vce(handle, gate);1233break;1234case AMD_IP_BLOCK_TYPE_GMC:1235/*1236* For now, this is only used on PICASSO.1237* And only "gate" operation is supported.1238*/1239if (gate)1240pp_dpm_powergate_mmhub(handle);1241break;1242case AMD_IP_BLOCK_TYPE_GFX:1243ret = pp_dpm_powergate_gfx(handle, gate);1244break;1245case AMD_IP_BLOCK_TYPE_ACP:1246pp_dpm_powergate_acp(handle, gate);1247break;1248case AMD_IP_BLOCK_TYPE_SDMA:1249pp_dpm_powergate_sdma(handle, gate);1250break;1251default:1252break;1253}1254return ret;1255}12561257static int pp_notify_smu_enable_pwe(void *handle)1258{1259struct pp_hwmgr *hwmgr = handle;12601261if (!hwmgr || !hwmgr->pm_en)1262return -EINVAL;12631264if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) {1265pr_info_ratelimited("%s was not implemented.\n", __func__);1266return -EINVAL;1267}12681269hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);12701271return 0;1272}12731274static int pp_enable_mgpu_fan_boost(void *handle)1275{1276struct pp_hwmgr *hwmgr = handle;12771278if (!hwmgr)1279return -EINVAL;12801281if (!hwmgr->pm_en ||1282hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL)1283return 0;12841285hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);12861287return 0;1288}12891290static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock)1291{1292struct pp_hwmgr *hwmgr = handle;12931294if (!hwmgr || !hwmgr->pm_en)1295return -EINVAL;12961297if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) {1298pr_debug("%s was not implemented.\n", __func__);1299return -EINVAL;1300}13011302hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock);13031304return 0;1305}13061307static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock)1308{1309struct pp_hwmgr *hwmgr = handle;13101311if (!hwmgr || !hwmgr->pm_en)1312return -EINVAL;13131314if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) {1315pr_debug("%s was not implemented.\n", __func__);1316return -EINVAL;1317}13181319hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock);13201321return 0;1322}13231324static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock)1325{1326struct pp_hwmgr *hwmgr = handle;13271328if (!hwmgr || !hwmgr->pm_en)1329return -EINVAL;13301331if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) {1332pr_debug("%s was not implemented.\n", __func__);1333return -EINVAL;1334}13351336hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock);13371338return 0;1339}13401341static int pp_set_active_display_count(void *handle, uint32_t count)1342{1343struct pp_hwmgr *hwmgr = handle;13441345if (!hwmgr || !hwmgr->pm_en)1346return -EINVAL;13471348return phm_set_active_display_count(hwmgr, count);1349}13501351static int pp_get_asic_baco_capability(void *handle)1352{1353struct pp_hwmgr *hwmgr = handle;13541355if (!hwmgr)1356return false;13571358if (!(hwmgr->not_vf && amdgpu_dpm) ||1359!hwmgr->hwmgr_func->get_bamaco_support)1360return false;13611362return hwmgr->hwmgr_func->get_bamaco_support(hwmgr);1363}13641365static int pp_get_asic_baco_state(void *handle, int *state)1366{1367struct pp_hwmgr *hwmgr = handle;13681369if (!hwmgr)1370return -EINVAL;13711372if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)1373return 0;13741375hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state);13761377return 0;1378}13791380static int pp_set_asic_baco_state(void *handle, int state)1381{1382struct pp_hwmgr *hwmgr = handle;13831384if (!hwmgr)1385return -EINVAL;13861387if (!(hwmgr->not_vf && amdgpu_dpm) ||1388!hwmgr->hwmgr_func->set_asic_baco_state)1389return 0;13901391hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state);13921393return 0;1394}13951396static int pp_get_ppfeature_status(void *handle, char *buf)1397{1398struct pp_hwmgr *hwmgr = handle;13991400if (!hwmgr || !hwmgr->pm_en || !buf)1401return -EINVAL;14021403if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {1404pr_info_ratelimited("%s was not implemented.\n", __func__);1405return -EINVAL;1406}14071408return hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);1409}14101411static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)1412{1413struct pp_hwmgr *hwmgr = handle;14141415if (!hwmgr || !hwmgr->pm_en)1416return -EINVAL;14171418if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {1419pr_info_ratelimited("%s was not implemented.\n", __func__);1420return -EINVAL;1421}14221423return hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);1424}14251426static int pp_asic_reset_mode_2(void *handle)1427{1428struct pp_hwmgr *hwmgr = handle;14291430if (!hwmgr || !hwmgr->pm_en)1431return -EINVAL;14321433if (hwmgr->hwmgr_func->asic_reset == NULL) {1434pr_info_ratelimited("%s was not implemented.\n", __func__);1435return -EINVAL;1436}14371438return hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2);1439}14401441static int pp_smu_i2c_bus_access(void *handle, bool acquire)1442{1443struct pp_hwmgr *hwmgr = handle;14441445if (!hwmgr || !hwmgr->pm_en)1446return -EINVAL;14471448if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) {1449pr_info_ratelimited("%s was not implemented.\n", __func__);1450return -EINVAL;1451}14521453return hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire);1454}14551456static int pp_set_df_cstate(void *handle, enum pp_df_cstate state)1457{1458struct pp_hwmgr *hwmgr = handle;14591460if (!hwmgr)1461return -EINVAL;14621463if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate)1464return 0;14651466hwmgr->hwmgr_func->set_df_cstate(hwmgr, state);14671468return 0;1469}14701471static int pp_set_xgmi_pstate(void *handle, uint32_t pstate)1472{1473struct pp_hwmgr *hwmgr = handle;14741475if (!hwmgr)1476return -EINVAL;14771478if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate)1479return 0;14801481hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate);14821483return 0;1484}14851486static ssize_t pp_get_gpu_metrics(void *handle, void **table)1487{1488struct pp_hwmgr *hwmgr = handle;14891490if (!hwmgr)1491return -EINVAL;14921493if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics)1494return -EOPNOTSUPP;14951496return hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table);1497}14981499static int pp_gfx_state_change_set(void *handle, uint32_t state)1500{1501struct pp_hwmgr *hwmgr = handle;15021503if (!hwmgr || !hwmgr->pm_en)1504return -EINVAL;15051506if (hwmgr->hwmgr_func->gfx_state_change == NULL) {1507pr_info_ratelimited("%s was not implemented.\n", __func__);1508return -EINVAL;1509}15101511hwmgr->hwmgr_func->gfx_state_change(hwmgr, state);1512return 0;1513}15141515static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size)1516{1517struct pp_hwmgr *hwmgr = handle;1518struct amdgpu_device *adev = hwmgr->adev;1519int err;15201521if (!addr || !size)1522return -EINVAL;15231524*addr = NULL;1525*size = 0;1526if (adev->pm.smu_prv_buffer) {1527err = amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr);1528if (err)1529return err;1530*size = adev->pm.smu_prv_buffer_size;1531}15321533return 0;1534}15351536static void pp_pm_compute_clocks(void *handle)1537{1538struct pp_hwmgr *hwmgr = handle;1539struct amdgpu_device *adev = hwmgr->adev;15401541if (!adev->dc_enabled) {1542amdgpu_dpm_get_display_cfg(adev);1543pp_display_configuration_change(handle,1544&adev->pm.pm_display_cfg);1545}15461547pp_dpm_dispatch_tasks(handle,1548AMD_PP_TASK_DISPLAY_CONFIG_CHANGE,1549NULL);1550}15511552static const struct amd_pm_funcs pp_dpm_funcs = {1553.load_firmware = pp_dpm_load_fw,1554.wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,1555.force_performance_level = pp_dpm_force_performance_level,1556.get_performance_level = pp_dpm_get_performance_level,1557.get_current_power_state = pp_dpm_get_current_power_state,1558.dispatch_tasks = pp_dpm_dispatch_tasks,1559.set_fan_control_mode = pp_dpm_set_fan_control_mode,1560.get_fan_control_mode = pp_dpm_get_fan_control_mode,1561.set_fan_speed_pwm = pp_dpm_set_fan_speed_pwm,1562.get_fan_speed_pwm = pp_dpm_get_fan_speed_pwm,1563.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,1564.set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,1565.get_pp_num_states = pp_dpm_get_pp_num_states,1566.get_pp_table = pp_dpm_get_pp_table,1567.set_pp_table = pp_dpm_set_pp_table,1568.force_clock_level = pp_dpm_force_clock_level,1569.emit_clock_levels = pp_dpm_emit_clock_levels,1570.get_sclk_od = pp_dpm_get_sclk_od,1571.set_sclk_od = pp_dpm_set_sclk_od,1572.get_mclk_od = pp_dpm_get_mclk_od,1573.set_mclk_od = pp_dpm_set_mclk_od,1574.read_sensor = pp_dpm_read_sensor,1575.get_vce_clock_state = pp_dpm_get_vce_clock_state,1576.switch_power_profile = pp_dpm_switch_power_profile,1577.set_clockgating_by_smu = pp_set_clockgating_by_smu,1578.set_powergating_by_smu = pp_set_powergating_by_smu,1579.get_power_profile_mode = pp_get_power_profile_mode,1580.set_power_profile_mode = pp_set_power_profile_mode,1581.set_fine_grain_clk_vol = pp_set_fine_grain_clk_vol,1582.odn_edit_dpm_table = pp_odn_edit_dpm_table,1583.set_mp1_state = pp_dpm_set_mp1_state,1584.set_power_limit = pp_set_power_limit,1585.get_power_limit = pp_get_power_limit,1586/* export to DC */1587.get_sclk = pp_dpm_get_sclk,1588.get_mclk = pp_dpm_get_mclk,1589.display_configuration_change = pp_display_configuration_change,1590.get_display_power_level = pp_get_display_power_level,1591.get_current_clocks = pp_get_current_clocks,1592.get_clock_by_type = pp_get_clock_by_type,1593.get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,1594.get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,1595.set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,1596.display_clock_voltage_request = pp_display_clock_voltage_request,1597.get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,1598.notify_smu_enable_pwe = pp_notify_smu_enable_pwe,1599.enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,1600.set_active_display_count = pp_set_active_display_count,1601.set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk,1602.set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq,1603.set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq,1604.get_asic_baco_capability = pp_get_asic_baco_capability,1605.get_asic_baco_state = pp_get_asic_baco_state,1606.set_asic_baco_state = pp_set_asic_baco_state,1607.get_ppfeature_status = pp_get_ppfeature_status,1608.set_ppfeature_status = pp_set_ppfeature_status,1609.asic_reset_mode_2 = pp_asic_reset_mode_2,1610.smu_i2c_bus_access = pp_smu_i2c_bus_access,1611.set_df_cstate = pp_set_df_cstate,1612.set_xgmi_pstate = pp_set_xgmi_pstate,1613.get_gpu_metrics = pp_get_gpu_metrics,1614.gfx_state_change_set = pp_gfx_state_change_set,1615.get_smu_prv_buf_details = pp_get_prv_buffer_details,1616.pm_compute_clocks = pp_pm_compute_clocks,1617};161816191620