amd_powerplay.c 31.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

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

39
	if (handle->smu_mgr == NULL || handle->smu_mgr->smumgr_funcs == NULL)
40 41
		return -EINVAL;

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

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

48 49
	return 0;
}
50

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

56
	ret = smum_early_init(pp_handle);
57
	if (ret)
58 59 60 61 62
		return ret;

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

64 65 66 67
	ret = hwmgr_early_init(pp_handle);
	if (ret) {
		pp_handle->pm_en = 0;
		return PP_DPM_DISABLED;
68 69
	}

70
	return 0;
71 72
}

73
static int pp_sw_init(void *handle)
74
{
75
	struct pp_smumgr *smumgr;
76
	int ret = 0;
77
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
78

79
	ret = pp_check(pp_handle);
80

81 82
	if (ret == 0 || ret == PP_DPM_DISABLED) {
		smumgr = pp_handle->smu_mgr;
83

84 85
		if (smumgr->smumgr_funcs->smu_init == NULL)
			return -EINVAL;
86

87
		ret = smumgr->smumgr_funcs->smu_init(smumgr);
88

89 90 91 92
		pr_info("amdgpu: powerplay sw initialized\n");
	}
	return ret;
}
93

94 95 96 97 98 99 100 101 102
static int pp_sw_fini(void *handle)
{
	struct pp_smumgr *smumgr;
	int ret = 0;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	ret = pp_check(pp_handle);
	if (ret == 0 || ret == PP_DPM_DISABLED) {
		smumgr = pp_handle->smu_mgr;
103

104 105 106 107 108
		if (smumgr->smumgr_funcs->smu_fini == NULL)
			return -EINVAL;

		ret = smumgr->smumgr_funcs->smu_fini(smumgr);
	}
109
	return ret;
110 111 112 113
}

static int pp_hw_init(void *handle)
{
114 115
	struct pp_smumgr *smumgr;
	int ret = 0;
116
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
117

118
	ret = pp_check(pp_handle);
119

120 121
	if (ret == 0 || ret == PP_DPM_DISABLED) {
		smumgr = pp_handle->smu_mgr;
122

123 124
		if (smumgr->smumgr_funcs->start_smu == NULL)
			return -EINVAL;
125

126 127 128 129 130 131 132
		if(smumgr->smumgr_funcs->start_smu(smumgr)) {
			pr_err("smc start failed\n");
			smumgr->smumgr_funcs->smu_fini(smumgr);
			return -EINVAL;;
		}
		if (ret == PP_DPM_DISABLED)
			return PP_DPM_DISABLED;
133
	}
134

135 136 137
	ret = hwmgr_hw_init(pp_handle);
	if (ret)
		goto err;
138
	return 0;
139 140 141 142 143
err:
	pp_handle->pm_en = 0;
	kfree(pp_handle->hwmgr);
	pp_handle->hwmgr = NULL;
	return PP_DPM_DISABLED;
144 145 146 147
}

static int pp_hw_fini(void *handle)
{
148 149
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
150

151
	ret = pp_check(pp_handle);
152
	if (ret == 0)
153
		hwmgr_hw_fini(pp_handle);
154

155 156 157 158 159
	return 0;
}

static bool pp_is_idle(void *handle)
{
160
	return false;
161 162 163 164 165 166 167 168 169 170 171 172 173
}

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

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


174
int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
175
{
176
	struct pp_hwmgr  *hwmgr;
177 178
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
179

180
	ret = pp_check(pp_handle);
181

182 183
	if (ret != 0)
		return ret;
184

185
	hwmgr = pp_handle->hwmgr;
186

187
	if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
188
		pr_info("%s was not implemented.\n", __func__);
189
		return 0;
190
	}
191

192
	return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
193 194 195 196 197
}

static int pp_set_powergating_state(void *handle,
				    enum amd_powergating_state state)
{
198
	struct pp_hwmgr  *hwmgr;
199 200
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
201

202
	ret = pp_check(pp_handle);
203

204 205
	if (ret != 0)
		return ret;
206

207
	hwmgr = pp_handle->hwmgr;
208 209

