amd_powerplay.c 32.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright 2015 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */
23
#include "pp_debug.h"
24 25 26
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/gfp.h>
27
#include <linux/slab.h>
28 29
#include "amd_shared.h"
#include "amd_powerplay.h"
30
#include "pp_instance.h"
31
#include "power_state.h"
32

33
static inline int pp_check(struct pp_instance *handle)
34
{
35 36
	if (handle == NULL || handle->pp_valid != PP_VALID)
		return -EINVAL;
37

38
	if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL)
39 40
		return -EINVAL;

41 42
	if (handle->pm_en == 0)
		return PP_DPM_DISABLED;
43

44
	if (handle->hwmgr->hwmgr_func == NULL)
45
		return PP_DPM_DISABLED;
46

47 48
	return 0;
}
49

50 51 52 53
static int pp_early_init(void *handle)
{
	int ret;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
54

55
	ret = hwmgr_early_init(pp_handle);
56
	if (ret)
57
		return -EINVAL;
58 59 60 61

	if ((pp_handle->pm_en == 0)
		|| cgs_is_virtualization_enabled(pp_handle->device))
		return PP_DPM_DISABLED;
62

63
	return 0;
64 65
}

66
static int pp_sw_init(void *handle)
67
{
68
	struct pp_hwmgr *hwmgr;
69
	int ret = 0;
70
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
71

72
	ret = pp_check(pp_handle);
73

74
	if (ret == 0 || ret == PP_DPM_DISABLED) {
75
		hwmgr = pp_handle->hwmgr;
76

77
		if (hwmgr->smumgr_funcs->smu_init == NULL)
78
			return -EINVAL;
79

80
		ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
81

82 83 84 85
		pr_info("amdgpu: powerplay sw initialized\n");
	}
	return ret;
}
86

87 88
static int pp_sw_fini(void *handle)
{
89
	struct pp_hwmgr *hwmgr;
90 91 92 93 94
	int ret = 0;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	ret = pp_check(pp_handle);
	if (ret == 0 || ret == PP_DPM_DISABLED) {
95
		hwmgr = pp_handle->hwmgr;
96

97
		if (hwmgr->smumgr_funcs->smu_fini == NULL)
98 99
			return -EINVAL;

100
		ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
101
	}
102
	return ret;
103 104 105 106
}

static int pp_hw_init(void *handle)
{
107
	int ret = 0;
108
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
109
	struct pp_hwmgr *hwmgr;
110

111
	ret = pp_check(pp_handle);
112

113
	if (ret == 0 || ret == PP_DPM_DISABLED) {
114
		hwmgr = pp_handle->hwmgr;
115

116
		if (hwmgr->smumgr_funcs->start_smu == NULL)
117
			return -EINVAL;
118

119
		if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
120
			pr_err("smc start failed\n");
121
			hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
122 123 124 125
			return -EINVAL;;
		}
		if (ret == PP_DPM_DISABLED)
			return PP_DPM_DISABLED;
126
	}
127

128 129 130
	ret = hwmgr_hw_init(pp_handle);
	if (ret)
		goto err;
131
	return 0;
132 133 134
err:
	pp_handle->pm_en = 0;
	return PP_DPM_DISABLED;
135 136 137 138
}

static int pp_hw_fini(void *handle)
{
139 140
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
141

142
	ret = pp_check(pp_handle);
143
	if (ret == 0)
144
		hwmgr_hw_fini(pp_handle);
145

146 147 148 149 150
	return 0;
}

static bool pp_is_idle(void *handle)
{
151
	return false;
152 153 154 155 156 157 158 159 160 161 162 163 164
}

static int pp_wait_for_idle(void *handle)
{
	return 0;
}

static int pp_sw_reset(void *handle)
{
	return 0;
}


165
int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
166
{
167
	struct pp_hwmgr  *hwmgr;
168 169
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
170

171
	ret = pp_check(pp_handle);
172

173 174
	if (ret != 0)
		return ret;
175

176
	hwmgr = pp_handle->hwmgr;
177

178
	if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
179
		pr_info("%s was not implemented.\n", __func__);
180
		return 0;
181
	}
182

183
	return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
184 185 186 187 188
}

static int pp_set_powergating_state(void *handle,
				    enum amd_powergating_state state)
{
189
	struct pp_hwmgr  *hwmgr;
190 191
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
192

193
	ret = pp_check(pp_handle);
194

195 196
	if (ret != 0)
		return ret;
197

198
	hwmgr = pp_handle->hwmgr;
199 200

