Linux Audio

Check our new training course

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