	if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
210
		pr_info("%s was not implemented.\n", __func__);
211 212
		return 0;
	}
213 214 215

	/* Enable/disable GFX per cu powergating through SMU */
	return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
216
			state == AMD_PG_STATE_GATE);
217 218 219 220
}

static int pp_suspend(void *handle)
{
221 222
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
223

224 225
	ret = pp_check(pp_handle);

226 227 228
	if (ret == PP_DPM_DISABLED)
		return 0;
	else if (ret != 0)
229
		return ret;
230

231
	return hwmgr_hw_suspend(pp_handle);
232 233 234 235
}

static int pp_resume(void *handle)
{
236
	struct pp_smumgr *smumgr;
237 238
	int ret, ret1;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
239

240 241 242 243
	ret1 = pp_check(pp_handle);

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

245 246
	smumgr = pp_handle->smu_mgr;

247
	if (smumgr->smumgr_funcs->start_smu == NULL)
248 249 250 251
		return -EINVAL;

	ret = smumgr->smumgr_funcs->start_smu(smumgr);
	if (ret) {
252
		pr_err("smc start failed\n");
253 254 255 256
		smumgr->smumgr_funcs->smu_fini(smumgr);
		return ret;
	}

257
	if (ret1 == PP_DPM_DISABLED)
M
Monk Liu 已提交
258
		return 0;
259

260
	return hwmgr_hw_resume(pp_handle);
261 262 263
}

const struct amd_ip_funcs pp_ip_funcs = {
264
	.name = "powerplay",
265 266 267 268 269 270 271 272 273 274 275
	.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,
276
	.set_clockgating_state = NULL,
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
	.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;
}

static int pp_dpm_force_performance_level(void *handle,
					enum amd_dpm_forced_level level)
{
293
	struct pp_hwmgr  *hwmgr;
294 295
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
296

297
	ret = pp_check(pp_handle);
298

299 300
	if (ret != 0)
		return ret;
301 302 303

	hwmgr = pp_handle->hwmgr;

304
	if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
305
		pr_info("%s was not implemented.\n", __func__);
306 307
		return 0;
	}
308

309
	mutex_lock(&pp_handle->pp_lock);
310
	hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
311
	hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
312
	mutex_unlock(&pp_handle->pp_lock);
313 314
	return 0;
}
315

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

324
	ret = pp_check(pp_handle);
325

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

329
	hwmgr = pp_handle->hwmgr;
330 331 332 333
	mutex_lock(&pp_handle->pp_lock);
	level = hwmgr->dpm_level;
	mutex_unlock(&pp_handle->pp_lock);
	return level;
334
}
335

336 337
static int pp_dpm_get_sclk(void *handle, bool low)
{
338
	struct pp_hwmgr  *hwmgr;
339 340
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
341

342
	ret = pp_check(pp_handle);
343

344 345
	if (ret != 0)
		return ret;
346

347
	hwmgr = pp_handle->hwmgr;
348 349

	if (hwmgr->hwmgr_func->get_sclk == NULL) {
350
		pr_info("%s was not implemented.\n", __func__);
351 352
		return 0;
	}
353 354 355 356
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
357
}
358

359 360
static int pp_dpm_get_mclk(void *handle, bool low)
{
361
	struct pp_hwmgr  *hwmgr;
362 363
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
364

365
	ret = pp_check(pp_handle);
366

367 368
	if (ret != 0)
		return ret;
369

370
	hwmgr = pp_handle->hwmgr;
371 372

	if (hwmgr->hwmgr_func->get_mclk == NULL) {
373
		pr_info("%s was not implemented.\n", __func__);
374 375
		return 0;
	}
376 377 378 379
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
380
}
381