	if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
201
		pr_info("%s was not implemented.\n", __func__);
202 203
		return 0;
	}
204 205 206

	/* Enable/disable GFX per cu powergating through SMU */
	return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
207
			state == AMD_PG_STATE_GATE);
208 209 210 211
}

static int pp_suspend(void *handle)
{
212 213
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
214

215 216
	ret = pp_check(pp_handle);

217 218 219
	if (ret == PP_DPM_DISABLED)
		return 0;
	else if (ret != 0)
220
		return ret;
221

222
	return hwmgr_hw_suspend(pp_handle);
223 224 225 226
}

static int pp_resume(void *handle)
{
227
	struct pp_hwmgr  *hwmgr;
228 229
	int ret, ret1;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
230

231 232 233 234
	ret1 = pp_check(pp_handle);

	if (ret1 != 0 && ret1 != PP_DPM_DISABLED)
		return ret1;
235

236
	hwmgr = pp_handle->hwmgr;
237

238
	if (hwmgr->smumgr_funcs->start_smu == NULL)
239 240
		return -EINVAL;

241
	ret = hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr);
242
	if (ret) {
243
		pr_err("smc start failed\n");
244
		hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
245 246 247
		return ret;
	}

248
	if (ret1 == PP_DPM_DISABLED)
M
Monk Liu 已提交
249
		return 0;
250

251
	return hwmgr_hw_resume(pp_handle);
252 253 254
}

const struct amd_ip_funcs pp_ip_funcs = {
255
	.name = "powerplay",
256 257 258 259 260 261 262 263 264 265 266
	.early_init = pp_early_init,
	.late_init = NULL,
	.sw_init = pp_sw_init,
	.sw_fini = pp_sw_fini,
	.hw_init = pp_hw_init,
	.hw_fini = pp_hw_fini,
	.suspend = pp_suspend,
	.resume = pp_resume,
	.is_idle = pp_is_idle,
	.wait_for_idle = pp_wait_for_idle,
	.soft_reset = pp_sw_reset,
267
	.set_clockgating_state = NULL,
268 269 270 271 272 273 274 275 276 277 278 279 280
	.set_powergating_state = pp_set_powergating_state,
};

static int pp_dpm_load_fw(void *handle)
{
	return 0;
}

static int pp_dpm_fw_loading_complete(void *handle)
{
	return 0;
}

281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
static void pp_dpm_en_umd_pstate(struct pp_hwmgr  *hwmgr,
						enum amd_dpm_forced_level *level)
{
	uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
					AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
					AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
					AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;

	if (!(hwmgr->dpm_level & profile_mode_mask)) {
		/* enter umd pstate, save current level, disable gfx cg*/
		if (*level & profile_mode_mask) {
			hwmgr->saved_dpm_level = hwmgr->dpm_level;
			hwmgr->en_umd_pstate = true;
			cgs_set_clockgating_state(hwmgr->device,
						AMD_IP_BLOCK_TYPE_GFX,
						AMD_CG_STATE_UNGATE);
			cgs_set_powergating_state(hwmgr->device,
					AMD_IP_BLOCK_TYPE_GFX,
					AMD_PG_STATE_UNGATE);
		}
	} else {
		/* exit umd pstate, restore level, enable gfx cg*/
		if (!(*level & profile_mode_mask)) {
			if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
				*level = hwmgr->saved_dpm_level;
			hwmgr->en_umd_pstate = false;
			cgs_set_clockgating_state(hwmgr->device,
					AMD_IP_BLOCK_TYPE_GFX,
					AMD_CG_STATE_GATE);
			cgs_set_powergating_state(hwmgr->device,
					AMD_IP_BLOCK_TYPE_GFX,
					AMD_PG_STATE_GATE);
		}
	}
}

317 318 319
static int pp_dpm_force_performance_level(void *handle,
					enum amd_dpm_forced_level level)
{
320
	struct pp_hwmgr  *hwmgr;
321 322
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
323

324
	ret = pp_check(pp_handle);
325

326 327
	if (ret != 0)
		return ret;
328 329 330

	hwmgr = pp_handle->hwmgr;

331 332 333
	if (level == hwmgr->dpm_level)
		return 0;

334
	if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
335
		pr_info("%s was not implemented.\n", __func__);
336 337
		return 0;
	}
338

339
	mutex_lock(&pp_handle->pp_lock);
340 341
	pp_dpm_en_umd_pstate(hwmgr, &level);
	hwmgr->request_dpm_level = level;
