amd_powerplay.c 32.6 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
#define PP_DPM_DISABLED 0xCCCC

R
Rex Zhu 已提交
35 36 37
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
		void *input, void *output);

38
static inline int pp_check(struct pp_instance *handle)
39
{
40 41
	if (handle == NULL || handle->pp_valid != PP_VALID)
		return -EINVAL;
42

43
	if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL)
44 45
		return -EINVAL;

46 47
	if (handle->pm_en == 0)
		return PP_DPM_DISABLED;
48

49
	if (handle->hwmgr->hwmgr_func == NULL)
50
		return PP_DPM_DISABLED;
51

52 53
	return 0;
}
54

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
static int amd_powerplay_create(struct amd_pp_init *pp_init,
				void **handle)
{
	struct pp_instance *instance;

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

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

	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;
	mutex_init(&instance->pp_lock);
	*handle = instance;
	return 0;
}

static int amd_powerplay_destroy(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;

	kfree(instance->hwmgr);
	instance->hwmgr = NULL;

	kfree(instance);
	instance = NULL;
	return 0;
}

90 91 92
static int pp_early_init(void *handle)
{
	int ret;
93 94 95 96 97 98
	struct pp_instance *pp_handle = NULL;

	pp_handle = cgs_register_pp_handle(handle, amd_powerplay_create);

	if (!pp_handle)
		return -EINVAL;
99

100
	ret = hwmgr_early_init(pp_handle);
101
	if (ret)
102
		return -EINVAL;
103

104
	return 0;
105 106
}

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

113
	ret = pp_check(pp_handle);
114

115
	if (ret >= 0) {
116
		hwmgr = pp_handle->hwmgr;
117

118
		if (hwmgr->smumgr_funcs->smu_init == NULL)
119
			return -EINVAL;
120

121
		ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
122

123 124 125 126
		pr_info("amdgpu: powerplay sw initialized\n");
	}
	return ret;
}
127

128 129
static int pp_sw_fini(void *handle)
{
130
	struct pp_hwmgr *hwmgr;
131 132 133 134
	int ret = 0;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	ret = pp_check(pp_handle);
135
	if (ret >= 0) {
136
		hwmgr = pp_handle->hwmgr;
137

138
		if (hwmgr->smumgr_funcs->smu_fini == NULL)
139 140
			return -EINVAL;

141
		ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
142
	}
143
	return ret;
144 145 146 147
}

static int pp_hw_init(void *handle)
{
148
	int ret = 0;
149
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
150
	struct pp_hwmgr *hwmgr;
151

152
	ret = pp_check(pp_handle);
153

154
	if (ret >= 0) {
155
		hwmgr = pp_handle->hwmgr;
156

157
		if (hwmgr->smumgr_funcs->start_smu == NULL)
158
			return -EINVAL;
159

160
		if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
161
			pr_err("smc start failed\n");
162
			hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
163 164 165
			return -EINVAL;;
		}
		if (ret == PP_DPM_DISABLED)
166 167 168 169
			goto exit;
		ret = hwmgr_hw_init(pp_handle);
		if (ret)
			goto exit;
170
	}
171 172
	return ret;
exit:
173
	pp_handle->pm_en = 0;
174 175 176
	cgs_notify_dpm_enabled(hwmgr->device, false);
	return 0;

177 178 179 180
}

static int pp_hw_fini(void *handle)
{
181 182
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
183

184
	ret = pp_check(pp_handle);
185
	if (ret == 0)
186
		hwmgr_hw_fini(pp_handle);
187

188 189 190
	return 0;
}

R
Rex Zhu 已提交
191 192 193 194 195 196 197 198 199 200 201 202 203
static int pp_late_init(void *handle)
{
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;

	ret = pp_check(pp_handle);
	if (ret == 0)
		pp_dpm_dispatch_tasks(pp_handle,
					AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);

	return 0;
}

204 205 206 207 208 209
static void pp_late_fini(void *handle)
{
	amd_powerplay_destroy(handle);
}


210 211
static bool pp_is_idle(void *handle)
{
212
	return false;
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
}

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

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