382 383
static int pp_dpm_powergate_vce(void *handle, bool gate)
{
384
	struct pp_hwmgr  *hwmgr;
385 386
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
387

388
	ret = pp_check(pp_handle);
389

390 391
	if (ret != 0)
		return ret;
392

393
	hwmgr = pp_handle->hwmgr;
394 395

	if (hwmgr->hwmgr_func->powergate_vce == NULL) {
396
		pr_info("%s was not implemented.\n", __func__);
397 398
		return 0;
	}
399 400 401 402
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
403
}
404

405 406
static int pp_dpm_powergate_uvd(void *handle, bool gate)
{
407
	struct pp_hwmgr  *hwmgr;
408 409
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
410

411
	ret = pp_check(pp_handle);
412

413 414
	if (ret != 0)
		return ret;
415

416
	hwmgr = pp_handle->hwmgr;
417 418

	if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
419
		pr_info("%s was not implemented.\n", __func__);
420 421
		return 0;
	}
422 423 424 425
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
426 427
}

428
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
429
		void *input, void *output)
430
{
431
	int ret = 0;
432
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
433

434
	ret = pp_check(pp_handle);
435

436 437
	if (ret != 0)
		return ret;
438

439 440
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr_handle_task(pp_handle, task_id, input, output);
441
	mutex_unlock(&pp_handle->pp_lock);
442

443
	return ret;
444
}
445

446
static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
447
{
448 449
	struct pp_hwmgr *hwmgr;
	struct pp_power_state *state;
450 451
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
452
	enum amd_pm_state_type pm_type;
453

454
	ret = pp_check(pp_handle);
455

456 457
	if (ret != 0)
		return ret;
458

459 460 461
	hwmgr = pp_handle->hwmgr;

	if (hwmgr->current_ps == NULL)
462 463
		return -EINVAL;

464 465
	mutex_lock(&pp_handle->pp_lock);

466 467 468 469
	state = hwmgr->current_ps;

	switch (state->classification.ui_label) {
	case PP_StateUILabel_Battery:
470
		pm_type = POWER_STATE_TYPE_BATTERY;
471
		break;
472
	case PP_StateUILabel_Balanced:
473
		pm_type = POWER_STATE_TYPE_BALANCED;
474
		break;
475
	case PP_StateUILabel_Performance:
476
		pm_type = POWER_STATE_TYPE_PERFORMANCE;
477
		break;
478
	default:
479
		if (state->classification.flags & PP_StateClassificationFlag_Boot)
480
			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
481
		else
482
			pm_type = POWER_STATE_TYPE_DEFAULT;
483
		break;
484
	}
485 486 487
	mutex_unlock(&pp_handle->pp_lock);

	return pm_type;
488
}
489

490 491 492
static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
{
	struct pp_hwmgr  *hwmgr;
493 494
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
495

496
	ret = pp_check(pp_handle);
497

498 499
	if (ret != 0)
		return ret;
500

501
	hwmgr = pp_handle->hwmgr;
502 503

	if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
504
		pr_info("%s was not implemented.\n", __func__);
505 506
		return 0;
	}
507 508 509 510
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
511 512 513 514 515
}

static int pp_dpm_get_fan_control_mode(void *handle)
{
	struct pp_hwmgr  *hwmgr;
516 517
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
518

519
	ret = pp_check(pp_handle);
520

521 522
	if (ret != 0)
		return ret;
523

524
	hwmgr = pp_handle->hwmgr;
525 526

	if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
527
		pr_info("%s was not implemented.\n", __func__);
528 529
		return 0;
	}
530 531 532 533
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
534 535 536 537 538
}

static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
{
	struct pp_hwmgr  *hwmgr;
539 540
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
541

542
	ret = pp_check(pp_handle);
543

544 545
	if (ret != 0)
		return ret;
546

547
	hwmgr = pp_handle->hwmgr;
548 549

	if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
550
		pr_info("%s was not implemented.\n", __func__);
551 552
		return 0;
	}
553 554 555 556
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
557 558 559 560 561
}