342
	hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
343 344 345 346
	ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
	if (!ret)
		hwmgr->dpm_level = hwmgr->request_dpm_level;

347
	mutex_unlock(&pp_handle->pp_lock);
348 349
	return 0;
}
350

351 352 353
static enum amd_dpm_forced_level pp_dpm_get_performance_level(
								void *handle)
{
354
	struct pp_hwmgr  *hwmgr;
355 356
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
357
	enum amd_dpm_forced_level level;
358

359
	ret = pp_check(pp_handle);
360

361 362
	if (ret != 0)
		return ret;
363

364
	hwmgr = pp_handle->hwmgr;
365 366 367 368
	mutex_lock(&pp_handle->pp_lock);
	level = hwmgr->dpm_level;
	mutex_unlock(&pp_handle->pp_lock);
	return level;
369
}
370

371
static uint32_t pp_dpm_get_sclk(void *handle, bool low)
372
{
373
	struct pp_hwmgr  *hwmgr;
374 375
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
376
	uint32_t clk = 0;
377

378
	ret = pp_check(pp_handle);
379

380 381
	if (ret != 0)
		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 388
		return 0;
	}
389
	mutex_lock(&pp_handle->pp_lock);
390
	clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
391
	mutex_unlock(&pp_handle->pp_lock);
392
	return clk;
393
}
394

395
static uint32_t pp_dpm_get_mclk(void *handle, bool low)
396
{
397
	struct pp_hwmgr  *hwmgr;
398 399
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
400
	uint32_t clk = 0;
401

402
	ret = pp_check(pp_handle);
403

404 405
	if (ret != 0)
		return ret;
406

407
	hwmgr = pp_handle->hwmgr;
408 409

	if (hwmgr->hwmgr_func->get_mclk == NULL) {
410
		pr_info("%s was not implemented.\n", __func__);
411 412
		return 0;
	}
413
	mutex_lock(&pp_handle->pp_lock);
414
	clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
415
	mutex_unlock(&pp_handle->pp_lock);
416
	return clk;
417
}
418

419
static void pp_dpm_powergate_vce(void *handle, bool gate)
420
{
421
	struct pp_hwmgr  *hwmgr;
422 423
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
424

425
	ret = pp_check(pp_handle);
426

427
	if (ret != 0)
428
		return;
429

430
	hwmgr = pp_handle->hwmgr;
431 432

	if (hwmgr->hwmgr_func->powergate_vce == NULL) {
433
		pr_info("%s was not implemented.\n", __func__);
434
		return;
435
	}
436
	mutex_lock(&pp_handle->pp_lock);
437
	hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
438
	mutex_unlock(&pp_handle->pp_lock);
439
}
440

441
static void pp_dpm_powergate_uvd(void *handle, bool gate)
442
{
443
	struct pp_hwmgr  *hwmgr;
444 445
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
446

447
	ret = pp_check(pp_handle);
448

449
	if (ret != 0)
450
		return;
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;
457
	}
458
	mutex_lock(&pp_handle->pp_lock);
459
	hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
460
	mutex_unlock(&pp_handle->pp_lock);
461 462
}

463
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
464
		void *input, void *output)
465
{
466
	int ret = 0;
467
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
468

469
	ret = pp_check(pp_handle);
470

471 472
	if (ret != 0)
		return ret;
473

474 475
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr_handle_task(pp_handle, task_id, input, output);
476
	mutex_unlock(&pp_handle->pp_lock);
477

478
	return ret;
479
}
480

481
static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
482
{
483 484
	struct pp_hwmgr *hwmgr;
	struct pp_power_state *state;
485 486
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
487
	enum amd_pm_state_type pm_type;
488

489
	ret = pp_check(pp_handle);
490

491 492
	if (ret != 0)
		return ret;
493

494 495 496
	hwmgr = pp_handle->hwmgr;

	if (hwmgr->current_ps == NULL)
497 498
		return -EINVAL;

499 500
	mutex_lock(&pp_handle->pp_lock);

501 502 503 504
	state = hwmgr->current_ps;

	switch (state->classification.ui_label) {
	case PP_StateUILabel_Battery:
505
		pm_type = POWER_STATE_TYPE_BATTERY;
506
		break;
507
	case PP_StateUILabel_Balanced:
508
		pm_type = POWER_STATE_TYPE_BALANCED;
509
		break;
510
	case PP_StateUILabel_Performance:
511
		pm_type = POWER_STATE_TYPE_PERFORMANCE;
512
		break;
513
	default:
514
		if (state->classification.flags & PP_StateClassificationFlag_Boot)
515
			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
516
		else
517
			pm_type = POWER_STATE_TYPE_DEFAULT;
518
		break;
519
	}
520 521 522
	mutex_unlock(&pp_handle->pp_lock);

	return pm_type;
523
}
524

