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 "amd_shared.h"
  29#include "amd_powerplay.h"
  30#include "pp_instance.h"
  31#include "power_state.h"
  32#include "eventmanager.h"
  33
  34
  35static inline int pp_check(struct pp_instance *handle)
  36{
  37        if (handle == NULL || handle->pp_valid != PP_VALID)
  38                return -EINVAL;
  39
  40        if (handle->smu_mgr == NULL || handle->smu_mgr->smumgr_funcs == NULL)
  41                return -EINVAL;
  42
  43        if (handle->pm_en == 0)
  44                return PP_DPM_DISABLED;
  45
  46        if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL
  47                || handle->eventmgr == NULL)
  48                return PP_DPM_DISABLED;
  49
  50        return 0;
  51}
  52
  53static int pp_early_init(void *handle)
  54{
  55        int ret;
  56        struct pp_instance *pp_handle = (struct pp_instance *)handle;
  57
  58        ret = smum_early_init(pp_handle);
  59        if (ret)
  60                return ret;
  61
  62        if ((pp_handle->pm_en == 0)
  63                || cgs_is_virtualization_enabled(pp_handle->device))
  64                return PP_DPM_DISABLED;
  65
  66        ret = hwmgr_early_init(pp_handle);
  67        if (ret) {
  68                pp_handle->pm_en = 0;
  69                return PP_DPM_DISABLED;
  70        }
  71
  72        ret = eventmgr_early_init(pp_handle);
  73        if (ret) {
  74                kfree(pp_handle->hwmgr);
  75                pp_handle->hwmgr = NULL;
  76                pp_handle->pm_en = 0;
  77                return PP_DPM_DISABLED;
  78        }
  79
  80        return 0;
  81}
  82
  83static int pp_sw_init(void *handle)
  84{
  85        struct pp_smumgr *smumgr;
  86        int ret = 0;
  87        struct pp_instance *pp_handle = (struct pp_instance *)handle;
  88
  89        ret = pp_check(pp_handle);
  90
  91        if (ret == 0 || ret == PP_DPM_DISABLED) {
  92                smumgr = pp_handle->smu_mgr;
  93
  94                if (smumgr->smumgr_funcs->smu_init == NULL)
  95                        return -EINVAL;
  96
  97                ret = smumgr->smumgr_funcs->smu_init(smumgr);
  98
  99                pr_info("amdgpu: powerplay sw initialized\n");
 100        }
 101        return ret;
 102}
 103
 104static int pp_sw_fini(void *handle)
 105{
 106        struct pp_smumgr *smumgr;
 107        int ret = 0;
 108        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 109
 110        ret = pp_check(pp_handle);
 111        if (ret == 0 || ret == PP_DPM_DISABLED) {
 112                smumgr = pp_handle->smu_mgr;
 113
 114                if (smumgr->smumgr_funcs->smu_fini == NULL)
 115                        return -EINVAL;
 116
 117                ret = smumgr->smumgr_funcs->smu_fini(smumgr);
 118        }
 119        return ret;
 120}
 121
 122static int pp_hw_init(void *handle)
 123{
 124        struct pp_smumgr *smumgr;
 125        struct pp_eventmgr *eventmgr;
 126        int ret = 0;
 127        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 128
 129        ret = pp_check(pp_handle);
 130
 131        if (ret == 0 || ret == PP_DPM_DISABLED) {
 132                smumgr = pp_handle->smu_mgr;
 133
 134                if (smumgr->smumgr_funcs->start_smu == NULL)
 135                        return -EINVAL;
 136
 137                if(smumgr->smumgr_funcs->start_smu(smumgr)) {
 138                        pr_err("smc start failed\n");
 139                        smumgr->smumgr_funcs->smu_fini(smumgr);
 140                        return -EINVAL;;
 141                }
 142                if (ret == PP_DPM_DISABLED)
 143                        return PP_DPM_DISABLED;
 144        }
 145
 146        ret = hwmgr_hw_init(pp_handle);
 147        if (ret)
 148                goto err;
 149
 150        eventmgr = pp_handle->eventmgr;
 151        if (eventmgr->pp_eventmgr_init == NULL ||
 152                eventmgr->pp_eventmgr_init(eventmgr))
 153                goto err;
 154
 155        return 0;
 156err:
 157        pp_handle->pm_en = 0;
 158        kfree(pp_handle->eventmgr);
 159        kfree(pp_handle->hwmgr);
 160        pp_handle->hwmgr = NULL;
 161        pp_handle->eventmgr = NULL;
 162        return PP_DPM_DISABLED;
 163}
 164
 165static int pp_hw_fini(void *handle)
 166{
 167        struct pp_eventmgr *eventmgr;
 168        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 169        int ret = 0;
 170
 171        ret = pp_check(pp_handle);
 172
 173        if (ret == 0) {
 174                eventmgr = pp_handle->eventmgr;
 175
 176                if (eventmgr->pp_eventmgr_fini != NULL)
 177                        eventmgr->pp_eventmgr_fini(eventmgr);
 178
 179                hwmgr_hw_fini(pp_handle);
 180        }
 181        return 0;
 182}
 183
 184static bool pp_is_idle(void *handle)
 185{
 186        return false;
 187}
 188
 189static int pp_wait_for_idle(void *handle)
 190{
 191        return 0;
 192}
 193
 194static int pp_sw_reset(void *handle)
 195{
 196        return 0;
 197}
 198
 199
 200int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
 201{
 202        struct pp_hwmgr  *hwmgr;
 203        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 204        int ret = 0;
 205
 206        ret = pp_check(pp_handle);
 207
 208        if (ret != 0)
 209                return ret;
 210
 211        hwmgr = pp_handle->hwmgr;
 212
 213        if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
 214                pr_info("%s was not implemented.\n", __func__);
 215                return 0;
 216        }
 217
 218        return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
 219}
 220
 221static int pp_set_powergating_state(void *handle,
 222                                    enum amd_powergating_state state)
 223{
 224        struct pp_hwmgr  *hwmgr;
 225        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 226        int ret = 0;
 227
 228        ret = pp_check(pp_handle);
 229
 230        if (ret != 0)
 231                return ret;
 232
 233        hwmgr = pp_handle->hwmgr;
 234
 235        if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
 236                pr_info("%s was not implemented.\n", __func__);
 237                return 0;
 238        }
 239
 240        /* Enable/disable GFX per cu powergating through SMU */
 241        return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
 242                        state == AMD_PG_STATE_GATE);
 243}
 244
 245static int pp_suspend(void *handle)
 246{
 247        struct pp_eventmgr *eventmgr;
 248        struct pem_event_data event_data = { {0} };
 249        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 250        int ret = 0;
 251
 252        ret = pp_check(pp_handle);
 253
 254        if (ret == PP_DPM_DISABLED)
 255                return 0;
 256        else if (ret != 0)
 257                return ret;
 258
 259        eventmgr = pp_handle->eventmgr;
 260        pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
 261
 262        return 0;
 263}
 264
 265static int pp_resume(void *handle)
 266{
 267        struct pp_eventmgr *eventmgr;
 268        struct pem_event_data event_data = { {0} };
 269        struct pp_smumgr *smumgr;
 270        int ret, ret1;
 271        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 272
 273        ret1 = pp_check(pp_handle);
 274
 275        if (ret1 != 0 && ret1 != PP_DPM_DISABLED)
 276                return ret1;
 277
 278        smumgr = pp_handle->smu_mgr;
 279
 280        if (smumgr->smumgr_funcs->start_smu == NULL)
 281                return -EINVAL;
 282
 283        ret = smumgr->smumgr_funcs->start_smu(smumgr);
 284        if (ret) {
 285                pr_err("smc start failed\n");
 286                smumgr->smumgr_funcs->smu_fini(smumgr);
 287                return ret;
 288        }
 289
 290        if (ret1 == PP_DPM_DISABLED)
 291                return 0;
 292
 293        eventmgr = pp_handle->eventmgr;
 294
 295        pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
 296
 297        return 0;
 298}
 299
 300const struct amd_ip_funcs pp_ip_funcs = {
 301        .name = "powerplay",
 302        .early_init = pp_early_init,
 303        .late_init = NULL,
 304        .sw_init = pp_sw_init,
 305        .sw_fini = pp_sw_fini,
 306        .hw_init = pp_hw_init,
 307        .hw_fini = pp_hw_fini,
 308        .suspend = pp_suspend,
 309        .resume = pp_resume,
 310        .is_idle = pp_is_idle,
 311        .wait_for_idle = pp_wait_for_idle,
 312        .soft_reset = pp_sw_reset,
 313        .set_clockgating_state = NULL,
 314        .set_powergating_state = pp_set_powergating_state,
 315};
 316
 317static int pp_dpm_load_fw(void *handle)
 318{
 319        return 0;
 320}
 321
 322static int pp_dpm_fw_loading_complete(void *handle)
 323{
 324        return 0;
 325}
 326
 327static int pp_dpm_force_performance_level(void *handle,
 328                                        enum amd_dpm_forced_level level)
 329{
 330        struct pp_hwmgr  *hwmgr;
 331        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 332        int ret = 0;
 333
 334        ret = pp_check(pp_handle);
 335
 336        if (ret != 0)
 337                return ret;
 338
 339        hwmgr = pp_handle->hwmgr;
 340
 341        if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
 342                pr_info("%s was not implemented.\n", __func__);
 343                return 0;
 344        }
 345
 346        mutex_lock(&pp_handle->pp_lock);
 347        hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
 348        mutex_unlock(&pp_handle->pp_lock);
 349        return 0;
 350}
 351
 352static enum amd_dpm_forced_level pp_dpm_get_performance_level(
 353                                                                void *handle)
 354{
 355        struct pp_hwmgr  *hwmgr;
 356        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 357        int ret = 0;
 358        enum amd_dpm_forced_level level;
 359
 360        ret = pp_check(pp_handle);
 361
 362        if (ret != 0)
 363                return ret;
 364
 365        hwmgr = pp_handle->hwmgr;
 366        mutex_lock(&pp_handle->pp_lock);
 367        level = hwmgr->dpm_level;
 368        mutex_unlock(&pp_handle->pp_lock);
 369        return level;
 370}
 371
 372static int pp_dpm_get_sclk(void *handle, bool low)
 373{
 374        struct pp_hwmgr  *hwmgr;
 375        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 376        int ret = 0;
 377
 378        ret = pp_check(pp_handle);
 379
 380        if (ret != 0)
 381                return ret;
 382
 383        hwmgr = pp_handle->hwmgr;
 384
 385        if (hwmgr->hwmgr_func->get_sclk == NULL) {
 386                pr_info("%s was not implemented.\n", __func__);
 387                return 0;
 388        }
 389        mutex_lock(&pp_handle->pp_lock);
 390        ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
 391        mutex_unlock(&pp_handle->pp_lock);
 392        return ret;
 393}
 394
 395static int pp_dpm_get_mclk(void *handle, bool low)
 396{
 397        struct pp_hwmgr  *hwmgr;
 398        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 399        int ret = 0;
 400
 401        ret = pp_check(pp_handle);
 402
 403        if (ret != 0)
 404                return ret;
 405
 406        hwmgr = pp_handle->hwmgr;
 407
 408        if (hwmgr->hwmgr_func->get_mclk == NULL) {
 409                pr_info("%s was not implemented.\n", __func__);
 410                return 0;
 411        }
 412        mutex_lock(&pp_handle->pp_lock);
 413        ret = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
 414        mutex_unlock(&pp_handle->pp_lock);
 415        return ret;
 416}
 417
 418static int pp_dpm_powergate_vce(void *handle, bool gate)
 419{
 420        struct pp_hwmgr  *hwmgr;
 421        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 422        int ret = 0;
 423
 424        ret = pp_check(pp_handle);
 425
 426        if (ret != 0)
 427                return ret;
 428
 429        hwmgr = pp_handle->hwmgr;
 430
 431        if (hwmgr->hwmgr_func->powergate_vce == NULL) {
 432                pr_info("%s was not implemented.\n", __func__);
 433                return 0;
 434        }
 435        mutex_lock(&pp_handle->pp_lock);
 436        ret = hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
 437        mutex_unlock(&pp_handle->pp_lock);
 438        return ret;
 439}
 440
 441static int pp_dpm_powergate_uvd(void *handle, bool gate)
 442{
 443        struct pp_hwmgr  *hwmgr;
 444        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 445        int ret = 0;
 446
 447        ret = pp_check(pp_handle);
 448
 449        if (ret != 0)
 450                return ret;
 451
 452        hwmgr = pp_handle->hwmgr;
 453
 454        if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
 455                pr_info("%s was not implemented.\n", __func__);
 456                return 0;
 457        }
 458        mutex_lock(&pp_handle->pp_lock);
 459        ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
 460        mutex_unlock(&pp_handle->pp_lock);
 461        return ret;
 462}
 463
 464static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
 465{
 466        switch (state) {
 467        case POWER_STATE_TYPE_BATTERY:
 468                return PP_StateUILabel_Battery;
 469        case POWER_STATE_TYPE_BALANCED:
 470                return PP_StateUILabel_Balanced;
 471        case POWER_STATE_TYPE_PERFORMANCE:
 472                return PP_StateUILabel_Performance;
 473        default:
 474                return PP_StateUILabel_None;
 475        }
 476}
 477
 478static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
 479                void *input, void *output)
 480{
 481        int ret = 0;
 482        struct pem_event_data data = { {0} };
 483        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 484
 485        ret = pp_check(pp_handle);
 486
 487        if (ret != 0)
 488                return ret;
 489        mutex_lock(&pp_handle->pp_lock);
 490        switch (event_id) {
 491        case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
 492                ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
 493                break;
 494        case AMD_PP_EVENT_ENABLE_USER_STATE:
 495        {
 496                enum amd_pm_state_type  ps;
 497
 498                if (input == NULL) {
 499                        ret = -EINVAL;
 500                        break;
 501                }
 502                ps = *(unsigned long *)input;
 503
 504                data.requested_ui_label = power_state_convert(ps);
 505                ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
 506                break;
 507        }
 508        case AMD_PP_EVENT_COMPLETE_INIT:
 509                ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
 510                break;
 511        case AMD_PP_EVENT_READJUST_POWER_STATE:
 512                ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
 513                break;
 514        default:
 515                break;
 516        }
 517        mutex_unlock(&pp_handle->pp_lock);
 518        return ret;
 519}
 520
 521static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
 522{
 523        struct pp_hwmgr *hwmgr;
 524        struct pp_power_state *state;
 525        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 526        int ret = 0;
 527        enum amd_pm_state_type pm_type;
 528
 529        ret = pp_check(pp_handle);
 530
 531        if (ret != 0)
 532                return ret;
 533
 534        hwmgr = pp_handle->hwmgr;
 535
 536        if (hwmgr->current_ps == NULL)
 537                return -EINVAL;
 538
 539        mutex_lock(&pp_handle->pp_lock);
 540
 541        state = hwmgr->current_ps;
 542
 543        switch (state->classification.ui_label) {
 544        case PP_StateUILabel_Battery:
 545                pm_type = POWER_STATE_TYPE_BATTERY;
 546                break;
 547        case PP_StateUILabel_Balanced:
 548                pm_type = POWER_STATE_TYPE_BALANCED;
 549                break;
 550        case PP_StateUILabel_Performance:
 551                pm_type = POWER_STATE_TYPE_PERFORMANCE;
 552                break;
 553        default:
 554                if (state->classification.flags & PP_StateClassificationFlag_Boot)
 555                        pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
 556                else
 557                        pm_type = POWER_STATE_TYPE_DEFAULT;
 558                break;
 559        }
 560        mutex_unlock(&pp_handle->pp_lock);
 561
 562        return pm_type;
 563}
 564
 565static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
 566{
 567        struct pp_hwmgr  *hwmgr;
 568        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 569        int ret = 0;
 570
 571        ret = pp_check(pp_handle);
 572
 573        if (ret != 0)
 574                return ret;
 575
 576        hwmgr = pp_handle->hwmgr;
 577
 578        if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
 579                pr_info("%s was not implemented.\n", __func__);
 580                return 0;
 581        }
 582        mutex_lock(&pp_handle->pp_lock);
 583        ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
 584        mutex_unlock(&pp_handle->pp_lock);
 585        return ret;
 586}
 587
 588static int pp_dpm_get_fan_control_mode(void *handle)
 589{
 590        struct pp_hwmgr  *hwmgr;
 591        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 592        int ret = 0;
 593
 594        ret = pp_check(pp_handle);
 595
 596        if (ret != 0)
 597                return ret;
 598
 599        hwmgr = pp_handle->hwmgr;
 600
 601        if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
 602                pr_info("%s was not implemented.\n", __func__);
 603                return 0;
 604        }
 605        mutex_lock(&pp_handle->pp_lock);
 606        ret = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
 607        mutex_unlock(&pp_handle->pp_lock);
 608        return ret;
 609}
 610
 611static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
 612{
 613        struct pp_hwmgr  *hwmgr;
 614        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 615        int ret = 0;
 616
 617        ret = pp_check(pp_handle);
 618
 619        if (ret != 0)
 620                return ret;
 621
 622        hwmgr = pp_handle->hwmgr;
 623
 624        if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
 625                pr_info("%s was not implemented.\n", __func__);
 626                return 0;
 627        }
 628        mutex_lock(&pp_handle->pp_lock);
 629        ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
 630        mutex_unlock(&pp_handle->pp_lock);
 631        return ret;
 632}
 633
 634static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
 635{
 636        struct pp_hwmgr  *hwmgr;
 637        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 638        int ret = 0;
 639
 640        ret = pp_check(pp_handle);
 641
 642        if (ret != 0)
 643                return ret;
 644
 645        hwmgr = pp_handle->hwmgr;
 646
 647        if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
 648                pr_info("%s was not implemented.\n", __func__);
 649                return 0;
 650        }
 651
 652        mutex_lock(&pp_handle->pp_lock);
 653        ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
 654        mutex_unlock(&pp_handle->pp_lock);
 655        return ret;
 656}
 657
 658static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
 659{
 660        struct pp_hwmgr *hwmgr;
 661        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 662        int ret = 0;
 663
 664        ret = pp_check(pp_handle);
 665
 666        if (ret != 0)
 667                return ret;
 668
 669        hwmgr = pp_handle->hwmgr;
 670
 671        if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
 672                return -EINVAL;
 673
 674        mutex_lock(&pp_handle->pp_lock);
 675        ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
 676        mutex_unlock(&pp_handle->pp_lock);
 677        return ret;
 678}
 679
 680static int pp_dpm_get_temperature(void *handle)
 681{
 682        struct pp_hwmgr  *hwmgr;
 683        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 684        int ret = 0;
 685
 686        ret = pp_check(pp_handle);
 687
 688        if (ret != 0)
 689                return ret;
 690
 691        hwmgr = pp_handle->hwmgr;
 692
 693        if (hwmgr->hwmgr_func->get_temperature == NULL) {
 694                pr_info("%s was not implemented.\n", __func__);
 695                return 0;
 696        }
 697        mutex_lock(&pp_handle->pp_lock);
 698        ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
 699        mutex_unlock(&pp_handle->pp_lock);
 700        return ret;
 701}
 702
 703static int pp_dpm_get_pp_num_states(void *handle,
 704                struct pp_states_info *data)
 705{
 706        struct pp_hwmgr *hwmgr;
 707        int i;
 708        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 709        int ret = 0;
 710
 711        ret = pp_check(pp_handle);
 712
 713        if (ret != 0)
 714                return ret;
 715
 716        hwmgr = pp_handle->hwmgr;
 717
 718        if (hwmgr->ps == NULL)
 719                return -EINVAL;
 720
 721        mutex_lock(&pp_handle->pp_lock);
 722
 723        data->nums = hwmgr->num_ps;
 724
 725        for (i = 0; i < hwmgr->num_ps; i++) {
 726                struct pp_power_state *state = (struct pp_power_state *)
 727                                ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
 728                switch (state->classification.ui_label) {
 729                case PP_StateUILabel_Battery:
 730                        data->states[i] = POWER_STATE_TYPE_BATTERY;
 731                        break;
 732                case PP_StateUILabel_Balanced:
 733                        data->states[i] = POWER_STATE_TYPE_BALANCED;
 734                        break;
 735                case PP_StateUILabel_Performance:
 736                        data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
 737                        break;
 738                default:
 739                        if (state->classification.flags & PP_StateClassificationFlag_Boot)
 740                                data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
 741                        else
 742                                data->states[i] = POWER_STATE_TYPE_DEFAULT;
 743                }
 744        }
 745        mutex_unlock(&pp_handle->pp_lock);
 746        return 0;
 747}
 748
 749static int pp_dpm_get_pp_table(void *handle, char **table)
 750{
 751        struct pp_hwmgr *hwmgr;
 752        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 753        int ret = 0;
 754        int size = 0;
 755
 756        ret = pp_check(pp_handle);
 757
 758        if (ret != 0)
 759                return ret;
 760
 761        hwmgr = pp_handle->hwmgr;
 762
 763        if (!hwmgr->soft_pp_table)
 764                return -EINVAL;
 765
 766        mutex_lock(&pp_handle->pp_lock);
 767        *table = (char *)hwmgr->soft_pp_table;
 768        size = hwmgr->soft_pp_table_size;
 769        mutex_unlock(&pp_handle->pp_lock);
 770        return size;
 771}
 772
 773static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
 774{
 775        struct pp_hwmgr *hwmgr;
 776        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 777        int ret = 0;
 778
 779        ret = pp_check(pp_handle);
 780
 781        if (ret != 0)
 782                return ret;
 783
 784        hwmgr = pp_handle->hwmgr;
 785        mutex_lock(&pp_handle->pp_lock);
 786        if (!hwmgr->hardcode_pp_table) {
 787                hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
 788                                                   hwmgr->soft_pp_table_size,
 789                                                   GFP_KERNEL);
 790                if (!hwmgr->hardcode_pp_table) {
 791                        mutex_unlock(&pp_handle->pp_lock);
 792                        return -ENOMEM;
 793                }
 794        }
 795
 796        memcpy(hwmgr->hardcode_pp_table, buf, size);
 797
 798        hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
 799        mutex_unlock(&pp_handle->pp_lock);
 800
 801        ret = amd_powerplay_reset(handle);
 802        if (ret)
 803                return ret;
 804
 805        if (hwmgr->hwmgr_func->avfs_control) {
 806                ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
 807                if (ret)
 808                        return ret;
 809        }
 810
 811        return 0;
 812}
 813
 814static int pp_dpm_force_clock_level(void *handle,
 815                enum pp_clock_type type, uint32_t mask)
 816{
 817        struct pp_hwmgr *hwmgr;
 818        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 819        int ret = 0;
 820
 821        ret = pp_check(pp_handle);
 822
 823        if (ret != 0)
 824                return ret;
 825
 826        hwmgr = pp_handle->hwmgr;
 827
 828        if (hwmgr->hwmgr_func->force_clock_level == NULL) {
 829                pr_info("%s was not implemented.\n", __func__);
 830                return 0;
 831        }
 832        mutex_lock(&pp_handle->pp_lock);
 833        hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
 834        mutex_unlock(&pp_handle->pp_lock);
 835        return ret;
 836}
 837
 838static int pp_dpm_print_clock_levels(void *handle,
 839                enum pp_clock_type type, char *buf)
 840{
 841        struct pp_hwmgr *hwmgr;
 842        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 843        int ret = 0;
 844
 845        ret = pp_check(pp_handle);
 846
 847        if (ret != 0)
 848                return ret;
 849
 850        hwmgr = pp_handle->hwmgr;
 851
 852        if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
 853                pr_info("%s was not implemented.\n", __func__);
 854                return 0;
 855        }
 856        mutex_lock(&pp_handle->pp_lock);
 857        ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
 858        mutex_unlock(&pp_handle->pp_lock);
 859        return ret;
 860}
 861
 862static int pp_dpm_get_sclk_od(void *handle)
 863{
 864        struct pp_hwmgr *hwmgr;
 865        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 866        int ret = 0;
 867
 868        ret = pp_check(pp_handle);
 869
 870        if (ret != 0)
 871                return ret;
 872
 873        hwmgr = pp_handle->hwmgr;
 874
 875        if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
 876                pr_info("%s was not implemented.\n", __func__);
 877                return 0;
 878        }
 879        mutex_lock(&pp_handle->pp_lock);
 880        ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
 881        mutex_unlock(&pp_handle->pp_lock);
 882        return ret;
 883}
 884
 885static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
 886{
 887        struct pp_hwmgr *hwmgr;
 888        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 889        int ret = 0;
 890
 891        ret = pp_check(pp_handle);
 892
 893        if (ret != 0)
 894                return ret;
 895
 896        hwmgr = pp_handle->hwmgr;
 897
 898        if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
 899                pr_info("%s was not implemented.\n", __func__);
 900                return 0;
 901        }
 902
 903        mutex_lock(&pp_handle->pp_lock);
 904        ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
 905        mutex_unlock(&pp_handle->pp_lock);
 906        return ret;
 907}
 908
 909static int pp_dpm_get_mclk_od(void *handle)
 910{
 911        struct pp_hwmgr *hwmgr;
 912        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 913        int ret = 0;
 914
 915        ret = pp_check(pp_handle);
 916
 917        if (ret != 0)
 918                return ret;
 919
 920        hwmgr = pp_handle->hwmgr;
 921
 922        if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
 923                pr_info("%s was not implemented.\n", __func__);
 924                return 0;
 925        }
 926        mutex_lock(&pp_handle->pp_lock);
 927        ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
 928        mutex_unlock(&pp_handle->pp_lock);
 929        return ret;
 930}
 931
 932static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
 933{
 934        struct pp_hwmgr *hwmgr;
 935        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 936        int ret = 0;
 937
 938        ret = pp_check(pp_handle);
 939
 940        if (ret != 0)
 941                return ret;
 942
 943        hwmgr = pp_handle->hwmgr;
 944
 945        if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
 946                pr_info("%s was not implemented.\n", __func__);
 947                return 0;
 948        }
 949        mutex_lock(&pp_handle->pp_lock);
 950        ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
 951        mutex_unlock(&pp_handle->pp_lock);
 952        return ret;
 953}
 954
 955static int pp_dpm_read_sensor(void *handle, int idx,
 956                              void *value, int *size)
 957{
 958        struct pp_hwmgr *hwmgr;
 959        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 960        int ret = 0;
 961
 962        ret = pp_check(pp_handle);
 963
 964        if (ret != 0)
 965                return ret;
 966
 967        hwmgr = pp_handle->hwmgr;
 968
 969        if (hwmgr->hwmgr_func->read_sensor == NULL) {
 970                pr_info("%s was not implemented.\n", __func__);
 971                return 0;
 972        }
 973
 974        mutex_lock(&pp_handle->pp_lock);
 975        ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
 976        mutex_unlock(&pp_handle->pp_lock);
 977
 978        return ret;
 979}
 980
 981static struct amd_vce_state*
 982pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
 983{
 984        struct pp_hwmgr *hwmgr;
 985        struct pp_instance *pp_handle = (struct pp_instance *)handle;
 986        int ret = 0;
 987
 988        ret = pp_check(pp_handle);
 989
 990        if (ret != 0)
 991                return NULL;
 992
 993        hwmgr = pp_handle->hwmgr;
 994
 995        if (hwmgr && idx < hwmgr->num_vce_state_tables)
 996                return &hwmgr->vce_states[idx];
 997        return NULL;
 998}
 999