static int pp_set_powergating_state(void *handle,
				    enum amd_powergating_state state)
{
228
	struct pp_hwmgr  *hwmgr;
229 230
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
231

232
	ret = pp_check(pp_handle);
233

234
	if (ret)
235
		return ret;
236

237
	hwmgr = pp_handle->hwmgr;
238 239

	if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
240
		pr_info("%s was not implemented.\n", __func__);
241 242
		return 0;
	}
243 244 245

	/* Enable/disable GFX per cu powergating through SMU */
	return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
246
			state == AMD_PG_STATE_GATE);
247 248 249 250
}

static int pp_suspend(void *handle)
{
251 252
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
253

254
	ret = pp_check(pp_handle);
255 256 257
	if (ret == 0)
		hwmgr_hw_suspend(pp_handle);
	return 0;
258 259 260 261
}

static int pp_resume(void *handle)
{
262
	struct pp_hwmgr  *hwmgr;
263
	int ret;
264
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
265

266
	ret = pp_check(pp_handle);
267

268 269
	if (ret < 0)
		return ret;
270

271
	hwmgr = pp_handle->hwmgr;
272

273
	if (hwmgr->smumgr_funcs->start_smu == NULL)
274 275
		return -EINVAL;

276
	if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
277
		pr_err("smc start failed\n");
278
		hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
279
		return -EINVAL;
280 281
	}

282
	if (ret == PP_DPM_DISABLED)
M
Monk Liu 已提交
283
		return 0;
284

285
	return hwmgr_hw_resume(pp_handle);
286 287 288
}

const struct amd_ip_funcs pp_ip_funcs = {
289
	.name = "powerplay",
290
	.early_init = pp_early_init,
R
Rex Zhu 已提交
291
	.late_init = pp_late_init,
292 293 294 295
	.sw_init = pp_sw_init,
	.sw_fini = pp_sw_fini,
	.hw_init = pp_hw_init,
	.hw_fini = pp_hw_fini,
296
	.late_fini = pp_late_fini,
297 298 299 300 301
	.suspend = pp_suspend,
	.resume = pp_resume,
	.is_idle = pp_is_idle,
	.wait_for_idle = pp_wait_for_idle,
	.soft_reset = pp_sw_reset,
302
	.set_clockgating_state = NULL,
303 304 305 306 307 308 309 310 311 312 313 314 315
	.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;
}

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
{
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;

	ret = pp_check(pp_handle);

	if (ret)
		return ret;

	hwmgr = pp_handle->hwmgr;

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

	return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
}

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
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);
		}
	}
}

373 374 375
static int pp_dpm_force_performance_level(void *handle,
					enum amd_dpm_forced_level level)
{
376
	struct pp_hwmgr  *hwmgr;
377 378
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
379

380
	ret = pp_check(pp_handle);
381

382
	if (ret)
383
		return ret;
384 385 386

	hwmgr = pp_handle->hwmgr;

387 388 389
	if (level == hwmgr->dpm_level)
		return 0;

390
	if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
391
		pr_info("%s was not implemented.\n", __func__);
392 393
		return 0;
	}
394

395
	mutex_lock(&pp_handle->pp_lock);
396 397
	pp_dpm_en_umd_pstate(hwmgr, &level);
	hwmgr->request_dpm_level = level;
398
	hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
399 400 401 402
	ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
	if (!ret)
		hwmgr->dpm_level = hwmgr->request_dpm_level;

403
	mutex_unlock(&pp_handle->pp_lock);
404 405
	return 0;
}
406

407 408 409
static enum amd_dpm_forced_level pp_dpm_get_performance_level(
								void *handle)
{
410
	struct pp_hwmgr  *hwmgr;
411 412
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
413
	enum amd_dpm_forced_level level;
414

415
	ret = pp_check(pp_handle);
416

417
	if (ret)
418
		return ret;
419

420
	hwmgr = pp_handle->hwmgr;
421 422 423 424
	mutex_lock(&pp_handle->pp_lock);
	level = hwmgr->dpm_level;
	mutex_unlock(&pp_handle->pp_lock);
	return level;
425
}
426