525
static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
526 527
{
	struct pp_hwmgr  *hwmgr;
528 529
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
530

531
	ret = pp_check(pp_handle);
532

533
	if (ret != 0)
534
		return;
535

536
	hwmgr = pp_handle->hwmgr;
537 538

	if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
539
		pr_info("%s was not implemented.\n", __func__);
540
		return;
541
	}
542
	mutex_lock(&pp_handle->pp_lock);
543
	hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
544
	mutex_unlock(&pp_handle->pp_lock);
545 546
}

547
static uint32_t pp_dpm_get_fan_control_mode(void *handle)
548 549
{
	struct pp_hwmgr  *hwmgr;
550 551
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
552
	uint32_t mode = 0;
553

554
	ret = pp_check(pp_handle);
555

556 557
	if (ret != 0)
		return ret;
558

559
	hwmgr = pp_handle->hwmgr;
560 561

	if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
562
		pr_info("%s was not implemented.\n", __func__);
563 564
		return 0;
	}
565
	mutex_lock(&pp_handle->pp_lock);
566
	mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
567
	mutex_unlock(&pp_handle->pp_lock);
568
	return mode;
569 570 571 572 573
}

static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
{
	struct pp_hwmgr  *hwmgr;
574 575
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
576

577
	ret = pp_check(pp_handle);
578

579 580
	if (ret != 0)
		return ret;
581

582
	hwmgr = pp_handle->hwmgr;
583 584

	if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
585
		pr_info("%s was not implemented.\n", __func__);
586 587
		return 0;
	}
588 589 590 591
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
592 593 594 595 596
}

static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
{
	struct pp_hwmgr  *hwmgr;
597 598
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
599

600
	ret = pp_check(pp_handle);
601

602 603
	if (ret != 0)
		return ret;
604

605
	hwmgr = pp_handle->hwmgr;
606 607

	if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
608
		pr_info("%s was not implemented.\n", __func__);
609 610
		return 0;
	}
611

612 613 614 615
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
616 617
}

618 619 620
static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
{
	struct pp_hwmgr *hwmgr;
621 622
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
623

624
	ret = pp_check(pp_handle);
625

626 627
	if (ret != 0)
		return ret;
628

629
	hwmgr = pp_handle->hwmgr;
630 631 632 633

	if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
		return -EINVAL;

634 635 636 637
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
638 639
}

640 641 642
static int pp_dpm_get_temperature(void *handle)
{
	struct pp_hwmgr  *hwmgr;
643 644
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
645

646
	ret = pp_check(pp_handle);
647

648 649
	if (ret != 0)
		return ret;
650

651
	hwmgr = pp_handle->hwmgr;
652 653

	if (hwmgr->hwmgr_func->get_temperature == NULL) {
654
		pr_info("%s was not implemented.\n", __func__);
655 656
		return 0;
	}
657 658 659 660
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
661
}
662

663 664 665 666 667
static int pp_dpm_get_pp_num_states(void *handle,
		struct pp_states_info *data)
{
	struct pp_hwmgr *hwmgr;
	int i;
668 669
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
670

671
	ret = pp_check(pp_handle);
672

673 674 675 676
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
677

678
	if (hwmgr->ps == NULL)
679 680
		return -EINVAL;

681 682
	mutex_lock(&pp_handle->pp_lock);

683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
	data->nums = hwmgr->num_ps;