static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
{
	struct pp_hwmgr  *hwmgr;
562 563
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
564

565
	ret = pp_check(pp_handle);
566

567 568
	if (ret != 0)
		return ret;
569

570
	hwmgr = pp_handle->hwmgr;
571 572

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

577 578 579 580
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
581 582
}

583 584 585
static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
{
	struct pp_hwmgr *hwmgr;
586 587
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
588

589
	ret = pp_check(pp_handle);
590

591 592
	if (ret != 0)
		return ret;
593

594
	hwmgr = pp_handle->hwmgr;
595 596 597 598

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

599 600 601 602
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
603 604
}

605 606 607
static int pp_dpm_get_temperature(void *handle)
{
	struct pp_hwmgr  *hwmgr;
608 609
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
610

611
	ret = pp_check(pp_handle);
612

613 614
	if (ret != 0)
		return ret;
615

616
	hwmgr = pp_handle->hwmgr;
617 618

	if (hwmgr->hwmgr_func->get_temperature == NULL) {
619
		pr_info("%s was not implemented.\n", __func__);
620 621
		return 0;
	}
622 623 624 625
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
626
}
627

628 629 630 631 632
static int pp_dpm_get_pp_num_states(void *handle,
		struct pp_states_info *data)
{
	struct pp_hwmgr *hwmgr;
	int i;
633 634
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
635

636
	ret = pp_check(pp_handle);
637

638 639 640 641
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
642

643
	if (hwmgr->ps == NULL)
644 645
		return -EINVAL;

646 647
	mutex_lock(&pp_handle->pp_lock);

648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
	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;
		}
	}
670
	mutex_unlock(&pp_handle->pp_lock);
671 672 673 674 675 676
	return 0;
}

static int pp_dpm_get_pp_table(void *handle, char **table)
{
	struct pp_hwmgr *hwmgr;
677 678
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
679
	int size = 0;
680

681
	ret = pp_check(pp_handle);
682

683 684
	if (ret != 0)
		return ret;
685

686
	hwmgr = pp_handle->hwmgr;
687

688 689 690
	if (!hwmgr->soft_pp_table)
		return -EINVAL;

691
	mutex_lock(&pp_handle->pp_lock);
692
	*table = (char *)hwmgr->soft_pp_table;
693 694 695
	size = hwmgr->soft_pp_table_size;
	mutex_unlock(&pp_handle->pp_lock);
	return size;
696 697 698 699 700
}

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

704
	ret = pp_check(pp_handle);
705

706 707
	if (ret != 0)
		return ret;
708

709
	hwmgr = pp_handle->hwmgr;
710
	mutex_lock(&pp_handle->pp_lock);
711
	if (!hwmgr->hardcode_pp_table) {
712 713 714
		hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
						   hwmgr->soft_pp_table_size,
						   GFP_KERNEL);
715 716
		if (!hwmgr->hardcode_pp_table) {
			mutex_unlock(&pp_handle->pp_lock);
717
			return -ENOMEM;
718
		}
719
	}
720

721 722 723
	memcpy(hwmgr->hardcode_pp_table, buf, size);

	hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
724
	mutex_unlock(&pp_handle->pp_lock);
725

726 727 728 729 730 731 732 733 734 735 736
	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;
737 738 739
}

static int pp_dpm_force_clock_level(void *handle,
740
		enum pp_clock_type type, uint32_t mask)
741 742
{
	struct pp_hwmgr *hwmgr;
743 744
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
745

746
	ret = pp_check(pp_handle);
747

748 749
	if (ret != 0)
		return ret;
750

751
	hwmgr = pp_handle->hwmgr;
752 753

	if (hwmgr->hwmgr_func->force_clock_level == NULL) {
754
		pr_info("%s was not implemented.\n", __func__);
755 756
		return 0;
	}
757 758 759 760
	mutex_lock(&pp_handle->pp_lock);
	hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
761 762 763 764 765 766
}

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

770
	ret = pp_check(pp_handle);
771

772 773
	if (ret != 0)
		return ret;
774

775
	hwmgr = pp_handle->hwmgr;