427
static uint32_t pp_dpm_get_sclk(void *handle, bool low)
428
{
429
	struct pp_hwmgr  *hwmgr;
430 431
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
432
	uint32_t clk = 0;
433

434
	ret = pp_check(pp_handle);
435

436
	if (ret)
437
		return ret;
438

439
	hwmgr = pp_handle->hwmgr;
440 441

	if (hwmgr->hwmgr_func->get_sclk == NULL) {
442
		pr_info("%s was not implemented.\n", __func__);
443 444
		return 0;
	}
445
	mutex_lock(&pp_handle->pp_lock);
446
	clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
447
	mutex_unlock(&pp_handle->pp_lock);
448
	return clk;
449
}
450

451
static uint32_t pp_dpm_get_mclk(void *handle, bool low)
452
{
453
	struct pp_hwmgr  *hwmgr;
454 455
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
456
	uint32_t clk = 0;
457

458
	ret = pp_check(pp_handle);
459

460
	if (ret)
461
		return ret;
462

463
	hwmgr = pp_handle->hwmgr;
464 465

	if (hwmgr->hwmgr_func->get_mclk == NULL) {
466
		pr_info("%s was not implemented.\n", __func__);
467 468
		return 0;
	}
469
	mutex_lock(&pp_handle->pp_lock);
470
	clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
471
	mutex_unlock(&pp_handle->pp_lock);
472
	return clk;
473
}
474

475
static void pp_dpm_powergate_vce(void *handle, bool gate)
476
{
477
	struct pp_hwmgr  *hwmgr;
478 479
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
480

481
	ret = pp_check(pp_handle);
482

483
	if (ret)
484
		return;
485

486
	hwmgr = pp_handle->hwmgr;
487 488

	if (hwmgr->hwmgr_func->powergate_vce == NULL) {
489
		pr_info("%s was not implemented.\n", __func__);
490
		return;
491
	}
492
	mutex_lock(&pp_handle->pp_lock);
493
	hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
494
	mutex_unlock(&pp_handle->pp_lock);
495
}
496

497
static void pp_dpm_powergate_uvd(void *handle, bool gate)
498
{
499
	struct pp_hwmgr  *hwmgr;
500 501
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
502

503
	ret = pp_check(pp_handle);
504

505
	if (ret)
506
		return;
507

508
	hwmgr = pp_handle->hwmgr;
509 510

	if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
511
		pr_info("%s was not implemented.\n", __func__);
512
		return;
513
	}
514
	mutex_lock(&pp_handle->pp_lock);
515
	hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
516
	mutex_unlock(&pp_handle->pp_lock);
517 518
}

519
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
520
		void *input, void *output)
521
{
522
	int ret = 0;
523
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
524

525
	ret = pp_check(pp_handle);
526

527
	if (ret)
528
		return ret;
529

530 531
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr_handle_task(pp_handle, task_id, input, output);
532
	mutex_unlock(&pp_handle->pp_lock);
533

534
	return ret;
535
}
536

537
static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
538
{
539 540
	struct pp_hwmgr *hwmgr;
	struct pp_power_state *state;
541 542
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
543
	enum amd_pm_state_type pm_type;
544

545
	ret = pp_check(pp_handle);
546

547
	if (ret)
548
		return ret;
549

550 551 552
	hwmgr = pp_handle->hwmgr;

	if (hwmgr->current_ps == NULL)
553 554
		return -EINVAL;

555 556
	mutex_lock(&pp_handle->pp_lock);

557 558 559 560
	state = hwmgr->current_ps;

	switch (state->classification.ui_label) {
	case PP_StateUILabel_Battery:
561
		pm_type = POWER_STATE_TYPE_BATTERY;
562
		break;
563
	case PP_StateUILabel_Balanced:
564
		pm_type = POWER_STATE_TYPE_BALANCED;
565
		break;
566
	case PP_StateUILabel_Performance:
567
		pm_type = POWER_STATE_TYPE_PERFORMANCE;
568
		break;
569
	default:
570
		if (state->classification.flags & PP_StateClassificationFlag_Boot)
571
			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
572
		else
573
			pm_type = POWER_STATE_TYPE_DEFAULT;
574
		break;
575
	}
576 577 578
	mutex_unlock(&pp_handle->pp_lock);

	return pm_type;
579
}
580