	for (i = 0; i < hwmgr->num_ps; i++) {
		struct pp_power_state *state = (struct pp_power_state *)
				((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
		switch (state->classification.ui_label) {
		case PP_StateUILabel_Battery:
			data->states[i] = POWER_STATE_TYPE_BATTERY;
			break;
		case PP_StateUILabel_Balanced:
			data->states[i] = POWER_STATE_TYPE_BALANCED;
			break;
		case PP_StateUILabel_Performance:
			data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
			break;
		default:
			if (state->classification.flags & PP_StateClassificationFlag_Boot)
				data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
			else
				data->states[i] = POWER_STATE_TYPE_DEFAULT;
		}
	}
705
	mutex_unlock(&pp_handle->pp_lock);
706 707 708 709 710 711
	return 0;
}

static int pp_dpm_get_pp_table(void *handle, char **table)
{
	struct pp_hwmgr *hwmgr;
712 713
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
714
	int size = 0;
715

716
	ret = pp_check(pp_handle);
717

718 719
	if (ret != 0)
		return ret;
720

721
	hwmgr = pp_handle->hwmgr;
722

723 724 725
	if (!hwmgr->soft_pp_table)
		return -EINVAL;

726
	mutex_lock(&pp_handle->pp_lock);
727
	*table = (char *)hwmgr->soft_pp_table;
728 729 730
	size = hwmgr->soft_pp_table_size;
	mutex_unlock(&pp_handle->pp_lock);
	return size;
731 732 733 734 735
}

static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
{
	struct pp_hwmgr *hwmgr;
736 737
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
738

739
	ret = pp_check(pp_handle);
740

741 742
	if (ret != 0)
		return ret;
743

744
	hwmgr = pp_handle->hwmgr;
745
	mutex_lock(&pp_handle->pp_lock);
746
	if (!hwmgr->hardcode_pp_table) {
747 748 749
		hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
						   hwmgr->soft_pp_table_size,
						   GFP_KERNEL);
750 751
		if (!hwmgr->hardcode_pp_table) {
			mutex_unlock(&pp_handle->pp_lock);
752
			return -ENOMEM;
753
		}
754
	}
755

756 757 758
	memcpy(hwmgr->hardcode_pp_table, buf, size);

	hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
759
	mutex_unlock(&pp_handle->pp_lock);
760

761 762 763 764 765 766 767 768 769 770 771
	ret = amd_powerplay_reset(handle);
	if (ret)
		return ret;

	if (hwmgr->hwmgr_func->avfs_control) {
		ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
		if (ret)
			return ret;
	}

	return 0;
772 773 774
}

static int pp_dpm_force_clock_level(void *handle,
775
		enum pp_clock_type type, uint32_t mask)
776 777
{
	struct pp_hwmgr *hwmgr;
778 779
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
780

781
	ret = pp_check(pp_handle);
782

783 784
	if (ret != 0)
		return ret;
785

786
	hwmgr = pp_handle->hwmgr;
787 788

	if (hwmgr->hwmgr_func->force_clock_level == NULL) {
789
		pr_info("%s was not implemented.\n", __func__);
790 791
		return 0;
	}
792 793 794 795
	mutex_lock(&pp_handle->pp_lock);
	hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
796 797 798 799 800 801
}

static int pp_dpm_print_clock_levels(void *handle,
		enum pp_clock_type type, char *buf)
{
	struct pp_hwmgr *hwmgr;
802 803
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
804

805
	ret = pp_check(pp_handle);
806

807 808
	if (ret != 0)
		return ret;
809

810
	hwmgr = pp_handle->hwmgr;
811

812
	if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
813
		pr_info("%s was not implemented.\n", __func__);
814 815
		return 0;
	}
816 817 818 819
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
820 821
}

822 823 824
static int pp_dpm_get_sclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
825 826
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
827

828
	ret = pp_check(pp_handle);
829

830 831
	if (ret != 0)
		return ret;
832

833
	hwmgr = pp_handle->hwmgr;
834 835

	if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
836
		pr_info("%s was not implemented.\n", __func__);
837 838
		return 0;
	}
839 840 841 842
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
843 844 845 846 847
}

static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
848 849
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
850

851
	ret = pp_check(pp_handle);
852

853 854
	if (ret != 0)
		return ret;
855

856
	hwmgr = pp_handle->hwmgr;
857 858

	if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
859
		pr_info("%s was not implemented.\n", __func__);
860 861 862
		return 0;
	}

863 864
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
865
	mutex_unlock(&pp_handle->pp_lock);
866
	return ret;
867 868
}

869 870 871
static int pp_dpm_get_mclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
872 873
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
874

875
	ret = pp_check(pp_handle);
876

877 878
	if (ret != 0)
		return ret;
879

880
	hwmgr = pp_handle->hwmgr;
881 882

	if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
883
		pr_info("%s was not implemented.\n", __func__);
884 885
		return 0;
	}
886 887 888 889
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
890 891 892 893 894
}

static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
895 896
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
897

898
	ret = pp_check(pp_handle);
899

900 901
	if (ret != 0)
		return ret;
902

903
	hwmgr = pp_handle->hwmgr;
904 905

	if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
906
		pr_info("%s was not implemented.\n", __func__);