776

777
	if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
778
		pr_info("%s was not implemented.\n", __func__);
779 780
		return 0;
	}
781 782 783 784
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
785 786
}

787 788 789
static int pp_dpm_get_sclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
790 791
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
792

793
	ret = pp_check(pp_handle);
794

795 796
	if (ret != 0)
		return ret;
797

798
	hwmgr = pp_handle->hwmgr;
799 800

	if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
801
		pr_info("%s was not implemented.\n", __func__);
802 803
		return 0;
	}
804 805 806 807
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
808 809 810 811 812
}

static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
813 814
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
815

816
	ret = pp_check(pp_handle);
817

818 819
	if (ret != 0)
		return ret;
820

821
	hwmgr = pp_handle->hwmgr;
822 823

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

828 829
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
830
	mutex_unlock(&pp_handle->pp_lock);
831
	return ret;
832 833
}

834 835 836
static int pp_dpm_get_mclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
837 838
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
839

840
	ret = pp_check(pp_handle);
841

842 843
	if (ret != 0)
		return ret;
844

845
	hwmgr = pp_handle->hwmgr;
846 847

	if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
848
		pr_info("%s was not implemented.\n", __func__);
849 850
		return 0;
	}
851 852 853 854
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
855 856 857 858 859
}

static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
860 861
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
862

863
	ret = pp_check(pp_handle);
864

865 866
	if (ret != 0)
		return ret;
867

868
	hwmgr = pp_handle->hwmgr;
869 870

	if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
871
		pr_info("%s was not implemented.\n", __func__);
872 873
		return 0;
	}
874 875 876 877
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
878 879
}

880 881
static int pp_dpm_read_sensor(void *handle, int idx,
			      void *value, int *size)
882 883
{
	struct pp_hwmgr *hwmgr;
884 885
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
886

887
	ret = pp_check(pp_handle);
888

889 890
	if (ret != 0)
		return ret;
891

892
	hwmgr = pp_handle->hwmgr;
893 894

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

899 900 901 902 903
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
	mutex_unlock(&pp_handle->pp_lock);

	return ret;
904 905
}

906 907 908 909
static struct amd_vce_state*
pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
{
	struct pp_hwmgr *hwmgr;
910 911
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
912

913
	ret = pp_check(pp_handle);
914

915 916 917 918 919 920 921
	if (ret != 0)
		return NULL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr && idx < hwmgr->num_vce_state_tables)
		return &hwmgr->vce_states[idx];
922 923 924
	return NULL;
}

925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 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
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;
}

1056
const struct amd_powerplay_funcs pp_dpm_funcs = {
1057
	.get_temperature = pp_dpm_get_temperature,
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
	.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,
1068 1069 1070 1071
	.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,
1072
	.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1073 1074 1075 1076 1077
	.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,
1078 1079
	.get_sclk_od = pp_dpm_get_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
1080 1081
	.get_mclk_od = pp_dpm_get_mclk_od,
	.set_mclk_od = pp_dpm_set_mclk_od,
1082
	.read_sensor = pp_dpm_read_sensor,
1083
	.get_vce_clock_state = pp_dpm_get_vce_clock_state,
1084 1085 1086 1087
	.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,
1088 1089
};

1090 1091
int amd_powerplay_create(struct amd_pp_init *pp_init,
				void **handle)
1092
{
1093
	struct pp_instance *instance;
1094

1095 1096
	if (pp_init == NULL || handle == NULL)
		return -EINVAL;
1097

1098 1099 1100
	instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
	if (instance == NULL)
		return -ENOMEM;
1101

1102 1103 1104 1105 1106 1107
	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;
1108
	mutex_init(&instance->pp_lock);
1109
	*handle = instance;
1110 1111 1112
	return 0;
}