581
static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
582 583
{
	struct pp_hwmgr  *hwmgr;
584 585
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
586

587
	ret = pp_check(pp_handle);
588

589
	if (ret)
590
		return;
591

592
	hwmgr = pp_handle->hwmgr;
593 594

	if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
595
		pr_info("%s was not implemented.\n", __func__);
596
		return;
597
	}
598
	mutex_lock(&pp_handle->pp_lock);
599
	hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
600
	mutex_unlock(&pp_handle->pp_lock);
601 602
}

603
static uint32_t pp_dpm_get_fan_control_mode(void *handle)
604 605
{
	struct pp_hwmgr  *hwmgr;
606 607
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
608
	uint32_t mode = 0;
609

610
	ret = pp_check(pp_handle);
611

612
	if (ret)
613
		return ret;
614

615
	hwmgr = pp_handle->hwmgr;
616 617

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

static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
{
	struct pp_hwmgr  *hwmgr;
630 631
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
632

633
	ret = pp_check(pp_handle);
634

635
	if (ret)
636
		return ret;
637

638
	hwmgr = pp_handle->hwmgr;
639 640

	if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
641
		pr_info("%s was not implemented.\n", __func__);
642 643
		return 0;
	}
644 645 646 647
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
648 649 650 651 652
}

static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
{
	struct pp_hwmgr  *hwmgr;
653 654
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
655

656
	ret = pp_check(pp_handle);
657

658
	if (ret)
659
		return ret;
660

661
	hwmgr = pp_handle->hwmgr;
662 663

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

668 669 670 671
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
672 673
}

674 675 676
static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
{
	struct pp_hwmgr *hwmgr;
677 678
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
679

680
	ret = pp_check(pp_handle);
681

682
	if (ret)
683
		return ret;
684

685
	hwmgr = pp_handle->hwmgr;
686 687 688 689

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

690 691 692 693
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
694 695
}

696 697 698
static int pp_dpm_get_temperature(void *handle)
{
	struct pp_hwmgr  *hwmgr;
699 700
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
701

702
	ret = pp_check(pp_handle);
703

704
	if (ret)
705
		return ret;
706

707
	hwmgr = pp_handle->hwmgr;
708 709

	if (hwmgr->hwmgr_func->get_temperature == NULL) {
710
		pr_info("%s was not implemented.\n", __func__);
711 712
		return 0;
	}
713 714 715 716
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
717
}
718

719 720 721 722 723
static int pp_dpm_get_pp_num_states(void *handle,
		struct pp_states_info *data)
{
	struct pp_hwmgr *hwmgr;
	int i;
724 725
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
726

727
	ret = pp_check(pp_handle);
728

729
	if (ret)
730 731 732
		return ret;

	hwmgr = pp_handle->hwmgr;
733

734
	if (hwmgr->ps == NULL)
735 736
		return -EINVAL;

737 738
	mutex_lock(&pp_handle->pp_lock);

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
	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;
		}
	}
761
	mutex_unlock(&pp_handle->pp_lock);
762 763 764 765 766 767
	return 0;
}

static int pp_dpm_get_pp_table(void *handle, char **table)
{
	struct pp_hwmgr *hwmgr;
768 769
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
770
	int size = 0;
771

772
	ret = pp_check(pp_handle);
773

774
	if (ret)
775
		return ret;
776

777
	hwmgr = pp_handle->hwmgr;
778

779 780 781
	if (!hwmgr->soft_pp_table)
		return -EINVAL;

782
	mutex_lock(&pp_handle->pp_lock);
783
	*table = (char *)hwmgr->soft_pp_table;
784 785 786
	size = hwmgr->soft_pp_table_size;
	mutex_unlock(&pp_handle->pp_lock);
	return size;
787 788 789 790 791
}

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

795
	ret = pp_check(pp_handle);
796

797
	if (ret)
798
		return ret;
799

800
	hwmgr = pp_handle->hwmgr;
801
	mutex_lock(&pp_handle->pp_lock);
802
	if (!hwmgr->hardcode_pp_table) {
803 804 805
		hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
						   hwmgr->soft_pp_table_size,
						   GFP_KERNEL);