1000static int pp_dpm_reset_power_profile_state(void *handle,
1001                struct amd_pp_profile *request)
1002{
1003        struct pp_hwmgr *hwmgr;
1004        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1005
1006        if (!request || pp_check(pp_handle))
1007                return -EINVAL;
1008
1009        hwmgr = pp_handle->hwmgr;
1010
1011        if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1012                pr_info("%s was not implemented.\n", __func__);
1013                return 0;
1014        }
1015
1016        if (request->type == AMD_PP_GFX_PROFILE) {
1017                hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1018                return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1019                                &hwmgr->gfx_power_profile);
1020        } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1021                hwmgr->compute_power_profile =
1022                                hwmgr->default_compute_power_profile;
1023                return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1024                                &hwmgr->compute_power_profile);
1025        } else
1026                return -EINVAL;
1027}
1028
1029static int pp_dpm_get_power_profile_state(void *handle,
1030                struct amd_pp_profile *query)
1031{
1032        struct pp_hwmgr *hwmgr;
1033        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1034
1035        if (!query || pp_check(pp_handle))
1036                return -EINVAL;
1037
1038        hwmgr = pp_handle->hwmgr;
1039
1040        if (query->type == AMD_PP_GFX_PROFILE)
1041                memcpy(query, &hwmgr->gfx_power_profile,
1042                                sizeof(struct amd_pp_profile));
1043        else if (query->type == AMD_PP_COMPUTE_PROFILE)
1044                memcpy(query, &hwmgr->compute_power_profile,
1045                                sizeof(struct amd_pp_profile));
1046        else
1047                return -EINVAL;
1048
1049        return 0;
1050}
1051
1052static int pp_dpm_set_power_profile_state(void *handle,
1053                struct amd_pp_profile *request)
1054{
1055        struct pp_hwmgr *hwmgr;
1056        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1057        int ret = -1;
1058
1059        if (!request || pp_check(pp_handle))
1060                return -EINVAL;
1061
1062        hwmgr = pp_handle->hwmgr;
1063
1064        if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1065                pr_info("%s was not implemented.\n", __func__);
1066                return 0;
1067        }
1068
1069        if (request->min_sclk ||
1070                request->min_mclk ||
1071                request->activity_threshold ||
1072                request->up_hyst ||
1073                request->down_hyst) {
1074                if (request->type == AMD_PP_GFX_PROFILE)
1075                        memcpy(&hwmgr->gfx_power_profile, request,
1076                                        sizeof(struct amd_pp_profile));
1077                else if (request->type == AMD_PP_COMPUTE_PROFILE)
1078                        memcpy(&hwmgr->compute_power_profile, request,
1079                                        sizeof(struct amd_pp_profile));
1080                else
1081                        return -EINVAL;
1082
1083                if (request->type == hwmgr->current_power_profile)
1084                        ret = hwmgr->hwmgr_func->set_power_profile_state(
1085                                        hwmgr,
1086                                        request);
1087        } else {
1088                /* set power profile if it exists */
1089                switch (request->type) {
1090                case AMD_PP_GFX_PROFILE:
1091                        ret = hwmgr->hwmgr_func->set_power_profile_state(
1092                                        hwmgr,
1093                                        &hwmgr->gfx_power_profile);
1094                        break;
1095                case AMD_PP_COMPUTE_PROFILE:
1096                        ret = hwmgr->hwmgr_func->set_power_profile_state(
1097                                        hwmgr,
1098                                        &hwmgr->compute_power_profile);
1099                        break;
1100                default:
1101                        return -EINVAL;
1102                }
1103        }
1104
1105        if (!ret)
1106                hwmgr->current_power_profile = request->type;
1107
1108        return 0;
1109}
1110
1111static int pp_dpm_switch_power_profile(void *handle,
1112                enum amd_pp_profile_type type)
1113{
1114        struct pp_hwmgr *hwmgr;
1115        struct amd_pp_profile request = {0};
1116        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1117
1118        if (pp_check(pp_handle))
1119                return -EINVAL;
1120
1121        hwmgr = pp_handle->hwmgr;
1122
1123        if (hwmgr->current_power_profile != type) {
1124                request.type = type;
1125                pp_dpm_set_power_profile_state(handle, &request);
1126        }
1127
1128        return 0;
1129}
1130
1131const struct amd_powerplay_funcs pp_dpm_funcs = {
1132        .get_temperature = pp_dpm_get_temperature,
1133        .load_firmware = pp_dpm_load_fw,
1134        .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1135        .force_performance_level = pp_dpm_force_performance_level,
1136        .get_performance_level = pp_dpm_get_performance_level,
1137        .get_current_power_state = pp_dpm_get_current_power_state,
1138        .get_sclk = pp_dpm_get_sclk,
1139        .get_mclk = pp_dpm_get_mclk,
1140        .powergate_vce = pp_dpm_powergate_vce,
1141        .powergate_uvd = pp_dpm_powergate_uvd,
1142        .dispatch_tasks = pp_dpm_dispatch_tasks,
1143        .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1144        .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1145        .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1146        .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
1147        .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1148        .get_pp_num_states = pp_dpm_get_pp_num_states,
1149        .get_pp_table = pp_dpm_get_pp_table,
1150        .set_pp_table = pp_dpm_set_pp_table,
1151        .force_clock_level = pp_dpm_force_clock_level,
1152        .print_clock_levels = pp_dpm_print_clock_levels,
1153        .get_sclk_od = pp_dpm_get_sclk_od,
1154        .set_sclk_od = pp_dpm_set_sclk_od,
1155        .get_mclk_od = pp_dpm_get_mclk_od,
1156        .set_mclk_od = pp_dpm_set_mclk_od,
1157        .read_sensor = pp_dpm_read_sensor,
1158        .get_vce_clock_state = pp_dpm_get_vce_clock_state,
1159        .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1160        .get_power_profile_state = pp_dpm_get_power_profile_state,
1161        .set_power_profile_state = pp_dpm_set_power_profile_state,
1162        .switch_power_profile = pp_dpm_switch_power_profile,
1163};
1164
1165int amd_powerplay_create(struct amd_pp_init *pp_init,
1166                                void **handle)
1167{
1168        struct pp_instance *instance;
1169
1170        if (pp_init == NULL || handle == NULL)
1171                return -EINVAL;
1172
1173        instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
1174        if (instance == NULL)
1175                return -ENOMEM;
1176
1177        instance->pp_valid = PP_VALID;
1178        instance->chip_family = pp_init->chip_family;
1179        instance->chip_id = pp_init->chip_id;
1180        instance->pm_en = pp_init->pm_en;
1181        instance->feature_mask = pp_init->feature_mask;
1182        instance->device = pp_init->device;
1183        mutex_init(&instance->pp_lock);
1184        *handle = instance;
1185        return 0;
1186}
1187
1188int amd_powerplay_destroy(void *handle)
1189{
1190        struct pp_instance *instance = (struct pp_instance *)handle;
1191
1192        if (instance->pm_en) {
1193                kfree(instance->eventmgr);
1194                kfree(instance->hwmgr);
1195                instance->hwmgr = NULL;
1196                instance->eventmgr = NULL;
1197        }
1198
1199        kfree(instance->smu_mgr);
1200        instance->smu_mgr = NULL;
1201        kfree(instance);
1202        instance = NULL;
1203        return 0;
1204}
1205
1206int amd_powerplay_reset(void *handle)
1207{
1208        struct pp_instance *instance = (struct pp_instance *)handle;
1209        struct pp_eventmgr *eventmgr;
1210        struct pem_event_data event_data = { {0} };
1211        int ret;
1212
1213        if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1214                return PP_DPM_DISABLED;
1215
1216        ret = pp_check(instance);
1217        if (ret != 0)
1218                return ret;
1219
1220        ret = pp_hw_fini(handle);
1221        if (ret)
1222                return ret;
1223
1224        ret = hwmgr_hw_init(instance);
1225        if (ret)
1226                return PP_DPM_DISABLED;
1227
1228        eventmgr = instance->eventmgr;
1229
1230        if (eventmgr->pp_eventmgr_init == NULL)
1231                return PP_DPM_DISABLED;
1232
1233        ret = eventmgr->pp_eventmgr_init(eventmgr);
1234        if (ret)
1235                return ret;
1236
1237        return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
1238}
1239
1240/* export this function to DAL */
1241
1242int amd_powerplay_display_configuration_change(void *handle,
1243        const struct amd_pp_display_configuration *display_config)
1244{
1245        struct pp_hwmgr  *hwmgr;
1246        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1247        int ret = 0;
1248
1249        ret = pp_check(pp_handle);
1250
1251        if (ret != 0)
1252                return ret;
1253
1254        hwmgr = pp_handle->hwmgr;
1255        mutex_lock(&pp_handle->pp_lock);
1256        phm_store_dal_configuration_data(hwmgr, display_config);
1257        mutex_unlock(&pp_handle->pp_lock);
1258        return 0;
1259}
1260
1261int amd_powerplay_get_display_power_level(void *handle,
1262                struct amd_pp_simple_clock_info *output)
1263{
1264        struct pp_hwmgr  *hwmgr;
1265        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1266        int ret = 0;
1267
1268        ret = pp_check(pp_handle);
1269
1270        if (ret != 0)
1271                return ret;
1272
1273        hwmgr = pp_handle->hwmgr;
1274
1275        if (output == NULL)
1276                return -EINVAL;
1277
1278        mutex_lock(&pp_handle->pp_lock);
1279        ret = phm_get_dal_power_level(hwmgr, output);
1280        mutex_unlock(&pp_handle->pp_lock);
1281        return ret;
1282}
1283
1284int amd_powerplay_get_current_clocks(void *handle,
1285                struct amd_pp_clock_info *clocks)
1286{
1287        struct amd_pp_simple_clock_info simple_clocks;
1288        struct pp_clock_info hw_clocks;
1289        struct pp_hwmgr  *hwmgr;
1290        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1291        int ret = 0;
1292
1293        ret = pp_check(pp_handle);
1294
1295        if (ret != 0)
1296                return ret;
1297
1298        hwmgr = pp_handle->hwmgr;
1299
1300        mutex_lock(&pp_handle->pp_lock);
1301
1302        phm_get_dal_power_level(hwmgr, &simple_clocks);
1303
1304        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1305                                        PHM_PlatformCaps_PowerContainment))
1306                ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1307                                        &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1308        else
1309                ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1310                                        &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1311
1312        if (ret != 0) {
1313                pr_info("Error in phm_get_clock_info \n");
1314                mutex_unlock(&pp_handle->pp_lock);
1315                return -EINVAL;
1316        }
1317
1318        clocks->min_engine_clock = hw_clocks.min_eng_clk;
1319        clocks->max_engine_clock = hw_clocks.max_eng_clk;
1320        clocks->min_memory_clock = hw_clocks.min_mem_clk;
1321        clocks->max_memory_clock = hw_clocks.max_mem_clk;
1322        clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1323        clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1324
1325        clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1326        clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1327
1328        clocks->max_clocks_state = simple_clocks.level;
1329
1330        if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1331                clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1332                clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1333        }
1334        mutex_unlock(&pp_handle->pp_lock);
1335        return 0;
1336}
1337
1338int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1339{
1340        struct pp_hwmgr  *hwmgr;
1341        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1342        int ret = 0;
1343
1344        ret = pp_check(pp_handle);
1345
1346        if (ret != 0)
1347                return ret;
1348
1349        hwmgr = pp_handle->hwmgr;
1350
1351        if (clocks == NULL)
1352                return -EINVAL;
1353
1354        mutex_lock(&pp_handle->pp_lock);
1355        ret = phm_get_clock_by_type(hwmgr, type, clocks);
1356        mutex_unlock(&pp_handle->pp_lock);
1357        return ret;
1358}
1359
1360int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1361                enum amd_pp_clock_type type,
1362                struct pp_clock_levels_with_latency *clocks)
1363{
1364        struct pp_hwmgr *hwmgr;
1365        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1366        int ret = 0;
1367
1368        ret = pp_check(pp_handle);
1369        if (ret != 0)
1370                return ret;
1371
1372        if (!clocks)
1373                return -EINVAL;
1374
1375        mutex_lock(&pp_handle->pp_lock);
1376        hwmgr = ((struct pp_instance *)handle)->hwmgr;
1377        ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1378        mutex_unlock(&pp_handle->pp_lock);
1379        return ret;
1380}
1381
1382int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1383                enum amd_pp_clock_type type,
1384                struct pp_clock_levels_with_voltage *clocks)
1385{
1386        struct pp_hwmgr *hwmgr;
1387        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1388        int ret = 0;
1389
1390        ret = pp_check(pp_handle);
1391        if (ret != 0)
1392                return ret;
1393
1394        if (!clocks)
1395                return -EINVAL;
1396
1397        hwmgr = ((struct pp_instance *)handle)->hwmgr;
1398
1399        mutex_lock(&pp_handle->pp_lock);
1400
1401        ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1402
1403        mutex_unlock(&pp_handle->pp_lock);
1404        return ret;
1405}
1406
1407int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1408                struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1409{
1410        struct pp_hwmgr *hwmgr;
1411        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1412        int ret = 0;
1413
1414        ret = pp_check(pp_handle);
1415        if (ret != 0)
1416                return ret;
1417
1418        if (!wm_with_clock_ranges)
1419                return -EINVAL;
1420
1421        hwmgr = ((struct pp_instance *)handle)->hwmgr;
1422
1423        mutex_lock(&pp_handle->pp_lock);
1424        ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1425                        wm_with_clock_ranges);
1426        mutex_unlock(&pp_handle->pp_lock);
1427
1428        return ret;
1429}
1430
1431int amd_powerplay_display_clock_voltage_request(void *handle,
1432                struct pp_display_clock_request *clock)
1433{
1434        struct pp_hwmgr *hwmgr;
1435        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1436        int ret = 0;
1437
1438        ret = pp_check(pp_handle);
1439        if (ret != 0)
1440                return ret;
1441
1442        if (!clock)
1443                return -EINVAL;
1444
1445        hwmgr = ((struct pp_instance *)handle)->hwmgr;
1446
1447        mutex_lock(&pp_handle->pp_lock);
1448        ret = phm_display_clock_voltage_request(hwmgr, clock);
1449        mutex_unlock(&pp_handle->pp_lock);
1450
1451        return ret;
1452}
1453
1454int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1455                struct amd_pp_simple_clock_info *clocks)
1456{
1457        struct pp_hwmgr  *hwmgr;
1458        struct pp_instance *pp_handle = (struct pp_instance *)handle;
1459        int ret = 0;
1460
1461        ret = pp_check(pp_handle);
1462
1463        if (ret != 0)
1464                return ret;
1465
1466        hwmgr = pp_handle->hwmgr;
1467
1468        if (clocks == NULL)
1469                return -EINVAL;
1470
1471        mutex_lock(&pp_handle->pp_lock);
1472
1473        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1474                ret = phm_get_max_high_clocks(hwmgr, clocks);
1475
1476        mutex_unlock(&pp_handle->pp_lock);
1477        return ret;
1478}
1479
1480