907 908
		return 0;
	}
909 910 911 912
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
913 914
}

915 916
static int pp_dpm_read_sensor(void *handle, int idx,
			      void *value, int *size)
917 918
{
	struct pp_hwmgr *hwmgr;
919 920
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
921

922
	ret = pp_check(pp_handle);
923

924 925
	if (ret != 0)
		return ret;
926

927
	hwmgr = pp_handle->hwmgr;
928 929

	if (hwmgr->hwmgr_func->read_sensor == NULL) {
930
		pr_info("%s was not implemented.\n", __func__);
931 932 933
		return 0;
	}

934 935 936 937 938
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
	mutex_unlock(&pp_handle->pp_lock);

	return ret;
939 940
}

941 942 943 944
static struct amd_vce_state*
pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
{
	struct pp_hwmgr *hwmgr;
945 946
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
947

948
	ret = pp_check(pp_handle);
949

950 951 952 953 954 955 956
	if (ret != 0)
		return NULL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr && idx < hwmgr->num_vce_state_tables)
		return &hwmgr->vce_states[idx];
957 958 959
	return NULL;
}

960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
static int pp_dpm_reset_power_profile_state(void *handle,
		struct amd_pp_profile *request)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	if (!request || pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return 0;
	}

	if (request->type == AMD_PP_GFX_PROFILE) {
		hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
		return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
				&hwmgr->gfx_power_profile);
	} else if (request->type == AMD_PP_COMPUTE_PROFILE) {
		hwmgr->compute_power_profile =
				hwmgr->default_compute_power_profile;
		return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
				&hwmgr->compute_power_profile);
	} else
		return -EINVAL;
}

static int pp_dpm_get_power_profile_state(void *handle,
		struct amd_pp_profile *query)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	if (!query || pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

	if (query->type == AMD_PP_GFX_PROFILE)
		memcpy(query, &hwmgr->gfx_power_profile,
				sizeof(struct amd_pp_profile));
	else if (query->type == AMD_PP_COMPUTE_PROFILE)
		memcpy(query, &hwmgr->compute_power_profile,
				sizeof(struct amd_pp_profile));
	else
		return -EINVAL;

	return 0;
}

static int pp_dpm_set_power_profile_state(void *handle,
		struct amd_pp_profile *request)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = -1;

	if (!request || pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return 0;
	}

	if (request->min_sclk ||
		request->min_mclk ||
		request->activity_threshold ||
		request->up_hyst ||
		request->down_hyst) {
		if (request->type == AMD_PP_GFX_PROFILE)
			memcpy(&hwmgr->gfx_power_profile, request,
					sizeof(struct amd_pp_profile));
		else if (request->type == AMD_PP_COMPUTE_PROFILE)
			memcpy(&hwmgr->compute_power_profile, request,
					sizeof(struct amd_pp_profile));
		else
			return -EINVAL;

		if (request->type == hwmgr->current_power_profile)
			ret = hwmgr->hwmgr_func->set_power_profile_state(
					hwmgr,
					request);
	} else {
		/* set power profile if it exists */
		switch (request->type) {
		case AMD_PP_GFX_PROFILE:
			ret = hwmgr->hwmgr_func->set_power_profile_state(
					hwmgr,
					&hwmgr->gfx_power_profile);
			break;
		case AMD_PP_COMPUTE_PROFILE:
			ret = hwmgr->hwmgr_func->set_power_profile_state(
					hwmgr,
					&hwmgr->compute_power_profile);
			break;
		default:
			return -EINVAL;
		}
	}

	if (!ret)
		hwmgr->current_power_profile = request->type;

	return 0;
}

static int pp_dpm_switch_power_profile(void *handle,
		enum amd_pp_profile_type type)
{
	struct pp_hwmgr *hwmgr;
	struct amd_pp_profile request = {0};
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	if (pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr->current_power_profile != type) {
		request.type = type;
		pp_dpm_set_power_profile_state(handle, &request);
	}

	return 0;
}