1113
int amd_powerplay_destroy(void *handle)
1114 1115
{
	struct pp_instance *instance = (struct pp_instance *)handle;
1116

1117 1118 1119
	if (instance->pm_en) {
		kfree(instance->hwmgr);
		instance->hwmgr = NULL;
1120
	}
1121

1122 1123 1124 1125
	kfree(instance->smu_mgr);
	instance->smu_mgr = NULL;
	kfree(instance);
	instance = NULL;
1126 1127
	return 0;
}
1128

1129 1130 1131 1132 1133
int amd_powerplay_reset(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;
	int ret;

1134 1135
	if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
		return PP_DPM_DISABLED;
1136

1137 1138
	ret = pp_check(instance);
	if (ret != 0)
1139 1140
		return ret;

1141
	ret = pp_hw_fini(instance);
1142 1143 1144
	if (ret)
		return ret;

1145 1146 1147
	ret = hwmgr_hw_init(instance);
	if (ret)
		return PP_DPM_DISABLED;
1148

1149
	return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
1150 1151
}

1152 1153
/* export this function to DAL */

1154 1155
int amd_powerplay_display_configuration_change(void *handle,
	const struct amd_pp_display_configuration *display_config)
1156 1157
{
	struct pp_hwmgr  *hwmgr;
1158 1159
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1160

1161
	ret = pp_check(pp_handle);
1162

1163 1164
	if (ret != 0)
		return ret;
1165

1166
	hwmgr = pp_handle->hwmgr;
1167
	mutex_lock(&pp_handle->pp_lock);
1168
	phm_store_dal_configuration_data(hwmgr, display_config);
1169
	mutex_unlock(&pp_handle->pp_lock);
1170 1171
	return 0;
}
1172

1173
int amd_powerplay_get_display_power_level(void *handle,
R
Rex Zhu 已提交
1174
		struct amd_pp_simple_clock_info *output)
1175 1176
{
	struct pp_hwmgr  *hwmgr;
1177 1178
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1179

1180
	ret = pp_check(pp_handle);
1181

1182 1183
	if (ret != 0)
		return ret;
1184

1185
	hwmgr = pp_handle->hwmgr;
1186

1187 1188
	if (output == NULL)
		return -EINVAL;
1189

1190 1191 1192 1193
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_dal_power_level(hwmgr, output);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1194
}
1195 1196

int amd_powerplay_get_current_clocks(void *handle,
1197
		struct amd_pp_clock_info *clocks)
1198 1199 1200
{
	struct amd_pp_simple_clock_info simple_clocks;
	struct pp_clock_info hw_clocks;
1201 1202 1203
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1204

1205
	ret = pp_check(pp_handle);
1206

1207 1208
	if (ret != 0)
		return ret;
1209

1210
	hwmgr = pp_handle->hwmgr;
1211

1212 1213
	mutex_lock(&pp_handle->pp_lock);

1214 1215
	phm_get_dal_power_level(hwmgr, &simple_clocks);

1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
	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;
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
	}

	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;
	}
1246
	mutex_unlock(&pp_handle->pp_lock);
1247 1248 1249 1250 1251
	return 0;
}

int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
{
1252 1253 1254
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1255

1256
	ret = pp_check(pp_handle);
1257

1258 1259 1260 1261
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
1262 1263

	if (clocks == NULL)
1264 1265
		return -EINVAL;

1266 1267 1268 1269
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_clock_by_type(hwmgr, type, clocks);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1270 1271
}

1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 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
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;
}

1366 1367
int amd_powerplay_get_display_mode_validation_clocks(void *handle,
		struct amd_pp_simple_clock_info *clocks)
1368 1369
{
	struct pp_hwmgr  *hwmgr;
1370 1371
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1372

1373
	ret = pp_check(pp_handle);
1374

1375 1376 1377 1378
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
1379

1380 1381
	if (clocks == NULL)
		return -EINVAL;
1382

1383 1384
	mutex_lock(&pp_handle->pp_lock);

1385
	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1386
		ret = phm_get_max_high_clocks(hwmgr, clocks);
1387

1388
	mutex_unlock(&pp_handle->pp_lock);
1389
	return ret;
1390 1391
}