806 807
		if (!hwmgr->hardcode_pp_table) {
			mutex_unlock(&pp_handle->pp_lock);
808
			return -ENOMEM;
809
		}
810
	}
811

812 813 814
	memcpy(hwmgr->hardcode_pp_table, buf, size);

	hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
815
	mutex_unlock(&pp_handle->pp_lock);
816

817 818 819 820 821 822 823 824 825 826 827
	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;
828 829 830
}

static int pp_dpm_force_clock_level(void *handle,
831
		enum pp_clock_type type, uint32_t mask)
832 833
{
	struct pp_hwmgr *hwmgr;
834 835
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
836

837
	ret = pp_check(pp_handle);
838

839
	if (ret)
840
		return ret;
841

842
	hwmgr = pp_handle->hwmgr;
843 844

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

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

861
	ret = pp_check(pp_handle);
862

863
	if (ret)
864
		return ret;
865

866
	hwmgr = pp_handle->hwmgr;
867

868
	if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
869
		pr_info("%s was not implemented.\n", __func__);
870 871
		return 0;
	}
872 873 874 875
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
876 877
}

878 879 880
static int pp_dpm_get_sclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
881 882
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
883

884
	ret = pp_check(pp_handle);
885

886
	if (ret)
887
		return ret;
888

889
	hwmgr = pp_handle->hwmgr;
890 891

	if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
892
		pr_info("%s was not implemented.\n", __func__);
893 894
		return 0;
	}
895 896 897 898
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
899 900 901 902 903
}

static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
904 905
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
906

907
	ret = pp_check(pp_handle);
908

909
	if (ret)
910
		return ret;
911

912
	hwmgr = pp_handle->hwmgr;
913 914

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

919 920
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
921
	mutex_unlock(&pp_handle->pp_lock);
922
	return ret;
923 924
}

925 926 927
static int pp_dpm_get_mclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
928 929
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
930

931
	ret = pp_check(pp_handle);
932

933
	if (ret)
934
		return ret;
935

936
	hwmgr = pp_handle->hwmgr;
937 938

	if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
939
		pr_info("%s was not implemented.\n", __func__);
940 941
		return 0;
	}
942 943 944 945
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
946 947 948 949 950
}

static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
951 952
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
953

954
	ret = pp_check(pp_handle);
955

956
	if (ret)
957
		return ret;
958

959
	hwmgr = pp_handle->hwmgr;
960 961

	if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
962
		pr_info("%s was not implemented.\n", __func__);
963 964
		return 0;
	}
965 966 967 968
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
969 970
}

971 972
static int pp_dpm_read_sensor(void *handle, int idx,
			      void *value, int *size)
973 974
{
	struct pp_hwmgr *hwmgr;
975 976
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
977

978
	ret = pp_check(pp_handle);
979

980
	if (ret)
981
		return ret;
982

983
	hwmgr = pp_handle->hwmgr;
984 985

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

990 991 992 993 994
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
	mutex_unlock(&pp_handle->pp_lock);

	return ret;
995 996
}

997 998 999 1000
static struct amd_vce_state*
pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
{
	struct pp_hwmgr *hwmgr;
1001 1002
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1003

1004
	ret = pp_check(pp_handle);
1005

1006
	if (ret)
1007 1008 1009 1010 1011 1012
		return NULL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr && idx < hwmgr->num_vce_state_tables)
		return &hwmgr->vce_states[idx];
1013 1014 1015
	return NULL;
}

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 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
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;
}

1147
const struct amd_pm_funcs pp_dpm_funcs = {
1148
	.get_temperature = pp_dpm_get_temperature,
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
	.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,
1159 1160 1161 1162
	.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,
1163
	.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1164 1165 1166 1167 1168
	.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,
1169 1170
	.get_sclk_od = pp_dpm_get_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
1171 1172
	.get_mclk_od = pp_dpm_get_mclk_od,
	.set_mclk_od = pp_dpm_set_mclk_od,
1173
	.read_sensor = pp_dpm_read_sensor,
1174
	.get_vce_clock_state = pp_dpm_get_vce_clock_state,
1175 1176 1177 1178
	.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,
1179
	.set_clockgating_by_smu = pp_set_clockgating_by_smu,
1180 1181
};