1091
const struct amd_pm_funcs pp_dpm_funcs = {
1092
	.get_temperature = pp_dpm_get_temperature,
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
	.load_firmware = pp_dpm_load_fw,
	.wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
	.force_performance_level = pp_dpm_force_performance_level,
	.get_performance_level = pp_dpm_get_performance_level,
	.get_current_power_state = pp_dpm_get_current_power_state,
	.get_sclk = pp_dpm_get_sclk,
	.get_mclk = pp_dpm_get_mclk,
	.powergate_vce = pp_dpm_powergate_vce,
	.powergate_uvd = pp_dpm_powergate_uvd,
	.dispatch_tasks = pp_dpm_dispatch_tasks,
1103 1104 1105 1106
	.set_fan_control_mode = pp_dpm_set_fan_control_mode,
	.get_fan_control_mode = pp_dpm_get_fan_control_mode,
	.set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
	.get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
1107
	.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1108 1109 1110 1111 1112
	.get_pp_num_states = pp_dpm_get_pp_num_states,
	.get_pp_table = pp_dpm_get_pp_table,
	.set_pp_table = pp_dpm_set_pp_table,
	.force_clock_level = pp_dpm_force_clock_level,
	.print_clock_levels = pp_dpm_print_clock_levels,
1113 1114
	.get_sclk_od = pp_dpm_get_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
1115 1116
	.get_mclk_od = pp_dpm_get_mclk_od,
	.set_mclk_od = pp_dpm_set_mclk_od,
1117
	.read_sensor = pp_dpm_read_sensor,
1118
	.get_vce_clock_state = pp_dpm_get_vce_clock_state,
1119 1120 1121 1122
	.reset_power_profile_state = pp_dpm_reset_power_profile_state,
	.get_power_profile_state = pp_dpm_get_power_profile_state,
	.set_power_profile_state = pp_dpm_set_power_profile_state,
	.switch_power_profile = pp_dpm_switch_power_profile,
1123 1124
};

1125 1126
int amd_powerplay_create(struct amd_pp_init *pp_init,
				void **handle)
1127
{
1128
	struct pp_instance *instance;
1129

1130 1131
	if (pp_init == NULL || handle == NULL)
		return -EINVAL;
1132

1133 1134 1135
	instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
	if (instance == NULL)
		return -ENOMEM;
1136

1137 1138 1139 1140 1141 1142
	instance->pp_valid = PP_VALID;
	instance->chip_family = pp_init->chip_family;
	instance->chip_id = pp_init->chip_id;
	instance->pm_en = pp_init->pm_en;
	instance->feature_mask = pp_init->feature_mask;
	instance->device = pp_init->device;
1143
	mutex_init(&instance->pp_lock);
1144
	*handle = instance;
1145 1146 1147
	return 0;
}

1148
int amd_powerplay_destroy(void *handle)
1149 1150
{
	struct pp_instance *instance = (struct pp_instance *)handle;
1151

1152 1153
	kfree(instance->hwmgr);
	instance->hwmgr = NULL;
1154

1155 1156
	kfree(instance);
	instance = NULL;
1157 1158
	return 0;
}
1159

1160 1161 1162 1163 1164
int amd_powerplay_reset(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;
	int ret;

1165
	if (cgs_is_virtualization_enabled(instance->hwmgr->device))
1166
		return PP_DPM_DISABLED;
1167

1168 1169
	ret = pp_check(instance);
	if (ret != 0)
1170 1171
		return ret;

1172
	ret = pp_hw_fini(instance);
1173 1174 1175
	if (ret)
		return ret;

1176 1177 1178
	ret = hwmgr_hw_init(instance);
	if (ret)
		return PP_DPM_DISABLED;
1179

1180
	return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
1181 1182
}

1183 1184
/* export this function to DAL */

1185 1186
int amd_powerplay_display_configuration_change(void *handle,
	const struct amd_pp_display_configuration *display_config)
1187 1188
{
	struct pp_hwmgr  *hwmgr;
1189 1190
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1191

1192
	ret = pp_check(pp_handle);
1193

1194 1195
	if (ret != 0)
		return ret;
1196

1197
	hwmgr = pp_handle->hwmgr;
1198
	mutex_lock(&pp_handle->pp_lock);
1199
	phm_store_dal_configuration_data(hwmgr, display_config);
1200
	mutex_unlock(&pp_handle->pp_lock);
1201 1202
	return 0;
}
1203

1204
int amd_powerplay_get_display_power_level(void *handle,
R
Rex Zhu 已提交
1205
		struct amd_pp_simple_clock_info *output)
1206 1207
{
	struct pp_hwmgr  *hwmgr;
1208 1209
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1210

1211
	ret = pp_check(pp_handle);
1212

1213 1214
	if (ret != 0)
		return ret;
1215

1216
	hwmgr = pp_handle->hwmgr;
1217

1218 1219
	if (output == NULL)
		return -EINVAL;
1220

1221 1222 1223 1224
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_dal_power_level(hwmgr, output);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1225
}
1226 1227

