linux/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
<<
>>
Prefs
   1/*
   2 * Copyright 2015 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23#include "pp_debug.h"
  24#include <linux/types.h>
  25#include <linux/kernel.h>
  26#include <linux/gfp.h>
  27#include <linux/slab.h>
  28#include <linux/firmware.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
  35
  36static const struct amd_pm_funcs pp_dpm_funcs;
  37
  38static int amd_powerplay_create(struct amdgpu_device *adev)
  39{
  40        struct pp_hwmgr *hwmgr;
  41
  42        if (adev == NULL)
  43                return -EINVAL;
  44
  45        hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
  46        if (hwmgr == NULL)
  47                return -ENOMEM;
  48
  49        hwmgr->adev = adev;
  50        hwmgr->not_vf = !amdgpu_sriov_vf(adev);
  51        hwmgr->pm_en = (amdgpu_dpm && hwmgr->not_vf) ? true : false;
  52        hwmgr->device = amdgpu_cgs_create_device(adev);
  53        mutex_init(&hwmgr->smu_lock);
  54        hwmgr->chip_family = adev->family;
  55        hwmgr->chip_id = adev->asic_type;
  56        hwmgr->feature_mask = adev->powerplay.pp_feature;
  57        hwmgr->display_config = &adev->pm.pm_display_cfg;
  58        adev->powerplay.pp_handle = hwmgr;
  59        adev->powerplay.pp_funcs = &pp_dpm_funcs;
  60        return 0;
  61}
  62
  63
  64static void amd_powerplay_destroy(struct amdgpu_device *adev)
  65{
  66        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
  67
  68        kfree(hwmgr->hardcode_pp_table);
  69        hwmgr->hardcode_pp_table = NULL;
  70
  71        kfree(hwmgr);
  72        hwmgr = NULL;
  73}
  74
  75static int pp_early_init(void *handle)
  76{
  77        int ret;
  78        struct amdgpu_device *adev = handle;
  79
  80        ret = amd_powerplay_create(adev);
  81
  82        if (ret != 0)
  83                return ret;
  84
  85        ret = hwmgr_early_init(adev->powerplay.pp_handle);
  86        if (ret)
  87                return -EINVAL;
  88
  89        return 0;
  90}
  91
  92static int pp_sw_init(void *handle)
  93{
  94        struct amdgpu_device *adev = handle;
  95        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
  96        int ret = 0;
  97
  98        ret = hwmgr_sw_init(hwmgr);
  99
 100        pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");
 101
 102        return ret;
 103}
 104
 105static int pp_sw_fini(void *handle)
 106{
 107        struct amdgpu_device *adev = handle;
 108        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 109
 110        hwmgr_sw_fini(hwmgr);
 111
 112        release_firmware(adev->pm.fw);
 113        adev->pm.fw = NULL;
 114
 115        return 0;
 116}
 117
 118static int pp_hw_init(void *handle)
 119{
 120        int ret = 0;
 121        struct amdgpu_device *adev = handle;
 122        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 123
 124        ret = hwmgr_hw_init(hwmgr);
 125
 126        if (ret)
 127                pr_err("powerplay hw init failed\n");
 128
 129        return ret;
 130}
 131
 132static int pp_hw_fini(void *handle)
 133{
 134        struct amdgpu_device *adev = handle;
 135        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 136
 137        hwmgr_hw_fini(hwmgr);
 138
 139        return 0;
 140}
 141
 142static void pp_reserve_vram_for_smu(struct amdgpu_device *adev)
 143{
 144        int r = -EINVAL;
 145        void *cpu_ptr = NULL;
 146        uint64_t gpu_addr;
 147        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 148
 149        if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size,
 150                                                PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
 151                                                &adev->pm.smu_prv_buffer,
 152                                                &gpu_addr,
 153                                                &cpu_ptr)) {
 154                DRM_ERROR("amdgpu: failed to create smu prv buffer\n");
 155                return;
 156        }
 157
 158        if (hwmgr->hwmgr_func->notify_cac_buffer_info)
 159                r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr,
 160                                        lower_32_bits((unsigned long)cpu_ptr),
 161                                        upper_32_bits((unsigned long)cpu_ptr),
 162                                        lower_32_bits(gpu_addr),
 163                                        upper_32_bits(gpu_addr),
 164                                        adev->pm.smu_prv_buffer_size);
 165
 166        if (r) {
 167                amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
 168                adev->pm.smu_prv_buffer = NULL;
 169                DRM_ERROR("amdgpu: failed to notify SMU buffer address\n");
 170        }
 171}
 172
 173static int pp_late_init(void *handle)
 174{
 175        struct amdgpu_device *adev = handle;
 176        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 177
 178        if (hwmgr && hwmgr->pm_en) {
 179                mutex_lock(&hwmgr->smu_lock);
 180                hwmgr_handle_task(hwmgr,
 181                                        AMD_PP_TASK_COMPLETE_INIT, NULL);
 182                mutex_unlock(&hwmgr->smu_lock);
 183        }
 184        if (adev->pm.smu_prv_buffer_size != 0)
 185                pp_reserve_vram_for_smu(adev);
 186
 187        return 0;
 188}
 189
 190static void pp_late_fini(void *handle)
 191{
 192        struct amdgpu_device *adev = handle;
 193
 194        if (adev->pm.smu_prv_buffer)
 195                amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
 196        amd_powerplay_destroy(adev);
 197}
 198
 199
 200static bool pp_is_idle(void *handle)
 201{
 202        return false;
 203}
 204
 205static int pp_wait_for_idle(void *handle)
 206{
 207        return 0;
 208}
 209
 210static int pp_sw_reset(void *handle)
 211{
 212        return 0;
 213}
 214
 215static int pp_set_powergating_state(void *handle,
 216                                    enum amd_powergating_state state)
 217{
 218        return 0;
 219}
 220
 221static int pp_suspend(void *handle)
 222{
 223        struct amdgpu_device *adev = handle;
 224        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 225
 226        return hwmgr_suspend(hwmgr);
 227}
 228
 229static int pp_resume(void *handle)
 230{
 231        struct amdgpu_device *adev = handle;
 232        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
 233
 234        return hwmgr_resume(hwmgr);
 235}
 236
 237static int pp_set_clockgating_state(void *handle,
 238                                          enum amd_clockgating_state state)
 239{
 240        return 0;
 241}
 242
 243static const struct amd_ip_funcs pp_ip_funcs = {
 244        .name = "powerplay",
 245        .early_init = pp_early_init,
 246        .late_init = pp_late_init,
 247        .sw_init = pp_sw_init,
 248        .sw_fini = pp_sw_fini,
 249        .hw_init = pp_hw_init,
 250        .hw_fini = pp_hw_fini,
 251        .late_fini = pp_late_fini,
 252        .suspend = pp_suspend,
 253        .resume = pp_resume,
 254        .is_idle = pp_is_idle,
 255        .wait_for_idle = pp_wait_for_idle,
 256        .soft_reset = pp_sw_reset,
 257        .set_clockgating_state = pp_set_clockgating_state,
 258        .set_powergating_state = pp_set_powergating_state,
 259};
 260
 261const struct amdgpu_ip_block_version pp_smu_ip_block =
 262{
 263        .type = AMD_IP_BLOCK_TYPE_SMC,
 264        .major = 1,
 265        .minor = 0,
 266        .rev = 0,
 267        .funcs = &pp_ip_funcs,
 268};
 269
 270/* This interface only be supported On Vi,
 271 * because only smu7/8 can help to load gfx/sdma fw,
 272 * smu need to be enabled before load other ip's fw.
 273 * so call start smu to load smu7 fw and other ip's fw
 274 */
 275static int pp_dpm_load_fw(void *handle)
 276{
 277        struct pp_hwmgr *hwmgr = handle;
 278
 279        if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu)
 280                return -EINVAL;
 281
 282        if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {
 283                pr_err("fw load failed\n");
 284                return -EINVAL;
 285        }
 286
 287        return 0;
 288}
 289
 290static int pp_dpm_fw_loading_complete(void *handle)
 291{
 292        return 0;
 293}
 294
 295static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
 296{
 297        struct pp_hwmgr *hwmgr = handle;
 298
 299        if (!hwmgr || !hwmgr->pm_en)
 300                return -EINVAL;
 301
 302        if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
 303                pr_info_ratelimited("%s was not implemented.\n", __func__);
 304                return 0;
 305        }
 306
 307        return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
 308}
 309
 310static void pp_dpm_en_umd_pstate(struct pp_hwmgr  *hwmgr,
 311                                                enum amd_dpm_forced_level *level)
 312{
 313        uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
 314                                        AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
 315                                        AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
 316                                        AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
 317
 318        if (!(hwmgr->dpm_level & profile_mode_mask)) {
 319                /* enter umd pstate, save current level, disable gfx cg*/
 320                if (*level & profile_mode_mask) {
 321                        hwmgr->saved_dpm_level = hwmgr->dpm_level;
 322                        hwmgr->en_umd_pstate = true;
 323                        amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
 324                                                AMD_IP_BLOCK_TYPE_GFX,
 325                                                AMD_CG_STATE_UNGATE);
 326                        amdgpu_device_ip_set_powergating_state(hwmgr->adev,
 327                                        AMD_IP_BLOCK_TYPE_GFX,
 328                                        AMD_PG_STATE_UNGATE);
 329                }
 330        } else {
 331                /* exit umd pstate, restore level, enable gfx cg*/
 332                if (!(*level & profile_mode_mask)) {
 333                        if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
 334                                *level = hwmgr->saved_dpm_level;
 335                        hwmgr->en_umd_pstate = false;
 336                        amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
 337                                        AMD_IP_BLOCK_TYPE_GFX,
 338                                        AMD_CG_STATE_GATE);
 339                        amdgpu_device_ip_set_powergating_state(hwmgr->adev,
 340                                        AMD_IP_BLOCK_TYPE_GFX,
 341                                        AMD_PG_STATE_GATE);
 342                }
 343        }
 344}
 345
 346static int pp_dpm_force_performance_level(void *handle,
 347                                        enum amd_dpm_forced_level level)
 348{
 349        struct pp_hwmgr *hwmgr = handle;
 350
 351        if (!hwmgr || !hwmgr->pm_en)
 352                return -EINVAL;
 353
 354        if (level == hwmgr->dpm_level)
 355                return 0;
 356
 357        mutex_lock(&hwmgr->smu_lock);
 358        pp_dpm_en_umd_pstate(hwmgr, &level);
 359        hwmgr->request_dpm_level = level;
 360        hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
 361        mutex_unlock(&hwmgr->smu_lock);
 362
 363        return 0;
 364}
 365
 366static enum amd_dpm_forced_level pp_dpm_get_performance_level(
 367                                                                void *handle)
 368{
 369        struct pp_hwmgr *hwmgr = handle;
 370        enum amd_dpm_forced_level level;
 371
 372        if (!hwmgr || !hwmgr->pm_en)
 373                return -EINVAL;
 374
 375        mutex_lock(&hwmgr->smu_lock);
 376        level = hwmgr->dpm_level;
 377        mutex_unlock(&hwmgr->smu_lock);
 378        return level;
 379}
 380
 381static uint32_t pp_dpm_get_sclk(void *handle, bool low)
 382{
 383        struct pp_hwmgr *hwmgr = handle;
 384        uint32_t clk = 0;
 385
 386        if (!hwmgr || !hwmgr->pm_en)
 387                return 0;
 388
 389        if (hwmgr->hwmgr_func->get_sclk == NULL) {
 390                pr_info_ratelimited("%s was not implemented.\n", __func__);
 391                return 0;
 392        }
 393        mutex_lock(&hwmgr->smu_lock);
 394        clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
 395        mutex_unlock(&hwmgr->smu_lock);
 396        return clk;
 397}
 398
 399static uint32_t pp_dpm_get_mclk(void *handle, bool low)
 400{
 401        struct pp_hwmgr *hwmgr = handle;
 402        uint32_t clk = 0;
 403
 404        if (!hwmgr || !hwmgr->pm_en)
 405                return 0;
 406
 407        if (hwmgr->hwmgr_func->get_mclk == NULL) {
 408                pr_info_ratelimited("%s was not implemented.\n", __func__);
 409                return 0;
 410        }
 411        mutex_lock(&hwmgr->smu_lock);
 412        clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
 413        mutex_unlock(&hwmgr->smu_lock);
 414        return clk;
 415}
 416
 417static void pp_dpm_powergate_vce(void *handle, bool gate)
 418{
 419        struct pp_hwmgr *hwmgr = handle;
 420
 421        if (!hwmgr || !hwmgr->pm_en)
 422                return;
 423
 424        if (hwmgr->hwmgr_func->powergate_vce == NULL) {
 425                pr_info_ratelimited("%s was not implemented.\n", __func__);
 426                return;
 427        }
 428        mutex_lock(&hwmgr->smu_lock);
 429        hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
 430        mutex_unlock(&hwmgr->smu_lock);
 431}
 432
 433static void pp_dpm_powergate_uvd(void *handle, bool gate)
 434{
 435        struct pp_hwmgr *hwmgr = handle;
 436
 437        if (!hwmgr || !hwmgr->pm_en)
 438                return;
 439
 440        if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
 441                pr_info_ratelimited("%s was not implemented.\n", __func__);
 442                return;
 443        }
 444        mutex_lock(&hwmgr->smu_lock);
 445        hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
 446        mutex_unlock(&hwmgr->smu_lock);
 447}
 448
 449static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
 450                enum amd_pm_state_type *user_state)
 451{
 452        int ret = 0;
 453        struct pp_hwmgr *hwmgr = handle;
 454
 455        if (!hwmgr || !hwmgr->pm_en)
 456                return -EINVAL;
 457
 458        mutex_lock(&hwmgr->smu_lock);
 459        ret = hwmgr_handle_task(hwmgr, task_id, user_state);
 460        mutex_unlock(&hwmgr->smu_lock);
 461
 462        return ret;
 463}
 464
 465static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
 466{
 467        struct pp_hwmgr *hwmgr = handle;
 468        struct pp_power_state *state;
 469        enum amd_pm_state_type pm_type;
 470
 471        if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)
 472                return -EINVAL;
 473
 474        mutex_lock(&hwmgr->smu_lock);
 475
 476        state = hwmgr->current_ps;
 477
 478        switch (state->classification.ui_label) {
 479        case PP_StateUILabel_Battery:
 480                pm_type = POWER_STATE_TYPE_BATTERY;
 481                break;
 482        case PP_StateUILabel_Balanced:
 483                pm_type = POWER_STATE_TYPE_BALANCED;
 484                break;
 485        case PP_StateUILabel_Performance:
 486                pm_type = POWER_STATE_TYPE_PERFORMANCE;
 487                break;
 488        default:
 489                if (state->classification.flags & PP_StateClassificationFlag_Boot)
 490                        pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
 491                else
 492                        pm_type = POWER_STATE_TYPE_DEFAULT;
 493                break;
 494        }
 495        mutex_unlock(&hwmgr->smu_lock);
 496
 497        return pm_type;
 498}
 499
 500static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
 501{
 502        struct pp_hwmgr *hwmgr = handle;
 503
 504        if (!hwmgr || !hwmgr->pm_en)
 505                return;
 506
 507        if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
 508                pr_info_ratelimited("%s was not implemented.\n", __func__);
 509                return;
 510        }
 511        mutex_lock(&hwmgr->smu_lock);
 512        hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
 513        mutex_unlock(&hwmgr->smu_lock);
 514}
 515
 516static uint32_t pp_dpm_get_fan_control_mode(void *handle)
 517{
 518        struct pp_hwmgr *hwmgr = handle;
 519        uint32_t mode = 0;
 520
 521        if (!hwmgr || !hwmgr->pm_en)
 522                return 0;
 523
 524        if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
 525                pr_info_ratelimited("%s was not implemented.\n", __func__);
 526                return 0;
 527        }
 528        mutex_lock(&hwmgr->smu_lock);
 529        mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
 530        mutex_unlock(&hwmgr->smu_lock);
 531        return mode;
 532}
 533
 534static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
 535{
 536        struct pp_hwmgr *hwmgr = handle;
 537        int ret = 0;
 538
 539        if (!hwmgr || !hwmgr->pm_en)
 540                return -EINVAL;
 541
 542        if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
 543                pr_info_ratelimited("%s was not implemented.\n", __func__);
 544                return 0;
 545        }
 546        mutex_lock(&hwmgr->smu_lock);
 547        ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
 548        mutex_unlock(&hwmgr->smu_lock);
 549        return ret;
 550}
 551
 552static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
 553{
 554        struct pp_hwmgr *hwmgr = handle;
 555        int ret = 0;
 556
 557        if (!hwmgr || !hwmgr->pm_en)
 558                return -EINVAL;
 559
 560        if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
 561                pr_info_ratelimited("%s was not implemented.\n", __func__);
 562                return 0;
 563        }
 564
 565        mutex_lock(&hwmgr->smu_lock);
 566        ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
 567        mutex_unlock(&hwmgr->smu_lock);
 568        return ret;
 569}
 570
 571static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
 572{
 573        struct pp_hwmgr *hwmgr = handle;
 574        int ret = 0;
 575
 576        if (!hwmgr || !hwmgr->pm_en)
 577                return -EINVAL;
 578
 579        if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
 580                return -EINVAL;
 581
 582        mutex_lock(&hwmgr->smu_lock);
 583        ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
 584        mutex_unlock(&hwmgr->smu_lock);
 585        return ret;
 586}
 587
 588static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm)
 589{
 590        struct pp_hwmgr *hwmgr = handle;
 591        int ret = 0;
 592
 593        if (!hwmgr || !hwmgr->pm_en)
 594                return -EINVAL;
 595
 596        if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) {
 597                pr_info_ratelimited("%s was not implemented.\n", __func__);
 598                return 0;
 599        }
 600        mutex_lock(&hwmgr->smu_lock);
 601        ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm);
 602        mutex_unlock(&hwmgr->smu_lock);
 603        return ret;
 604}
 605
 606static int pp_dpm_get_pp_num_states(void *handle,
 607                struct pp_states_info *data)
 608{
 609        struct pp_hwmgr *hwmgr = handle;
 610        int i;
 611
 612        memset(data, 0, sizeof(*data));
 613
 614        if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps)
 615                return -EINVAL;
 616
 617        mutex_lock(&hwmgr->smu_lock);
 618
 619        data->nums = hwmgr->num_ps;
 620
 621        for (i = 0; i < hwmgr->num_ps; i++) {
 622                struct pp_power_state *state = (struct pp_power_state *)
 623                                ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
 624                switch (state->classification.ui_label) {
 625                case PP_StateUILabel_Battery:
 626                        data->states[i] = POWER_STATE_TYPE_BATTERY;
 627                        break;
 628                case PP_StateUILabel_Balanced:
 629                        data->states[i] = POWER_STATE_TYPE_BALANCED;
 630                        break;
 631                case PP_StateUILabel_Performance:
 632                        data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
 633                        break;
 634                default:
 635                        if (state->classification.flags & PP_StateClassificationFlag_Boot)
 636                                data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
 637                        else
 638                                data->states[i] = POWER_STATE_TYPE_DEFAULT;
 639                }
 640        }
 641        mutex_unlock(&hwmgr->smu_lock);
 642        return 0;
 643}
 644
 645static int pp_dpm_get_pp_table(void *handle, char **table)
 646{
 647        struct pp_hwmgr *hwmgr = handle;
 648        int size = 0;
 649
 650        if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table)
 651                return -EINVAL;
 652
 653        mutex_lock(&hwmgr->smu_lock);
 654        *table = (char *)hwmgr->soft_pp_table;
 655        size = hwmgr->soft_pp_table_size;
 656        mutex_unlock(&hwmgr->smu_lock);
 657        return size;
 658}
 659
 660static int amd_powerplay_reset(void *handle)
 661{
 662        struct pp_hwmgr *hwmgr = handle;
 663        int ret;
 664
 665        ret = hwmgr_hw_fini(hwmgr);
 666        if (ret)
 667                return ret;
 668
 669        ret = hwmgr_hw_init(hwmgr);
 670        if (ret)
 671                return ret;
 672
 673        return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL);
 674}
 675
 676static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
 677{
 678        struct pp_hwmgr *hwmgr = handle;
 679        int ret = -ENOMEM;
 680
 681        if (!hwmgr || !hwmgr->pm_en)
 682                return -EINVAL;
 683
 684        mutex_lock(&hwmgr->smu_lock);
 685        if (!hwmgr->hardcode_pp_table) {
 686                hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
 687                                                   hwmgr->soft_pp_table_size,
 688                                                   GFP_KERNEL);
 689                if (!hwmgr->hardcode_pp_table)
 690                        goto err;
 691        }
 692
 693        memcpy(hwmgr->hardcode_pp_table, buf, size);
 694
 695        hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
 696
 697        ret = amd_powerplay_reset(handle);
 698        if (ret)
 699                goto err;
 700
 701        if (hwmgr->hwmgr_func->avfs_control) {
 702                ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
 703                if (ret)
 704                        goto err;
 705        }
 706        mutex_unlock(&hwmgr->smu_lock);
 707        return 0;
 708err:
 709        mutex_unlock(&hwmgr->smu_lock);
 710        return ret;
 711}
 712
 713static int pp_dpm_force_clock_level(void *handle,
 714                enum pp_clock_type type, uint32_t mask)
 715{
 716        struct pp_hwmgr *hwmgr = handle;
 717        int ret = 0;
 718
 719        if (!hwmgr || !hwmgr->pm_en)
 720                return -EINVAL;
 721
 722        if (hwmgr->hwmgr_func->force_clock_level == NULL) {
 723                pr_info_ratelimited("%s was not implemented.\n", __func__);
 724                return 0;
 725        }
 726
 727        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
 728                pr_debug("force clock level is for dpm manual mode only.\n");
 729                return -EINVAL;
 730        }
 731
 732        mutex_lock(&hwmgr->smu_lock);
 733        ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
 734        mutex_unlock(&hwmgr->smu_lock);
 735        return ret;
 736}
 737
 738static int pp_dpm_print_clock_levels(void *handle,
 739                enum pp_clock_type type, char *buf)
 740{
 741        struct pp_hwmgr *hwmgr = handle;
 742        int ret = 0;
 743
 744        if (!hwmgr || !hwmgr->pm_en)
 745                return -EINVAL;
 746
 747        if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
 748                pr_info_ratelimited("%s was not implemented.\n", __func__);
 749                return 0;
 750        }
 751        mutex_lock(&hwmgr->smu_lock);
 752        ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
 753        mutex_unlock(&hwmgr->smu_lock);
 754        return ret;
 755}
 756
 757static int pp_dpm_get_sclk_od(void *handle)
 758{
 759        struct pp_hwmgr *hwmgr = handle;
 760        int ret = 0;
 761
 762        if (!hwmgr || !hwmgr->pm_en)
 763                return -EINVAL;
 764
 765        if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
 766                pr_info_ratelimited("%s was not implemented.\n", __func__);
 767                return 0;
 768        }
 769        mutex_lock(&hwmgr->smu_lock);
 770        ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
 771        mutex_unlock(&hwmgr->smu_lock);
 772        return ret;
 773}
 774
 775static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
 776{
 777        struct pp_hwmgr *hwmgr = handle;
 778        int ret = 0;
 779
 780        if (!hwmgr || !hwmgr->pm_en)
 781                return -EINVAL;
 782
 783        if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
 784                pr_info_ratelimited("%s was not implemented.\n", __func__);
 785                return 0;
 786        }
 787
 788        mutex_lock(&hwmgr->smu_lock);
 789        ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
 790        mutex_unlock(&hwmgr->smu_lock);
 791        return ret;
 792}
 793
 794static int pp_dpm_get_mclk_od(void *handle)
 795{
 796        struct pp_hwmgr *hwmgr = handle;
 797        int ret = 0;
 798
 799        if (!hwmgr || !hwmgr->pm_en)
 800                return -EINVAL;
 801
 802        if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
 803                pr_info_ratelimited("%s was not implemented.\n", __func__);
 804                return 0;
 805        }
 806        mutex_lock(&hwmgr->smu_lock);
 807        ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
 808        mutex_unlock(&hwmgr->smu_lock);
 809        return ret;
 810}
 811
 812static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
 813{
 814        struct pp_hwmgr *hwmgr = handle;
 815        int ret = 0;
 816
 817        if (!hwmgr || !hwmgr->pm_en)
 818                return -EINVAL;
 819
 820        if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
 821                pr_info_ratelimited("%s was not implemented.\n", __func__);
 822                return 0;
 823        }
 824        mutex_lock(&hwmgr->smu_lock);
 825        ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
 826        mutex_unlock(&hwmgr->smu_lock);
 827        return ret;
 828}
 829
 830static int pp_dpm_read_sensor(void *handle, int idx,
 831                              void *value, int *size)
 832{
 833        struct pp_hwmgr *hwmgr = handle;
 834        int ret = 0;
 835
 836        if (!hwmgr || !hwmgr->pm_en || !value)
 837                return -EINVAL;
 838
 839        switch (idx) {
 840        case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
 841                *((uint32_t *)value) = hwmgr->pstate_sclk;
 842                return 0;
 843        case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
 844                *((uint32_t *)value) = hwmgr->pstate_mclk;
 845                return 0;
 846        case AMDGPU_PP_SENSOR_MIN_FAN_RPM:
 847                *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM;
 848                return 0;
 849        case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
 850                *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
 851                return 0;
 852        default:
 853                mutex_lock(&hwmgr->smu_lock);
 854                ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
 855                mutex_unlock(&hwmgr->smu_lock);
 856                return ret;
 857        }
 858}
 859
 860static struct amd_vce_state*
 861pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
 862{
 863        struct pp_hwmgr *hwmgr = handle;
 864
 865        if (!hwmgr || !hwmgr->pm_en)
 866                return NULL;
 867
 868        if (idx < hwmgr->num_vce_state_tables)
 869                return &hwmgr->vce_states[idx];
 870        return NULL;
 871}
 872
 873static int pp_get_power_profile_mode(void *handle, char *buf)
 874{
 875        struct pp_hwmgr *hwmgr = handle;
 876
 877        if (!hwmgr || !hwmgr->pm_en || !buf)
 878                return -EINVAL;
 879
 880        if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) {
 881                pr_info_ratelimited("%s was not implemented.\n", __func__);
 882                return snprintf(buf, PAGE_SIZE, "\n");
 883        }
 884
 885        return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
 886}
 887
 888static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
 889{
 890        struct pp_hwmgr *hwmgr = handle;
 891        int ret = -EINVAL;
 892
 893        if (!hwmgr || !hwmgr->pm_en)
 894                return ret;
 895
 896        if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
 897                pr_info_ratelimited("%s was not implemented.\n", __func__);
 898                return ret;
 899        }
 900
 901        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
 902                pr_debug("power profile setting is for manual dpm mode only.\n");
 903                return ret;
 904        }
 905
 906        mutex_lock(&hwmgr->smu_lock);
 907        ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
 908        mutex_unlock(&hwmgr->smu_lock);
 909        return ret;
 910}
 911
 912static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
 913{
 914        struct pp_hwmgr *hwmgr = handle;
 915
 916        if (!hwmgr || !hwmgr->pm_en)
 917                return -EINVAL;
 918
 919        if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {
 920                pr_info_ratelimited("%s was not implemented.\n", __func__);
 921                return -EINVAL;
 922        }
 923
 924        return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
 925}
 926
 927static int pp_dpm_switch_power_profile(void *handle,
 928                enum PP_SMC_POWER_PROFILE type, bool en)
 929{
 930        struct pp_hwmgr *hwmgr = handle;
 931        long workload;
 932        uint32_t index;
 933
 934        if (!hwmgr || !hwmgr->pm_en)
 935                return -EINVAL;
 936
 937        if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
 938                pr_info_ratelimited("%s was not implemented.\n", __func__);
 939                return -EINVAL;
 940        }
 941
 942        if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
 943                return -EINVAL;
 944
 945        mutex_lock(&hwmgr->smu_lock);
 946
 947        if (!en) {
 948                hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
 949                index = fls(hwmgr->workload_mask);
 950                index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
 951                workload = hwmgr->workload_setting[index];
 952        } else {
 953                hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
 954                index = fls(hwmgr->workload_mask);
 955                index = index <= Workload_Policy_Max ? index - 1 : 0;
 956                workload = hwmgr->workload_setting[index];
 957        }
 958
 959        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
 960                hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
 961        mutex_unlock(&hwmgr->smu_lock);
 962
 963        return 0;
 964}
 965
 966static int pp_set_power_limit(void *handle, uint32_t limit)
 967{
 968        struct pp_hwmgr *hwmgr = handle;
 969        uint32_t max_power_limit;
 970
 971        if (!hwmgr || !hwmgr->pm_en)
 972                return -EINVAL;
 973
 974        if (hwmgr->hwmgr_func->set_power_limit == NULL) {
 975                pr_info_ratelimited("%s was not implemented.\n", __func__);
 976                return -EINVAL;
 977        }
 978
 979        if (limit == 0)
 980                limit = hwmgr->default_power_limit;
 981
 982        max_power_limit = hwmgr->default_power_limit;
 983        if (hwmgr->od_enabled) {
 984                max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
 985                max_power_limit /= 100;
 986        }
 987
 988        if (limit > max_power_limit)
 989                return -EINVAL;
 990
 991        mutex_lock(&hwmgr->smu_lock);
 992        hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
 993        hwmgr->power_limit = limit;
 994        mutex_unlock(&hwmgr->smu_lock);
 995        return 0;
 996}
 997
 998static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
 999{
1000        struct pp_hwmgr *hwmgr = handle;
1001
1002        if (!hwmgr || !hwmgr->pm_en ||!limit)
1003                return -EINVAL;
1004
1005        mutex_lock(&hwmgr->smu_lock);
1006
1007        if (default_limit) {
1008                *limit = hwmgr->default_power_limit;
1009                if (hwmgr->od_enabled) {
1010                        *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
1011                        *limit /= 100;
1012                }
1013        }
1014        else
1015                *limit = hwmgr->power_limit;
1016
1017        mutex_unlock(&hwmgr->smu_lock);
1018
1019        return 0;
1020}
1021
1022static int pp_display_configuration_change(void *handle,
1023        const struct amd_pp_display_configuration *display_config)
1024{
1025        struct pp_hwmgr *hwmgr = handle;
1026
1027        if (!hwmgr || !hwmgr->pm_en)
1028                return -EINVAL;
1029
1030        mutex_lock(&hwmgr->smu_lock);
1031        phm_store_dal_configuration_data(hwmgr, display_config);
1032        mutex_unlock(&hwmgr->smu_lock);
1033        return 0;
1034}
1035
1036static int pp_get_display_power_level(void *handle,
1037                struct amd_pp_simple_clock_info *output)
1038{
1039        struct pp_hwmgr *hwmgr = handle;
1040        int ret = 0;
1041
1042        if (!hwmgr || !hwmgr->pm_en ||!output)
1043                return -EINVAL;
1044
1045        mutex_lock(&hwmgr->smu_lock);
1046        ret = phm_get_dal_power_level(hwmgr, output);
1047        mutex_unlock(&hwmgr->smu_lock);
1048        return ret;
1049}
1050
1051static int pp_get_current_clocks(void *handle,
1052                struct amd_pp_clock_info *clocks)
1053{
1054        struct amd_pp_simple_clock_info simple_clocks = { 0 };
1055        struct pp_clock_info hw_clocks;
1056        struct pp_hwmgr *hwmgr = handle;
1057        int ret = 0;
1058
1059        if (!hwmgr || !hwmgr->pm_en)
1060                return -EINVAL;
1061
1062        mutex_lock(&hwmgr->smu_lock);
1063
1064        phm_get_dal_power_level(hwmgr, &simple_clocks);
1065
1066        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1067                                        PHM_PlatformCaps_PowerContainment))
1068                ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1069                                        &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1070        else
1071                ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1072                                        &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1073
1074        if (ret) {
1075                pr_debug("Error in phm_get_clock_info \n");
1076                mutex_unlock(&hwmgr->smu_lock);
1077                return -EINVAL;
1078        }
1079
1080        clocks->min_engine_clock = hw_clocks.min_eng_clk;
1081        clocks->max_engine_clock = hw_clocks.max_eng_clk;
1082        clocks->min_memory_clock = hw_clocks.min_mem_clk;
1083        clocks->max_memory_clock = hw_clocks.max_mem_clk;
1084        clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1085        clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1086
1087        clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1088        clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1089
1090        if (simple_clocks.level == 0)
1091                clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;
1092        else
1093                clocks->max_clocks_state = simple_clocks.level;
1094
1095        if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1096                clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1097                clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1098        }
1099        mutex_unlock(&hwmgr->smu_lock);
1100        return 0;
1101}
1102
1103static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1104{
1105        struct pp_hwmgr *hwmgr = handle;
1106        int ret = 0;
1107
1108        if (!hwmgr || !hwmgr->pm_en)
1109                return -EINVAL;
1110
1111        if (clocks == NULL)
1112                return -EINVAL;
1113
1114        mutex_lock(&hwmgr->smu_lock);
1115        ret = phm_get_clock_by_type(hwmgr, type, clocks);
1116        mutex_unlock(&hwmgr->smu_lock);
1117        return ret;
1118}
1119
1120static int pp_get_clock_by_type_with_latency(void *handle,
1121                enum amd_pp_clock_type type,
1122                struct pp_clock_levels_with_latency *clocks)
1123{
1124        struct pp_hwmgr *hwmgr = handle;
1125        int ret = 0;
1126
1127        if (!hwmgr || !hwmgr->pm_en ||!clocks)
1128                return -EINVAL;
1129
1130        mutex_lock(&hwmgr->smu_lock);
1131        ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1132        mutex_unlock(&hwmgr->smu_lock);
1133        return ret;
1134}
1135
1136static int pp_get_clock_by_type_with_voltage(void *handle,
1137                enum amd_pp_clock_type type,
1138                struct pp_clock_levels_with_voltage *clocks)
1139{
1140        struct pp_hwmgr *hwmgr = handle;
1141        int ret = 0;
1142
1143        if (!hwmgr || !hwmgr->pm_en ||!clocks)
1144                return -EINVAL;
1145
1146        mutex_lock(&hwmgr->smu_lock);
1147
1148        ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1149
1150        mutex_unlock(&hwmgr->smu_lock);
1151        return ret;
1152}
1153
1154static int pp_set_watermarks_for_clocks_ranges(void *handle,
1155                void *clock_ranges)
1156{
1157        struct pp_hwmgr *hwmgr = handle;
1158        int ret = 0;
1159
1160        if (!hwmgr || !hwmgr->pm_en || !clock_ranges)
1161                return -EINVAL;
1162
1163        mutex_lock(&hwmgr->smu_lock);
1164        ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1165                        clock_ranges);
1166        mutex_unlock(&hwmgr->smu_lock);
1167
1168        return ret;
1169}
1170
1171static int pp_display_clock_voltage_request(void *handle,
1172                struct pp_display_clock_request *clock)
1173{
1174        struct pp_hwmgr *hwmgr = handle;
1175        int ret = 0;
1176
1177        if (!hwmgr || !hwmgr->pm_en ||!clock)
1178                return -EINVAL;
1179
1180        mutex_lock(&hwmgr->smu_lock);
1181        ret = phm_display_clock_voltage_request(hwmgr, clock);
1182        mutex_unlock(&hwmgr->smu_lock);
1183
1184        return ret;
1185}
1186
1187static int pp_get_display_mode_validation_clocks(void *handle,
1188                struct amd_pp_simple_clock_info *clocks)
1189{
1190        struct pp_hwmgr *hwmgr = handle;
1191        int ret = 0;
1192
1193        if (!hwmgr || !hwmgr->pm_en ||!clocks)
1194                return -EINVAL;
1195
1196        clocks->level = PP_DAL_POWERLEVEL_7;
1197
1198        mutex_lock(&hwmgr->smu_lock);
1199
1200        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1201                ret = phm_get_max_high_clocks(hwmgr, clocks);
1202
1203        mutex_unlock(&hwmgr->smu_lock);
1204        return ret;
1205}
1206
1207static int pp_dpm_powergate_mmhub(void *handle)
1208{
1209        struct pp_hwmgr *hwmgr = handle;
1210
1211        if (!hwmgr || !hwmgr->pm_en)
1212                return -EINVAL;
1213
1214        if (hwmgr->hwmgr_func->powergate_mmhub == NULL) {
1215                pr_info_ratelimited("%s was not implemented.\n", __func__);
1216                return 0;
1217        }
1218
1219        return hwmgr->hwmgr_func->powergate_mmhub(hwmgr);
1220}
1221
1222static int pp_dpm_powergate_gfx(void *handle, bool gate)
1223{
1224        struct pp_hwmgr *hwmgr = handle;
1225
1226        if (!hwmgr || !hwmgr->pm_en)
1227                return 0;
1228
1229        if (hwmgr->hwmgr_func->powergate_gfx == NULL) {
1230                pr_info_ratelimited("%s was not implemented.\n", __func__);
1231                return 0;
1232        }
1233
1234        return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate);
1235}
1236
1237static void pp_dpm_powergate_acp(void *handle, bool gate)
1238{
1239        struct pp_hwmgr *hwmgr = handle;
1240
1241        if (!hwmgr || !hwmgr->pm_en)
1242                return;
1243
1244        if (hwmgr->hwmgr_func->powergate_acp == NULL) {
1245                pr_info_ratelimited("%s was not implemented.\n", __func__);
1246                return;
1247        }
1248
1249        hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);
1250}
1251
1252static void pp_dpm_powergate_sdma(void *handle, bool gate)
1253{
1254        struct pp_hwmgr *hwmgr = handle;
1255
1256        if (!hwmgr)
1257                return;
1258
1259        if (hwmgr->hwmgr_func->powergate_sdma == NULL) {
1260                pr_info_ratelimited("%s was not implemented.\n", __func__);
1261                return;
1262        }
1263
1264        hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);
1265}
1266
1267static int pp_set_powergating_by_smu(void *handle,
1268                                uint32_t block_type, bool gate)
1269{
1270        int ret = 0;
1271
1272        switch (block_type) {
1273        case AMD_IP_BLOCK_TYPE_UVD:
1274        case AMD_IP_BLOCK_TYPE_VCN:
1275                pp_dpm_powergate_uvd(handle, gate);
1276                break;
1277        case AMD_IP_BLOCK_TYPE_VCE:
1278                pp_dpm_powergate_vce(handle, gate);
1279                break;
1280        case AMD_IP_BLOCK_TYPE_GMC:
1281                pp_dpm_powergate_mmhub(handle);
1282                break;
1283        case AMD_IP_BLOCK_TYPE_GFX:
1284                ret = pp_dpm_powergate_gfx(handle, gate);
1285                break;
1286        case AMD_IP_BLOCK_TYPE_ACP:
1287                pp_dpm_powergate_acp(handle, gate);
1288                break;
1289        case AMD_IP_BLOCK_TYPE_SDMA:
1290                pp_dpm_powergate_sdma(handle, gate);
1291                break;
1292        default:
1293                break;
1294        }
1295        return ret;
1296}
1297
1298static int pp_notify_smu_enable_pwe(void *handle)
1299{
1300        struct pp_hwmgr *hwmgr = handle;
1301
1302        if (!hwmgr || !hwmgr->pm_en)
1303                return -EINVAL;
1304
1305        if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) {
1306                pr_info_ratelimited("%s was not implemented.\n", __func__);
1307                return -EINVAL;;
1308        }
1309
1310        mutex_lock(&hwmgr->smu_lock);
1311        hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);
1312        mutex_unlock(&hwmgr->smu_lock);
1313
1314        return 0;
1315}
1316
1317static int pp_enable_mgpu_fan_boost(void *handle)
1318{
1319        struct pp_hwmgr *hwmgr = handle;
1320
1321        if (!hwmgr)
1322                return -EINVAL;
1323
1324        if (!hwmgr->pm_en ||
1325             hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL)
1326                return 0;
1327
1328        mutex_lock(&hwmgr->smu_lock);
1329        hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);
1330        mutex_unlock(&hwmgr->smu_lock);
1331
1332        return 0;
1333}
1334
1335static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock)
1336{
1337        struct pp_hwmgr *hwmgr = handle;
1338
1339        if (!hwmgr || !hwmgr->pm_en)
1340                return -EINVAL;
1341
1342        if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) {
1343                pr_debug("%s was not implemented.\n", __func__);
1344                return -EINVAL;;
1345        }
1346
1347        mutex_lock(&hwmgr->smu_lock);
1348        hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock);
1349        mutex_unlock(&hwmgr->smu_lock);
1350
1351        return 0;
1352}
1353
1354static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock)
1355{
1356        struct pp_hwmgr *hwmgr = handle;
1357
1358        if (!hwmgr || !hwmgr->pm_en)
1359                return -EINVAL;
1360
1361        if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) {
1362                pr_debug("%s was not implemented.\n", __func__);
1363                return -EINVAL;;
1364        }
1365
1366        mutex_lock(&hwmgr->smu_lock);
1367        hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock);
1368        mutex_unlock(&hwmgr->smu_lock);
1369
1370        return 0;
1371}
1372
1373static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock)
1374{
1375        struct pp_hwmgr *hwmgr = handle;
1376
1377        if (!hwmgr || !hwmgr->pm_en)
1378                return -EINVAL;
1379
1380        if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) {
1381                pr_debug("%s was not implemented.\n", __func__);
1382                return -EINVAL;;
1383        }
1384
1385        mutex_lock(&hwmgr->smu_lock);
1386        hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock);
1387        mutex_unlock(&hwmgr->smu_lock);
1388
1389        return 0;
1390}
1391
1392static int pp_set_active_display_count(void *handle, uint32_t count)
1393{
1394        struct pp_hwmgr *hwmgr = handle;
1395        int ret = 0;
1396
1397        if (!hwmgr || !hwmgr->pm_en)
1398                return -EINVAL;
1399
1400        mutex_lock(&hwmgr->smu_lock);
1401        ret = phm_set_active_display_count(hwmgr, count);
1402        mutex_unlock(&hwmgr->smu_lock);
1403
1404        return ret;
1405}
1406
1407static int pp_get_asic_baco_capability(void *handle, bool *cap)
1408{
1409        struct pp_hwmgr *hwmgr = handle;
1410
1411        if (!hwmgr)
1412                return -EINVAL;
1413
1414        if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_capability)
1415                return 0;
1416
1417        mutex_lock(&hwmgr->smu_lock);
1418        hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap);
1419        mutex_unlock(&hwmgr->smu_lock);
1420
1421        return 0;
1422}
1423
1424static int pp_get_asic_baco_state(void *handle, int *state)
1425{
1426        struct pp_hwmgr *hwmgr = handle;
1427
1428        if (!hwmgr)
1429                return -EINVAL;
1430
1431        if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)
1432                return 0;
1433
1434        mutex_lock(&hwmgr->smu_lock);
1435        hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state);
1436        mutex_unlock(&hwmgr->smu_lock);
1437
1438        return 0;
1439}
1440
1441static int pp_set_asic_baco_state(void *handle, int state)
1442{
1443        struct pp_hwmgr *hwmgr = handle;
1444
1445        if (!hwmgr)
1446                return -EINVAL;
1447
1448        if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_asic_baco_state)
1449                return 0;
1450
1451        mutex_lock(&hwmgr->smu_lock);
1452        hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state);
1453        mutex_unlock(&hwmgr->smu_lock);
1454
1455        return 0;
1456}
1457
1458static int pp_get_ppfeature_status(void *handle, char *buf)
1459{
1460        struct pp_hwmgr *hwmgr = handle;
1461        int ret = 0;
1462
1463        if (!hwmgr || !hwmgr->pm_en || !buf)
1464                return -EINVAL;
1465
1466        if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {
1467                pr_info_ratelimited("%s was not implemented.\n", __func__);
1468                return -EINVAL;
1469        }
1470
1471        mutex_lock(&hwmgr->smu_lock);
1472        ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);
1473        mutex_unlock(&hwmgr->smu_lock);
1474
1475        return ret;
1476}
1477
1478static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)
1479{
1480        struct pp_hwmgr *hwmgr = handle;
1481        int ret = 0;
1482
1483        if (!hwmgr || !hwmgr->pm_en)
1484                return -EINVAL;
1485
1486        if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {
1487                pr_info_ratelimited("%s was not implemented.\n", __func__);
1488                return -EINVAL;
1489        }
1490
1491        mutex_lock(&hwmgr->smu_lock);
1492        ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);
1493        mutex_unlock(&hwmgr->smu_lock);
1494
1495        return ret;
1496}
1497
1498static const struct amd_pm_funcs pp_dpm_funcs = {
1499        .load_firmware = pp_dpm_load_fw,
1500        .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1501        .force_performance_level = pp_dpm_force_performance_level,
1502        .get_performance_level = pp_dpm_get_performance_level,
1503        .get_current_power_state = pp_dpm_get_current_power_state,
1504        .dispatch_tasks = pp_dpm_dispatch_tasks,
1505        .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1506        .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1507        .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1508        .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
1509        .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1510        .set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,
1511        .get_pp_num_states = pp_dpm_get_pp_num_states,
1512        .get_pp_table = pp_dpm_get_pp_table,
1513        .set_pp_table = pp_dpm_set_pp_table,
1514        .force_clock_level = pp_dpm_force_clock_level,
1515        .print_clock_levels = pp_dpm_print_clock_levels,
1516        .get_sclk_od = pp_dpm_get_sclk_od,
1517        .set_sclk_od = pp_dpm_set_sclk_od,
1518        .get_mclk_od = pp_dpm_get_mclk_od,
1519        .set_mclk_od = pp_dpm_set_mclk_od,
1520        .read_sensor = pp_dpm_read_sensor,
1521        .get_vce_clock_state = pp_dpm_get_vce_clock_state,
1522        .switch_power_profile = pp_dpm_switch_power_profile,
1523        .set_clockgating_by_smu = pp_set_clockgating_by_smu,
1524        .set_powergating_by_smu = pp_set_powergating_by_smu,
1525        .get_power_profile_mode = pp_get_power_profile_mode,
1526        .set_power_profile_mode = pp_set_power_profile_mode,
1527        .odn_edit_dpm_table = pp_odn_edit_dpm_table,
1528        .set_power_limit = pp_set_power_limit,
1529        .get_power_limit = pp_get_power_limit,
1530/* export to DC */
1531        .get_sclk = pp_dpm_get_sclk,
1532        .get_mclk = pp_dpm_get_mclk,
1533        .display_configuration_change = pp_display_configuration_change,
1534        .get_display_power_level = pp_get_display_power_level,
1535        .get_current_clocks = pp_get_current_clocks,
1536        .get_clock_by_type = pp_get_clock_by_type,
1537        .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
1538        .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
1539        .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
1540        .display_clock_voltage_request = pp_display_clock_voltage_request,
1541        .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
1542        .notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
1543        .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,
1544        .set_active_display_count = pp_set_active_display_count,
1545        .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk,
1546        .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq,
1547        .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq,
1548        .get_asic_baco_capability = pp_get_asic_baco_capability,
1549        .get_asic_baco_state = pp_get_asic_baco_state,
1550        .set_asic_baco_state = pp_set_asic_baco_state,
1551        .get_ppfeature_status = pp_get_ppfeature_status,
1552        .set_ppfeature_status = pp_set_ppfeature_status,
1553};
1554