Path: blob/master/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
26535 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 "pp_debug.h"23#include <linux/types.h>24#include <linux/kernel.h>25#include <linux/gfp.h>26#include <linux/slab.h>27#include <linux/firmware.h>28#include <linux/reboot.h>29#include "amd_shared.h"30#include "amd_powerplay.h"31#include "power_state.h"32#include "amdgpu.h"33#include "hwmgr.h"34#include "amdgpu_dpm_internal.h"35#include "amdgpu_display.h"3637static const struct amd_pm_funcs pp_dpm_funcs;3839static int amd_powerplay_create(struct amdgpu_device *adev)40{41struct pp_hwmgr *hwmgr;4243if (adev == NULL)44return -EINVAL;4546hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);47if (hwmgr == NULL)48return -ENOMEM;4950hwmgr->adev = adev;51hwmgr->not_vf = !amdgpu_sriov_vf(adev);52hwmgr->device = amdgpu_cgs_create_device(adev);53if (!hwmgr->device) {54kfree(hwmgr);55return -ENOMEM;56}5758mutex_init(&hwmgr->msg_lock);59hwmgr->chip_family = adev->family;60hwmgr->chip_id = adev->asic_type;61hwmgr->feature_mask = adev->pm.pp_feature;62hwmgr->display_config = &adev->pm.pm_display_cfg;63adev->powerplay.pp_handle = hwmgr;64adev->powerplay.pp_funcs = &pp_dpm_funcs;65return 0;66}676869static void amd_powerplay_destroy(struct amdgpu_device *adev)70{71struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;7273mutex_destroy(&hwmgr->msg_lock);7475kfree(hwmgr->hardcode_pp_table);76hwmgr->hardcode_pp_table = NULL;7778kfree(hwmgr);79hwmgr = NULL;80}8182static int pp_early_init(struct amdgpu_ip_block *ip_block)83{84int ret;85struct amdgpu_device *adev = ip_block->adev;86ret = amd_powerplay_create(adev);8788if (ret != 0)89return ret;9091ret = hwmgr_early_init(adev->powerplay.pp_handle);92if (ret)93return -EINVAL;9495return 0;96}9798static void pp_swctf_delayed_work_handler(struct work_struct *work)99{100struct pp_hwmgr *hwmgr =101container_of(work, struct pp_hwmgr, swctf_delayed_work.work);102struct amdgpu_device *adev = hwmgr->adev;103struct amdgpu_dpm_thermal *range =104&adev->pm.dpm.thermal;105uint32_t gpu_temperature, size = sizeof(gpu_temperature);106int ret;107108/*109* If the hotspot/edge temperature is confirmed as below SW CTF setting point110* after the delay enforced, nothing will be done.111* Otherwise, a graceful shutdown will be performed to prevent further damage.112*/113if (range->sw_ctf_threshold &&114hwmgr->hwmgr_func->read_sensor) {115ret = hwmgr->hwmgr_func->read_sensor(hwmgr,116AMDGPU_PP_SENSOR_HOTSPOT_TEMP,117&gpu_temperature,118&size);119/*120* For some legacy ASICs, hotspot temperature retrieving might be not121* supported. Check the edge temperature instead then.122*/123if (ret == -EOPNOTSUPP)124ret = hwmgr->hwmgr_func->read_sensor(hwmgr,125AMDGPU_PP_SENSOR_EDGE_TEMP,126&gpu_temperature,127&size);128if (!ret && gpu_temperature / 1000 < range->sw_ctf_threshold)129return;130}131132dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");133dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");134orderly_poweroff(true);135}136137static int pp_sw_init(struct amdgpu_ip_block *ip_block)138{139struct amdgpu_device *adev = ip_block->adev;140struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;141int ret = 0;142143ret = hwmgr_sw_init(hwmgr);144145pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");146147if (!ret)148INIT_DELAYED_WORK(&hwmgr->swctf_delayed_work,149pp_swctf_delayed_work_handler);150151return ret;152}153154static int pp_sw_fini(struct amdgpu_ip_block *ip_block)155{156struct amdgpu_device *adev = ip_block->adev;157struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;158159hwmgr_sw_fini(hwmgr);160161amdgpu_ucode_release(&adev->pm.fw);162163return 0;164}165166static int pp_hw_init(struct amdgpu_ip_block *ip_block)167{168int ret = 0;169struct amdgpu_device *adev = ip_block->adev;170struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;171172ret = hwmgr_hw_init(hwmgr);173174if (ret)175pr_err("powerplay hw init failed\n");176177return ret;178}179180static int pp_hw_fini(struct amdgpu_ip_block *ip_block)181{182struct pp_hwmgr *hwmgr = ip_block->adev->powerplay.pp_handle;183184cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);185186hwmgr_hw_fini(hwmgr);187188return 0;189}190191static void pp_reserve_vram_for_smu(struct amdgpu_device *adev)192{193int r = -EINVAL;194void *cpu_ptr = NULL;195uint64_t gpu_addr;196struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;197198if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size,199PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,200&adev->pm.smu_prv_buffer,201&gpu_addr,202&cpu_ptr)) {203DRM_ERROR("amdgpu: failed to create smu prv buffer\n");204return;205}206207if (hwmgr->hwmgr_func->notify_cac_buffer_info)208r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr,209lower_32_bits((unsigned long)cpu_ptr),210upper_32_bits((unsigned long)cpu_ptr),211lower_32_bits(gpu_addr),212upper_32_bits(gpu_addr),213adev->pm.smu_prv_buffer_size);214215if (r) {216amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);217adev->pm.smu_prv_buffer = NULL;218DRM_ERROR("amdgpu: failed to notify SMU buffer address\n");219}220}221222static int pp_late_init(struct amdgpu_ip_block *ip_block)223{224struct amdgpu_device *adev = ip_block->adev;225struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;226227if (hwmgr && hwmgr->pm_en)228hwmgr_handle_task(hwmgr,229AMD_PP_TASK_COMPLETE_INIT, NULL);230if (adev->pm.smu_prv_buffer_size != 0)231pp_reserve_vram_for_smu(adev);232233return 0;234}235236static void pp_late_fini(struct amdgpu_ip_block *ip_block)237{238struct amdgpu_device *adev = ip_block->adev;239240if (adev->pm.smu_prv_buffer)241amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);242amd_powerplay_destroy(adev);243}244245246static bool pp_is_idle(struct amdgpu_ip_block *ip_block)247{248return false;249}250251static int pp_set_powergating_state(struct amdgpu_ip_block *ip_block,252enum amd_powergating_state state)253{254return 0;255}256257static int pp_suspend(struct amdgpu_ip_block *ip_block)258{259struct amdgpu_device *adev = ip_block->adev;260struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;261262cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);263264return hwmgr_suspend(hwmgr);265}266267static int pp_resume(struct amdgpu_ip_block *ip_block)268{269struct pp_hwmgr *hwmgr = ip_block->adev->powerplay.pp_handle;270271return hwmgr_resume(hwmgr);272}273274static int pp_set_clockgating_state(struct amdgpu_ip_block *ip_block,275enum amd_clockgating_state state)276{277return 0;278}279280static const struct amd_ip_funcs pp_ip_funcs = {281.name = "powerplay",282.early_init = pp_early_init,283.late_init = pp_late_init,284.sw_init = pp_sw_init,285.sw_fini = pp_sw_fini,286.hw_init = pp_hw_init,287.hw_fini = pp_hw_fini,288.late_fini = pp_late_fini,289.suspend = pp_suspend,290.resume = pp_resume,291.is_idle = pp_is_idle,292.set_clockgating_state = pp_set_clockgating_state,293.set_powergating_state = pp_set_powergating_state,294};295296const struct amdgpu_ip_block_version pp_smu_ip_block =297{298.type = AMD_IP_BLOCK_TYPE_SMC,299.major = 1,300.minor = 0,301.rev = 0,302.funcs = &pp_ip_funcs,303};304305/* This interface only be supported On Vi,306* because only smu7/8 can help to load gfx/sdma fw,307* smu need to be enabled before load other ip's fw.308* so call start smu to load smu7 fw and other ip's fw309*/310static int pp_dpm_load_fw(void *handle)311{312struct pp_hwmgr *hwmgr = handle;313314if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu)315return -EINVAL;316317if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {318pr_err("fw load failed\n");319return -EINVAL;320}321322return 0;323}324325static int pp_dpm_fw_loading_complete(void *handle)326{327return 0;328}329330static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)331{332struct pp_hwmgr *hwmgr = handle;333334if (!hwmgr || !hwmgr->pm_en)335return -EINVAL;336337if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {338pr_info_ratelimited("%s was not implemented.\n", __func__);339return 0;340}341342return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);343}344345static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,346enum amd_dpm_forced_level *level)347{348uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |349AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |350AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |351AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;352353if (!(hwmgr->dpm_level & profile_mode_mask)) {354/* enter umd pstate, save current level, disable gfx cg*/355if (*level & profile_mode_mask) {356hwmgr->saved_dpm_level = hwmgr->dpm_level;357hwmgr->en_umd_pstate = true;358}359} else {360/* exit umd pstate, restore level, enable gfx cg*/361if (!(*level & profile_mode_mask)) {362if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)363*level = hwmgr->saved_dpm_level;364hwmgr->en_umd_pstate = false;365}366}367}368369static int pp_dpm_force_performance_level(void *handle,370enum amd_dpm_forced_level level)371{372struct pp_hwmgr *hwmgr = handle;373374if (!hwmgr || !hwmgr->pm_en)375return -EINVAL;376377if (level == hwmgr->dpm_level)378return 0;379380pp_dpm_en_umd_pstate(hwmgr, &level);381hwmgr->request_dpm_level = level;382hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);383384return 0;385}386387static enum amd_dpm_forced_level pp_dpm_get_performance_level(388void *handle)389{390struct pp_hwmgr *hwmgr = handle;391392if (!hwmgr || !hwmgr->pm_en)393return -EINVAL;394395return hwmgr->dpm_level;396}397398static uint32_t pp_dpm_get_sclk(void *handle, bool low)399{400struct pp_hwmgr *hwmgr = handle;401402if (!hwmgr || !hwmgr->pm_en)403return 0;404405if (hwmgr->hwmgr_func->get_sclk == NULL) {406pr_info_ratelimited("%s was not implemented.\n", __func__);407return 0;408}409return hwmgr->hwmgr_func->get_sclk(hwmgr, low);410}411412static uint32_t pp_dpm_get_mclk(void *handle, bool low)413{414struct pp_hwmgr *hwmgr = handle;415416if (!hwmgr || !hwmgr->pm_en)417return 0;418419if (hwmgr->hwmgr_func->get_mclk == NULL) {420pr_info_ratelimited("%s was not implemented.\n", __func__);421return 0;422}423return hwmgr->hwmgr_func->get_mclk(hwmgr, low);424}425426static void pp_dpm_powergate_vce(void *handle, bool gate)427{428struct pp_hwmgr *hwmgr = handle;429430if (!hwmgr || !hwmgr->pm_en)431return;432433if (hwmgr->hwmgr_func->powergate_vce == NULL) {434pr_info_ratelimited("%s was not implemented.\n", __func__);435return;436}437hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);438}439440static void pp_dpm_powergate_uvd(void *handle, bool gate)441{442struct pp_hwmgr *hwmgr = handle;443444if (!hwmgr || !hwmgr->pm_en)445return;446447if (hwmgr->hwmgr_func->powergate_uvd == NULL) {448pr_info_ratelimited("%s was not implemented.\n", __func__);449return;450}451hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);452}453454static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,455enum amd_pm_state_type *user_state)456{457struct pp_hwmgr *hwmgr = handle;458459if (!hwmgr || !hwmgr->pm_en)460return -EINVAL;461462return hwmgr_handle_task(hwmgr, task_id, user_state);463}464465static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)466{467struct pp_hwmgr *hwmgr = handle;468struct pp_power_state *state;469enum amd_pm_state_type pm_type;470471if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)472return -EINVAL;473474state = hwmgr->current_ps;475476switch (state->classification.ui_label) {477case PP_StateUILabel_Battery:478pm_type = POWER_STATE_TYPE_BATTERY;479break;480case PP_StateUILabel_Balanced:481pm_type = POWER_STATE_TYPE_BALANCED;482break;483case PP_StateUILabel_Performance:484pm_type = POWER_STATE_TYPE_PERFORMANCE;485break;486default:487if (state->classification.flags & PP_StateClassificationFlag_Boot)488pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;489else490pm_type = POWER_STATE_TYPE_DEFAULT;491break;492}493494return pm_type;495}496497static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)498{499struct pp_hwmgr *hwmgr = handle;500501if (!hwmgr || !hwmgr->pm_en)502return -EOPNOTSUPP;503504if (hwmgr->hwmgr_func->set_fan_control_mode == NULL)505return -EOPNOTSUPP;506507if (mode == U32_MAX)508return -EINVAL;509510hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);511512return 0;513}514515static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode)516{517struct pp_hwmgr *hwmgr = handle;518519if (!hwmgr || !hwmgr->pm_en)520return -EOPNOTSUPP;521522if (hwmgr->hwmgr_func->get_fan_control_mode == NULL)523return -EOPNOTSUPP;524525if (!fan_mode)526return -EINVAL;527528*fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);529return 0;530}531532static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed)533{534struct pp_hwmgr *hwmgr = handle;535536if (!hwmgr || !hwmgr->pm_en)537return -EOPNOTSUPP;538539if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL)540return -EOPNOTSUPP;541542if (speed == U32_MAX)543return -EINVAL;544545return hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed);546}547548static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed)549{550struct pp_hwmgr *hwmgr = handle;551552if (!hwmgr || !hwmgr->pm_en)553return -EOPNOTSUPP;554555if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL)556return -EOPNOTSUPP;557558if (!speed)559return -EINVAL;560561return hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed);562}563564static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)565{566struct pp_hwmgr *hwmgr = handle;567568if (!hwmgr || !hwmgr->pm_en)569return -EOPNOTSUPP;570571if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)572return -EOPNOTSUPP;573574if (!rpm)575return -EINVAL;576577return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);578}579580static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm)581{582struct pp_hwmgr *hwmgr = handle;583584if (!hwmgr || !hwmgr->pm_en)585return -EOPNOTSUPP;586587if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL)588return -EOPNOTSUPP;589590if (rpm == U32_MAX)591return -EINVAL;592593return hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm);594}595596static int pp_dpm_get_pp_num_states(void *handle,597struct pp_states_info *data)598{599struct pp_hwmgr *hwmgr = handle;600int i;601602memset(data, 0, sizeof(*data));603604if (!hwmgr || !hwmgr->pm_en || !hwmgr->ps)605return -EINVAL;606607data->nums = hwmgr->num_ps;608609for (i = 0; i < hwmgr->num_ps; i++) {610struct pp_power_state *state = (struct pp_power_state *)611((unsigned long)hwmgr->ps + i * hwmgr->ps_size);612switch (state->classification.ui_label) {613case PP_StateUILabel_Battery:614data->states[i] = POWER_STATE_TYPE_BATTERY;615break;616case PP_StateUILabel_Balanced:617data->states[i] = POWER_STATE_TYPE_BALANCED;618break;619case PP_StateUILabel_Performance:620data->states[i] = POWER_STATE_TYPE_PERFORMANCE;621break;622default:623if (state->classification.flags & PP_StateClassificationFlag_Boot)624data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;625else626data->states[i] = POWER_STATE_TYPE_DEFAULT;627}628}629return 0;630}631632static int pp_dpm_get_pp_table(void *handle, char **table)633{634struct pp_hwmgr *hwmgr = handle;635636if (!hwmgr || !hwmgr->pm_en || !hwmgr->soft_pp_table)637return -EINVAL;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_print_clock_levels(void *handle,727enum pp_clock_type type, char *buf)728{729struct pp_hwmgr *hwmgr = handle;730731if (!hwmgr || !hwmgr->pm_en)732return -EINVAL;733734if (hwmgr->hwmgr_func->print_clock_levels == NULL) {735pr_info_ratelimited("%s was not implemented.\n", __func__);736return 0;737}738return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);739}740741static int pp_dpm_get_sclk_od(void *handle)742{743struct pp_hwmgr *hwmgr = handle;744745if (!hwmgr || !hwmgr->pm_en)746return -EINVAL;747748if (hwmgr->hwmgr_func->get_sclk_od == NULL) {749pr_info_ratelimited("%s was not implemented.\n", __func__);750return 0;751}752return hwmgr->hwmgr_func->get_sclk_od(hwmgr);753}754755static int pp_dpm_set_sclk_od(void *handle, uint32_t value)756{757struct pp_hwmgr *hwmgr = handle;758759if (!hwmgr || !hwmgr->pm_en)760return -EINVAL;761762if (hwmgr->hwmgr_func->set_sclk_od == NULL) {763pr_info_ratelimited("%s was not implemented.\n", __func__);764return 0;765}766767return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);768}769770static int pp_dpm_get_mclk_od(void *handle)771{772struct pp_hwmgr *hwmgr = handle;773774if (!hwmgr || !hwmgr->pm_en)775return -EINVAL;776777if (hwmgr->hwmgr_func->get_mclk_od == NULL) {778pr_info_ratelimited("%s was not implemented.\n", __func__);779return 0;780}781return hwmgr->hwmgr_func->get_mclk_od(hwmgr);782}783784static int pp_dpm_set_mclk_od(void *handle, uint32_t value)785{786struct pp_hwmgr *hwmgr = handle;787788if (!hwmgr || !hwmgr->pm_en)789return -EINVAL;790791if (hwmgr->hwmgr_func->set_mclk_od == NULL) {792pr_info_ratelimited("%s was not implemented.\n", __func__);793return 0;794}795return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);796}797798static int pp_dpm_read_sensor(void *handle, int idx,799void *value, int *size)800{801struct pp_hwmgr *hwmgr = handle;802803if (!hwmgr || !hwmgr->pm_en || !value)804return -EINVAL;805806switch (idx) {807case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:808*((uint32_t *)value) = hwmgr->pstate_sclk * 100;809return 0;810case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:811*((uint32_t *)value) = hwmgr->pstate_mclk * 100;812return 0;813case AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK:814*((uint32_t *)value) = hwmgr->pstate_sclk_peak * 100;815return 0;816case AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK:817*((uint32_t *)value) = hwmgr->pstate_mclk_peak * 100;818return 0;819case AMDGPU_PP_SENSOR_MIN_FAN_RPM:820*((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM;821return 0;822case AMDGPU_PP_SENSOR_MAX_FAN_RPM:823*((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM;824return 0;825default:826return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);827}828}829830static struct amd_vce_state*831pp_dpm_get_vce_clock_state(void *handle, unsigned idx)832{833struct pp_hwmgr *hwmgr = handle;834835if (!hwmgr || !hwmgr->pm_en)836return NULL;837838if (idx < hwmgr->num_vce_state_tables)839return &hwmgr->vce_states[idx];840return NULL;841}842843static int pp_get_power_profile_mode(void *handle, char *buf)844{845struct pp_hwmgr *hwmgr = handle;846847if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->get_power_profile_mode)848return -EOPNOTSUPP;849if (!buf)850return -EINVAL;851852return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);853}854855static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)856{857struct pp_hwmgr *hwmgr = handle;858859if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->set_power_profile_mode)860return -EOPNOTSUPP;861862if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {863pr_debug("power profile setting is for manual dpm mode only.\n");864return -EINVAL;865}866867return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);868}869870static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size)871{872struct pp_hwmgr *hwmgr = handle;873874if (!hwmgr || !hwmgr->pm_en)875return -EINVAL;876877if (hwmgr->hwmgr_func->set_fine_grain_clk_vol == NULL)878return 0;879880return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size);881}882883static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type,884long *input, uint32_t size)885{886struct pp_hwmgr *hwmgr = handle;887888if (!hwmgr || !hwmgr->pm_en)889return -EINVAL;890891if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {892pr_info_ratelimited("%s was not implemented.\n", __func__);893return 0;894}895896return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);897}898899static int pp_dpm_set_mp1_state(void *handle, enum pp_mp1_state mp1_state)900{901struct pp_hwmgr *hwmgr = handle;902903if (!hwmgr)904return -EINVAL;905906if (!hwmgr->pm_en)907return 0;908909if (hwmgr->hwmgr_func->set_mp1_state)910return hwmgr->hwmgr_func->set_mp1_state(hwmgr, mp1_state);911912return 0;913}914915static int pp_dpm_switch_power_profile(void *handle,916enum PP_SMC_POWER_PROFILE type, bool en)917{918struct pp_hwmgr *hwmgr = handle;919long workload[1];920uint32_t index;921922if (!hwmgr || !hwmgr->pm_en)923return -EINVAL;924925if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {926pr_info_ratelimited("%s was not implemented.\n", __func__);927return -EINVAL;928}929930if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))931return -EINVAL;932933if (!en) {934hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);935index = fls(hwmgr->workload_mask);936index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;937workload[0] = hwmgr->workload_setting[index];938} else {939hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);940index = fls(hwmgr->workload_mask);941index = index <= Workload_Policy_Max ? index - 1 : 0;942workload[0] = hwmgr->workload_setting[index];943}944945if (type == PP_SMC_POWER_PROFILE_COMPUTE &&946hwmgr->hwmgr_func->disable_power_features_for_compute_performance) {947if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en))948return -EINVAL;949}950951if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)952hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);953954return 0;955}956957static int pp_set_power_limit(void *handle, uint32_t limit)958{959struct pp_hwmgr *hwmgr = handle;960uint32_t max_power_limit;961962if (!hwmgr || !hwmgr->pm_en)963return -EINVAL;964965if (hwmgr->hwmgr_func->set_power_limit == NULL) {966pr_info_ratelimited("%s was not implemented.\n", __func__);967return -EINVAL;968}969970if (limit == 0)971limit = hwmgr->default_power_limit;972973max_power_limit = hwmgr->default_power_limit;974if (hwmgr->od_enabled) {975max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);976max_power_limit /= 100;977}978979if (limit > max_power_limit)980return -EINVAL;981982hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);983hwmgr->power_limit = limit;984return 0;985}986987static int pp_get_power_limit(void *handle, uint32_t *limit,988enum pp_power_limit_level pp_limit_level,989enum pp_power_type power_type)990{991struct pp_hwmgr *hwmgr = handle;992int ret = 0;993994if (!hwmgr || !hwmgr->pm_en || !limit)995return -EINVAL;996997if (power_type != PP_PWR_TYPE_SUSTAINED)998return -EOPNOTSUPP;9991000switch (pp_limit_level) {1001case PP_PWR_LIMIT_CURRENT:1002*limit = hwmgr->power_limit;1003break;1004case PP_PWR_LIMIT_DEFAULT:1005*limit = hwmgr->default_power_limit;1006break;1007case PP_PWR_LIMIT_MAX:1008*limit = hwmgr->default_power_limit;1009if (hwmgr->od_enabled) {1010*limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);1011*limit /= 100;1012}1013break;1014case PP_PWR_LIMIT_MIN:1015*limit = 0;1016break;1017default:1018ret = -EOPNOTSUPP;1019break;1020}10211022return ret;1023}10241025static int pp_display_configuration_change(void *handle,1026const struct amd_pp_display_configuration *display_config)1027{1028struct pp_hwmgr *hwmgr = handle;10291030if (!hwmgr || !hwmgr->pm_en)1031return -EINVAL;10321033phm_store_dal_configuration_data(hwmgr, display_config);1034return 0;1035}10361037static int pp_get_display_power_level(void *handle,1038struct amd_pp_simple_clock_info *output)1039{1040struct pp_hwmgr *hwmgr = handle;10411042if (!hwmgr || !hwmgr->pm_en || !output)1043return -EINVAL;10441045return phm_get_dal_power_level(hwmgr, output);1046}10471048static int pp_get_current_clocks(void *handle,1049struct amd_pp_clock_info *clocks)1050{1051struct amd_pp_simple_clock_info simple_clocks = { 0 };1052struct pp_clock_info hw_clocks;1053struct pp_hwmgr *hwmgr = handle;1054int ret = 0;10551056if (!hwmgr || !hwmgr->pm_en)1057return -EINVAL;10581059phm_get_dal_power_level(hwmgr, &simple_clocks);10601061if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,1062PHM_PlatformCaps_PowerContainment))1063ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,1064&hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);1065else1066ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,1067&hw_clocks, PHM_PerformanceLevelDesignation_Activity);10681069if (ret) {1070pr_debug("Error in phm_get_clock_info \n");1071return -EINVAL;1072}10731074clocks->min_engine_clock = hw_clocks.min_eng_clk;1075clocks->max_engine_clock = hw_clocks.max_eng_clk;1076clocks->min_memory_clock = hw_clocks.min_mem_clk;1077clocks->max_memory_clock = hw_clocks.max_mem_clk;1078clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;1079clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;10801081clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;1082clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;10831084if (simple_clocks.level == 0)1085clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;1086else1087clocks->max_clocks_state = simple_clocks.level;10881089if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {1090clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;1091clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;1092}1093return 0;1094}10951096static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)1097{1098struct pp_hwmgr *hwmgr = handle;10991100if (!hwmgr || !hwmgr->pm_en)1101return -EINVAL;11021103if (clocks == NULL)1104return -EINVAL;11051106return phm_get_clock_by_type(hwmgr, type, clocks);1107}11081109static int pp_get_clock_by_type_with_latency(void *handle,1110enum amd_pp_clock_type type,1111struct pp_clock_levels_with_latency *clocks)1112{1113struct pp_hwmgr *hwmgr = handle;11141115if (!hwmgr || !hwmgr->pm_en || !clocks)1116return -EINVAL;11171118return phm_get_clock_by_type_with_latency(hwmgr, type, clocks);1119}11201121static int pp_get_clock_by_type_with_voltage(void *handle,1122enum amd_pp_clock_type type,1123struct pp_clock_levels_with_voltage *clocks)1124{1125struct pp_hwmgr *hwmgr = handle;11261127if (!hwmgr || !hwmgr->pm_en || !clocks)1128return -EINVAL;11291130return phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);1131}11321133static int pp_set_watermarks_for_clocks_ranges(void *handle,1134void *clock_ranges)1135{1136struct pp_hwmgr *hwmgr = handle;11371138if (!hwmgr || !hwmgr->pm_en || !clock_ranges)1139return -EINVAL;11401141return phm_set_watermarks_for_clocks_ranges(hwmgr,1142clock_ranges);1143}11441145static int pp_display_clock_voltage_request(void *handle,1146struct pp_display_clock_request *clock)1147{1148struct pp_hwmgr *hwmgr = handle;11491150if (!hwmgr || !hwmgr->pm_en || !clock)1151return -EINVAL;11521153return phm_display_clock_voltage_request(hwmgr, clock);1154}11551156static int pp_get_display_mode_validation_clocks(void *handle,1157struct amd_pp_simple_clock_info *clocks)1158{1159struct pp_hwmgr *hwmgr = handle;1160int ret = 0;11611162if (!hwmgr || !hwmgr->pm_en || !clocks)1163return -EINVAL;11641165clocks->level = PP_DAL_POWERLEVEL_7;11661167if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))1168ret = phm_get_max_high_clocks(hwmgr, clocks);11691170return ret;1171}11721173static int pp_dpm_powergate_mmhub(void *handle)1174{1175struct pp_hwmgr *hwmgr = handle;11761177if (!hwmgr || !hwmgr->pm_en)1178return -EINVAL;11791180if (hwmgr->hwmgr_func->powergate_mmhub == NULL) {1181pr_info_ratelimited("%s was not implemented.\n", __func__);1182return 0;1183}11841185return hwmgr->hwmgr_func->powergate_mmhub(hwmgr);1186}11871188static int pp_dpm_powergate_gfx(void *handle, bool gate)1189{1190struct pp_hwmgr *hwmgr = handle;11911192if (!hwmgr || !hwmgr->pm_en)1193return 0;11941195if (hwmgr->hwmgr_func->powergate_gfx == NULL) {1196pr_info_ratelimited("%s was not implemented.\n", __func__);1197return 0;1198}11991200return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate);1201}12021203static void pp_dpm_powergate_acp(void *handle, bool gate)1204{1205struct pp_hwmgr *hwmgr = handle;12061207if (!hwmgr || !hwmgr->pm_en)1208return;12091210if (hwmgr->hwmgr_func->powergate_acp == NULL) {1211pr_info_ratelimited("%s was not implemented.\n", __func__);1212return;1213}12141215hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);1216}12171218static void pp_dpm_powergate_sdma(void *handle, bool gate)1219{1220struct pp_hwmgr *hwmgr = handle;12211222if (!hwmgr)1223return;12241225if (hwmgr->hwmgr_func->powergate_sdma == NULL) {1226pr_info_ratelimited("%s was not implemented.\n", __func__);1227return;1228}12291230hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);1231}12321233static int pp_set_powergating_by_smu(void *handle,1234uint32_t block_type,1235bool gate,1236int inst)1237{1238int ret = 0;12391240switch (block_type) {1241case AMD_IP_BLOCK_TYPE_UVD:1242case AMD_IP_BLOCK_TYPE_VCN:1243pp_dpm_powergate_uvd(handle, gate);1244break;1245case AMD_IP_BLOCK_TYPE_VCE:1246pp_dpm_powergate_vce(handle, gate);1247break;1248case AMD_IP_BLOCK_TYPE_GMC:1249/*1250* For now, this is only used on PICASSO.1251* And only "gate" operation is supported.1252*/1253if (gate)1254pp_dpm_powergate_mmhub(handle);1255break;1256case AMD_IP_BLOCK_TYPE_GFX:1257ret = pp_dpm_powergate_gfx(handle, gate);1258break;1259case AMD_IP_BLOCK_TYPE_ACP:1260pp_dpm_powergate_acp(handle, gate);1261break;1262case AMD_IP_BLOCK_TYPE_SDMA:1263pp_dpm_powergate_sdma(handle, gate);1264break;1265default:1266break;1267}1268return ret;1269}12701271static int pp_notify_smu_enable_pwe(void *handle)1272{1273struct pp_hwmgr *hwmgr = handle;12741275if (!hwmgr || !hwmgr->pm_en)1276return -EINVAL;12771278if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) {1279pr_info_ratelimited("%s was not implemented.\n", __func__);1280return -EINVAL;1281}12821283hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);12841285return 0;1286}12871288static int pp_enable_mgpu_fan_boost(void *handle)1289{1290struct pp_hwmgr *hwmgr = handle;12911292if (!hwmgr)1293return -EINVAL;12941295if (!hwmgr->pm_en ||1296hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL)1297return 0;12981299hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);13001301return 0;1302}13031304static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock)1305{1306struct pp_hwmgr *hwmgr = handle;13071308if (!hwmgr || !hwmgr->pm_en)1309return -EINVAL;13101311if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) {1312pr_debug("%s was not implemented.\n", __func__);1313return -EINVAL;1314}13151316hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock);13171318return 0;1319}13201321static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock)1322{1323struct pp_hwmgr *hwmgr = handle;13241325if (!hwmgr || !hwmgr->pm_en)1326return -EINVAL;13271328if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) {1329pr_debug("%s was not implemented.\n", __func__);1330return -EINVAL;1331}13321333hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock);13341335return 0;1336}13371338static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock)1339{1340struct pp_hwmgr *hwmgr = handle;13411342if (!hwmgr || !hwmgr->pm_en)1343return -EINVAL;13441345if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) {1346pr_debug("%s was not implemented.\n", __func__);1347return -EINVAL;1348}13491350hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock);13511352return 0;1353}13541355static int pp_set_active_display_count(void *handle, uint32_t count)1356{1357struct pp_hwmgr *hwmgr = handle;13581359if (!hwmgr || !hwmgr->pm_en)1360return -EINVAL;13611362return phm_set_active_display_count(hwmgr, count);1363}13641365static int pp_get_asic_baco_capability(void *handle)1366{1367struct pp_hwmgr *hwmgr = handle;13681369if (!hwmgr)1370return false;13711372if (!(hwmgr->not_vf && amdgpu_dpm) ||1373!hwmgr->hwmgr_func->get_bamaco_support)1374return false;13751376return hwmgr->hwmgr_func->get_bamaco_support(hwmgr);1377}13781379static int pp_get_asic_baco_state(void *handle, int *state)1380{1381struct pp_hwmgr *hwmgr = handle;13821383if (!hwmgr)1384return -EINVAL;13851386if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)1387return 0;13881389hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state);13901391return 0;1392}13931394static int pp_set_asic_baco_state(void *handle, int state)1395{1396struct pp_hwmgr *hwmgr = handle;13971398if (!hwmgr)1399return -EINVAL;14001401if (!(hwmgr->not_vf && amdgpu_dpm) ||1402!hwmgr->hwmgr_func->set_asic_baco_state)1403return 0;14041405hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state);14061407return 0;1408}14091410static int pp_get_ppfeature_status(void *handle, char *buf)1411{1412struct pp_hwmgr *hwmgr = handle;14131414if (!hwmgr || !hwmgr->pm_en || !buf)1415return -EINVAL;14161417if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {1418pr_info_ratelimited("%s was not implemented.\n", __func__);1419return -EINVAL;1420}14211422return hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);1423}14241425static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)1426{1427struct pp_hwmgr *hwmgr = handle;14281429if (!hwmgr || !hwmgr->pm_en)1430return -EINVAL;14311432if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {1433pr_info_ratelimited("%s was not implemented.\n", __func__);1434return -EINVAL;1435}14361437return hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);1438}14391440static int pp_asic_reset_mode_2(void *handle)1441{1442struct pp_hwmgr *hwmgr = handle;14431444if (!hwmgr || !hwmgr->pm_en)1445return -EINVAL;14461447if (hwmgr->hwmgr_func->asic_reset == NULL) {1448pr_info_ratelimited("%s was not implemented.\n", __func__);1449return -EINVAL;1450}14511452return hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2);1453}14541455static int pp_smu_i2c_bus_access(void *handle, bool acquire)1456{1457struct pp_hwmgr *hwmgr = handle;14581459if (!hwmgr || !hwmgr->pm_en)1460return -EINVAL;14611462if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) {1463pr_info_ratelimited("%s was not implemented.\n", __func__);1464return -EINVAL;1465}14661467return hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire);1468}14691470static int pp_set_df_cstate(void *handle, enum pp_df_cstate state)1471{1472struct pp_hwmgr *hwmgr = handle;14731474if (!hwmgr)1475return -EINVAL;14761477if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate)1478return 0;14791480hwmgr->hwmgr_func->set_df_cstate(hwmgr, state);14811482return 0;1483}14841485static int pp_set_xgmi_pstate(void *handle, uint32_t pstate)1486{1487struct pp_hwmgr *hwmgr = handle;14881489if (!hwmgr)1490return -EINVAL;14911492if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate)1493return 0;14941495hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate);14961497return 0;1498}14991500static ssize_t pp_get_gpu_metrics(void *handle, void **table)1501{1502struct pp_hwmgr *hwmgr = handle;15031504if (!hwmgr)1505return -EINVAL;15061507if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics)1508return -EOPNOTSUPP;15091510return hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table);1511}15121513static int pp_gfx_state_change_set(void *handle, uint32_t state)1514{1515struct pp_hwmgr *hwmgr = handle;15161517if (!hwmgr || !hwmgr->pm_en)1518return -EINVAL;15191520if (hwmgr->hwmgr_func->gfx_state_change == NULL) {1521pr_info_ratelimited("%s was not implemented.\n", __func__);1522return -EINVAL;1523}15241525hwmgr->hwmgr_func->gfx_state_change(hwmgr, state);1526return 0;1527}15281529static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size)1530{1531struct pp_hwmgr *hwmgr = handle;1532struct amdgpu_device *adev = hwmgr->adev;1533int err;15341535if (!addr || !size)1536return -EINVAL;15371538*addr = NULL;1539*size = 0;1540if (adev->pm.smu_prv_buffer) {1541err = amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr);1542if (err)1543return err;1544*size = adev->pm.smu_prv_buffer_size;1545}15461547return 0;1548}15491550static void pp_pm_compute_clocks(void *handle)1551{1552struct pp_hwmgr *hwmgr = handle;1553struct amdgpu_device *adev = hwmgr->adev;15541555if (!adev->dc_enabled) {1556amdgpu_dpm_get_active_displays(adev);1557adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;1558adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);1559adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev);1560/* we have issues with mclk switching with1561* refresh rates over 120 hz on the non-DC code.1562*/1563if (adev->pm.pm_display_cfg.vrefresh > 120)1564adev->pm.pm_display_cfg.min_vblank_time = 0;15651566pp_display_configuration_change(handle,1567&adev->pm.pm_display_cfg);1568}15691570pp_dpm_dispatch_tasks(handle,1571AMD_PP_TASK_DISPLAY_CONFIG_CHANGE,1572NULL);1573}15741575static const struct amd_pm_funcs pp_dpm_funcs = {1576.load_firmware = pp_dpm_load_fw,1577.wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,1578.force_performance_level = pp_dpm_force_performance_level,1579.get_performance_level = pp_dpm_get_performance_level,1580.get_current_power_state = pp_dpm_get_current_power_state,1581.dispatch_tasks = pp_dpm_dispatch_tasks,1582.set_fan_control_mode = pp_dpm_set_fan_control_mode,1583.get_fan_control_mode = pp_dpm_get_fan_control_mode,1584.set_fan_speed_pwm = pp_dpm_set_fan_speed_pwm,1585.get_fan_speed_pwm = pp_dpm_get_fan_speed_pwm,1586.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,1587.set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,1588.get_pp_num_states = pp_dpm_get_pp_num_states,1589.get_pp_table = pp_dpm_get_pp_table,1590.set_pp_table = pp_dpm_set_pp_table,1591.force_clock_level = pp_dpm_force_clock_level,1592.emit_clock_levels = pp_dpm_emit_clock_levels,1593.print_clock_levels = pp_dpm_print_clock_levels,1594.get_sclk_od = pp_dpm_get_sclk_od,1595.set_sclk_od = pp_dpm_set_sclk_od,1596.get_mclk_od = pp_dpm_get_mclk_od,1597.set_mclk_od = pp_dpm_set_mclk_od,1598.read_sensor = pp_dpm_read_sensor,1599.get_vce_clock_state = pp_dpm_get_vce_clock_state,1600.switch_power_profile = pp_dpm_switch_power_profile,1601.set_clockgating_by_smu = pp_set_clockgating_by_smu,1602.set_powergating_by_smu = pp_set_powergating_by_smu,1603.get_power_profile_mode = pp_get_power_profile_mode,1604.set_power_profile_mode = pp_set_power_profile_mode,1605.set_fine_grain_clk_vol = pp_set_fine_grain_clk_vol,1606.odn_edit_dpm_table = pp_odn_edit_dpm_table,1607.set_mp1_state = pp_dpm_set_mp1_state,1608.set_power_limit = pp_set_power_limit,1609.get_power_limit = pp_get_power_limit,1610/* export to DC */1611.get_sclk = pp_dpm_get_sclk,1612.get_mclk = pp_dpm_get_mclk,1613.display_configuration_change = pp_display_configuration_change,1614.get_display_power_level = pp_get_display_power_level,1615.get_current_clocks = pp_get_current_clocks,1616.get_clock_by_type = pp_get_clock_by_type,1617.get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,1618.get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,1619.set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,1620.display_clock_voltage_request = pp_display_clock_voltage_request,1621.get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,1622.notify_smu_enable_pwe = pp_notify_smu_enable_pwe,1623.enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,1624.set_active_display_count = pp_set_active_display_count,1625.set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk,1626.set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq,1627.set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq,1628.get_asic_baco_capability = pp_get_asic_baco_capability,1629.get_asic_baco_state = pp_get_asic_baco_state,1630.set_asic_baco_state = pp_set_asic_baco_state,1631.get_ppfeature_status = pp_get_ppfeature_status,1632.set_ppfeature_status = pp_set_ppfeature_status,1633.asic_reset_mode_2 = pp_asic_reset_mode_2,1634.smu_i2c_bus_access = pp_smu_i2c_bus_access,1635.set_df_cstate = pp_set_df_cstate,1636.set_xgmi_pstate = pp_set_xgmi_pstate,1637.get_gpu_metrics = pp_get_gpu_metrics,1638.gfx_state_change_set = pp_gfx_state_change_set,1639.get_smu_prv_buf_details = pp_get_prv_buffer_details,1640.pm_compute_clocks = pp_pm_compute_clocks,1641};164216431644