1182 1183 1184 1185 1186
int amd_powerplay_reset(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;
	int ret;

1187
	ret = pp_check(instance);
1188
	if (!ret)
1189 1190
		return ret;

1191
	ret = pp_hw_fini(instance);
1192 1193 1194
	if (ret)
		return ret;

1195 1196
	ret = hwmgr_hw_init(instance);
	if (ret)
1197
		return ret;
1198

1199
	return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
1200 1201
}

1202 1203
/* export this function to DAL */

1204 1205
int amd_powerplay_display_configuration_change(void *handle,
	const struct amd_pp_display_configuration *display_config)
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
	if (ret)
1214
		return ret;
1215

1216
	hwmgr = pp_handle->hwmgr;
1217
	mutex_lock(&pp_handle->pp_lock);
1218
	phm_store_dal_configuration_data(hwmgr, display_config);
1219
	mutex_unlock(&pp_handle->pp_lock);
1220 1221
	return 0;
}
1222

1223
int amd_powerplay_get_display_power_level(void *handle,
R
Rex Zhu 已提交
1224
		struct amd_pp_simple_clock_info *output)
1225 1226
{
	struct pp_hwmgr  *hwmgr;
1227 1228
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1229

1230
	ret = pp_check(pp_handle);
1231

1232
	if (ret)
1233
		return ret;
1234

1235
	hwmgr = pp_handle->hwmgr;
1236

1237 1238
	if (output == NULL)
		return -EINVAL;
1239

1240 1241 1242 1243
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_dal_power_level(hwmgr, output);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1244
}
1245 1246

int amd_powerplay_get_current_clocks(void *handle,
1247
		struct amd_pp_clock_info *clocks)
1248 1249 1250
{
	struct amd_pp_simple_clock_info simple_clocks;
	struct pp_clock_info hw_clocks;
1251 1252 1253
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1254

1255
	ret = pp_check(pp_handle);
1256

1257
	if (ret)
1258
		return ret;
1259

1260
	hwmgr = pp_handle->hwmgr;
1261

1262 1263
	mutex_lock(&pp_handle->pp_lock);

1264 1265
	phm_get_dal_power_level(hwmgr, &simple_clocks);

1266 1267 1268 1269 1270 1271 1272 1273
	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);

1274
	if (ret) {
1275 1276 1277
		pr_info("Error in phm_get_clock_info \n");
		mutex_unlock(&pp_handle->pp_lock);
		return -EINVAL;
1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
	}

	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;
	}
1296
	mutex_unlock(&pp_handle->pp_lock);
1297 1298 1299 1300 1301
	return 0;
}

int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
{
1302 1303 1304
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1305

1306
	ret = pp_check(pp_handle);
1307

1308
	if (ret)
1309 1310 1311
		return ret;

	hwmgr = pp_handle->hwmgr;
1312 1313

	if (clocks == NULL)
1314 1315
		return -EINVAL;

1316 1317 1318 1319
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_clock_by_type(hwmgr, type, clocks);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1320 1321
}

1322 1323 1324 1325 1326 1327 1328 1329 1330
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);
1331
	if (ret)
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
		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);
1353
	if (ret)
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
		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);
1377
	if (ret)
1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
		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);
1401
	if (ret)
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
		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;
}

1416 1417
int amd_powerplay_get_display_mode_validation_clocks(void *handle,
		struct amd_pp_simple_clock_info *clocks)
1418 1419
{
	struct pp_hwmgr  *hwmgr;
1420 1421
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1422

1423
	ret = pp_check(pp_handle);
1424

1425
	if (ret)
1426 1427 1428
		return ret;

	hwmgr = pp_handle->hwmgr;
1429

1430 1431
	if (clocks == NULL)
		return -EINVAL;
1432

1433 1434
	mutex_lock(&pp_handle->pp_lock);

1435
	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1436
		ret = phm_get_max_high_clocks(hwmgr, clocks);
1437

1438
	mutex_unlock(&pp_handle->pp_lock);
1439
	return ret;
1440 1441
}