int amd_powerplay_get_current_clocks(void *handle,
1228
		struct amd_pp_clock_info *clocks)
1229 1230 1231
{
	struct amd_pp_simple_clock_info simple_clocks;
	struct pp_clock_info hw_clocks;
1232 1233 1234
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1235

1236
	ret = pp_check(pp_handle);
1237

1238 1239
	if (ret != 0)
		return ret;
1240

1241
	hwmgr = pp_handle->hwmgr;
1242

1243 1244
	mutex_lock(&pp_handle->pp_lock);

1245 1246
	phm_get_dal_power_level(hwmgr, &simple_clocks);

1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
					PHM_PlatformCaps_PowerContainment))
		ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
					&hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
	else
		ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
					&hw_clocks, PHM_PerformanceLevelDesignation_Activity);

	if (ret != 0) {
		pr_info("Error in phm_get_clock_info \n");
		mutex_unlock(&pp_handle->pp_lock);
		return -EINVAL;
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
	}

	clocks->min_engine_clock = hw_clocks.min_eng_clk;
	clocks->max_engine_clock = hw_clocks.max_eng_clk;
	clocks->min_memory_clock = hw_clocks.min_mem_clk;
	clocks->max_memory_clock = hw_clocks.max_mem_clk;
	clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
	clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;

	clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
	clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;

	clocks->max_clocks_state = simple_clocks.level;

	if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
		clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
		clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
	}
1277
	mutex_unlock(&pp_handle->pp_lock);
1278 1279 1280 1281 1282
	return 0;
}

int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
{
1283 1284 1285
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1286

1287
	ret = pp_check(pp_handle);
1288

1289 1290 1291 1292
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
1293 1294

	if (clocks == NULL)
1295 1296
		return -EINVAL;

1297 1298 1299 1300
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_clock_by_type(hwmgr, type, clocks);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1301 1302
}

1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
int amd_powerplay_get_clock_by_type_with_latency(void *handle,
		enum amd_pp_clock_type type,
		struct pp_clock_levels_with_latency *clocks)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;

	ret = pp_check(pp_handle);
	if (ret != 0)
		return ret;

	if (!clocks)
		return -EINVAL;

	mutex_lock(&pp_handle->pp_lock);
	hwmgr = ((struct pp_instance *)handle)->hwmgr;
	ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
}

int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
		enum amd_pp_clock_type type,
		struct pp_clock_levels_with_voltage *clocks)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;

	ret = pp_check(pp_handle);
	if (ret != 0)
		return ret;

	if (!clocks)
		return -EINVAL;

	hwmgr = ((struct pp_instance *)handle)->hwmgr;

	mutex_lock(&pp_handle->pp_lock);

	ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);

	mutex_unlock(&pp_handle->pp_lock);
	return ret;
}

int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
		struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;

	ret = pp_check(pp_handle);
	if (ret != 0)
		return ret;

	if (!wm_with_clock_ranges)
		return -EINVAL;

	hwmgr = ((struct pp_instance *)handle)->hwmgr;

	mutex_lock(&pp_handle->pp_lock);
	ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
			wm_with_clock_ranges);
	mutex_unlock(&pp_handle->pp_lock);

	return ret;
}

int amd_powerplay_display_clock_voltage_request(void *handle,
		struct pp_display_clock_request *clock)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;

	ret = pp_check(pp_handle);
	if (ret != 0)
		return ret;

	if (!clock)
		return -EINVAL;

	hwmgr = ((struct pp_instance *)handle)->hwmgr;

	mutex_lock(&pp_handle->pp_lock);
	ret = phm_display_clock_voltage_request(hwmgr, clock);
	mutex_unlock(&pp_handle->pp_lock);

	return ret;
}

1397 1398
int amd_powerplay_get_display_mode_validation_clocks(void *handle,
		struct amd_pp_simple_clock_info *clocks)
1399 1400
{
	struct pp_hwmgr  *hwmgr;
1401 1402
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1403

1404
	ret = pp_check(pp_handle);
1405

1406 1407 1408 1409
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
1410

1411 1412
	if (clocks == NULL)
		return -EINVAL;
1413

1414 1415
	mutex_lock(&pp_handle->pp_lock);

1416
	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1417
		ret = phm_get_max_high_clocks(hwmgr, clocks);
1418

1419
	mutex_unlock(&pp_handle->pp_lock);
1420
	return ret;
1421 1422
}