amd_powerplay.c 33.4 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 32
#include "power_state.h"
#include "eventmanager.h"
33

34

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

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

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

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

50 51
	return 0;
}
52

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

58
	ret = smum_early_init(pp_handle);
59
	if (ret)
60 61 62 63 64
		return ret;

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

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

72 73 74 75 76 77 78
	ret = eventmgr_early_init(pp_handle);
	if (ret) {
		kfree(pp_handle->hwmgr);
		pp_handle->hwmgr = NULL;
		pp_handle->pm_en = 0;
		return PP_DPM_DISABLED;
	}
79 80

	return 0;
81 82
}

83
static int pp_sw_init(void *handle)
84
{
85
	struct pp_smumgr *smumgr;
86
	int ret = 0;
87
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
88

89
	ret = pp_check(pp_handle);
90

91 92
	if (ret == 0 || ret == PP_DPM_DISABLED) {
		smumgr = pp_handle->smu_mgr;
93

94 95
		if (smumgr->smumgr_funcs->smu_init == NULL)
			return -EINVAL;
96

97
		ret = smumgr->smumgr_funcs->smu_init(smumgr);
98

99 100 101 102
		pr_info("amdgpu: powerplay sw initialized\n");
	}
	return ret;
}
103

104 105 106 107 108 109 110 111 112
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;
113

114 115 116 117 118
		if (smumgr->smumgr_funcs->smu_fini == NULL)
			return -EINVAL;

		ret = smumgr->smumgr_funcs->smu_fini(smumgr);
	}
119
	return ret;
120 121 122 123
}

static int pp_hw_init(void *handle)
{
124
	struct pp_smumgr *smumgr;
125
	struct pp_eventmgr *eventmgr;
126
	int ret = 0;
127
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
128

129
	ret = pp_check(pp_handle);
130

131 132
	if (ret == 0 || ret == PP_DPM_DISABLED) {
		smumgr = pp_handle->smu_mgr;
133

134 135
		if (smumgr->smumgr_funcs->start_smu == NULL)
			return -EINVAL;
136

137 138 139 140 141 142 143
		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;
144
	}
145

146 147 148
	ret = hwmgr_hw_init(pp_handle);
	if (ret)
		goto err;
149 150

	eventmgr = pp_handle->eventmgr;
151 152 153
	if (eventmgr->pp_eventmgr_init == NULL ||
		eventmgr->pp_eventmgr_init(eventmgr))
		goto err;
154

155
	return 0;
156 157 158 159 160 161 162
err:
	pp_handle->pm_en = 0;
	kfree(pp_handle->eventmgr);
	kfree(pp_handle->hwmgr);
	pp_handle->hwmgr = NULL;
	pp_handle->eventmgr = NULL;
	return PP_DPM_DISABLED;
163 164 165 166
}

static int pp_hw_fini(void *handle)
{
167
	struct pp_eventmgr *eventmgr;
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) {
		eventmgr = pp_handle->eventmgr;
175

176 177
		if (eventmgr->pp_eventmgr_fini != NULL)
			eventmgr->pp_eventmgr_fini(eventmgr);
178

179 180
		hwmgr_hw_fini(pp_handle);
	}
181 182 183 184 185
	return 0;
}

static bool pp_is_idle(void *handle)
{
186
	return false;
187 188 189 190 191 192 193 194 195 196 197 198 199
}

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

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


200
int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
201
{
202
	struct pp_hwmgr  *hwmgr;
203 204
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
205

206
	ret = pp_check(pp_handle);
207

208 209
	if (ret != 0)
		return ret;
210

211
	hwmgr = pp_handle->hwmgr;
212

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

218
	return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
219 220 221 222 223
}

static int pp_set_powergating_state(void *handle,
				    enum amd_powergating_state state)
{
224
	struct pp_hwmgr  *hwmgr;
225 226
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
227

228
	ret = pp_check(pp_handle);
229

230 231
	if (ret != 0)
		return ret;
232

233
	hwmgr = pp_handle->hwmgr;
234 235

	if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
236
		pr_info("%s was not implemented.\n", __func__);
237 238
		return 0;
	}
239 240 241

	/* Enable/disable GFX per cu powergating through SMU */
	return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
242
			state == AMD_PG_STATE_GATE);
243 244 245 246
}

static int pp_suspend(void *handle)
{
247 248
	struct pp_eventmgr *eventmgr;
	struct pem_event_data event_data = { {0} };
249 250
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
251

252 253 254 255
	ret = pp_check(pp_handle);

	if (ret != 0)
		return ret;
256 257

	eventmgr = pp_handle->eventmgr;
258
	pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
259

260 261 262 263 264
	return 0;
}

static int pp_resume(void *handle)
{
265 266
	struct pp_eventmgr *eventmgr;
	struct pem_event_data event_data = { {0} };
267
	struct pp_smumgr *smumgr;
268 269
	int ret, ret1;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
270

271 272 273 274
	ret1 = pp_check(pp_handle);

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

276 277
	smumgr = pp_handle->smu_mgr;

278
	if (smumgr->smumgr_funcs->start_smu == NULL)
279 280 281 282
		return -EINVAL;

	ret = smumgr->smumgr_funcs->start_smu(smumgr);
	if (ret) {
283
		pr_err("smc start failed\n");
284 285 286 287
		smumgr->smumgr_funcs->smu_fini(smumgr);
		return ret;
	}

288
	if (ret1 == PP_DPM_DISABLED)
M
Monk Liu 已提交
289
		return 0;
290

291
	eventmgr = pp_handle->eventmgr;
292 293

	pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
294

295 296 297 298
	return 0;
}

const struct amd_ip_funcs pp_ip_funcs = {
299
	.name = "powerplay",
300 301 302 303 304 305 306 307 308 309 310
	.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,
311
	.set_clockgating_state = NULL,
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
	.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)
{
328
	struct pp_hwmgr  *hwmgr;
329 330
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
331

332
	ret = pp_check(pp_handle);
333

334 335
	if (ret != 0)
		return ret;
336 337 338

	hwmgr = pp_handle->hwmgr;

339
	if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
340
		pr_info("%s was not implemented.\n", __func__);
341 342
		return 0;
	}
343

344
	mutex_lock(&pp_handle->pp_lock);
345
	hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
346
	mutex_unlock(&pp_handle->pp_lock);
347 348
	return 0;
}
349

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

358
	ret = pp_check(pp_handle);
359

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

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

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

376
	ret = pp_check(pp_handle);
377

378 379
	if (ret != 0)
		return ret;
380

381
	hwmgr = pp_handle->hwmgr;
382 383

	if (hwmgr->hwmgr_func->get_sclk == NULL) {
384
		pr_info("%s was not implemented.\n", __func__);
385 386
		return 0;
	}
387 388 389 390
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
391
}
392

393 394
static int pp_dpm_get_mclk(void *handle, bool low)
{
395
	struct pp_hwmgr  *hwmgr;
396 397
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
398

399
	ret = pp_check(pp_handle);
400

401 402
	if (ret != 0)
		return ret;
403

404
	hwmgr = pp_handle->hwmgr;
405 406

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

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

422
	ret = pp_check(pp_handle);
423

424 425
	if (ret != 0)
		return ret;
426

427
	hwmgr = pp_handle->hwmgr;
428 429

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

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

445
	ret = pp_check(pp_handle);
446

447 448
	if (ret != 0)
		return ret;
449

450
	hwmgr = pp_handle->hwmgr;
451 452

	if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
453
		pr_info("%s was not implemented.\n", __func__);
454 455
		return 0;
	}
456 457 458 459
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
460 461 462 463 464 465 466 467 468 469 470 471 472 473
}

static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
{
	switch (state) {
	case POWER_STATE_TYPE_BATTERY:
		return PP_StateUILabel_Battery;
	case POWER_STATE_TYPE_BALANCED:
		return PP_StateUILabel_Balanced;
	case POWER_STATE_TYPE_PERFORMANCE:
		return PP_StateUILabel_Performance;
	default:
		return PP_StateUILabel_None;
	}
474 475
}

476 477
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
		void *input, void *output)
478
{
479 480
	int ret = 0;
	struct pem_event_data data = { {0} };
481
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
482

483
	ret = pp_check(pp_handle);
484

485 486
	if (ret != 0)
		return ret;
487
	mutex_lock(&pp_handle->pp_lock);
488 489 490 491 492 493 494 495 496 497 498 499 500 501
	switch (event_id) {
	case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
		break;
	case AMD_PP_EVENT_ENABLE_USER_STATE:
	{
		enum amd_pm_state_type  ps;

		if (input == NULL)
			return -EINVAL;
		ps = *(unsigned long *)input;

		data.requested_ui_label = power_state_convert(ps);
		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
502
		break;
503
	}
504 505 506
	case AMD_PP_EVENT_COMPLETE_INIT:
		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
		break;
507 508 509
	case AMD_PP_EVENT_READJUST_POWER_STATE:
		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
		break;
510 511 512
	default:
		break;
	}
513
	mutex_unlock(&pp_handle->pp_lock);
514
	return ret;
515
}
516

517
static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
518
{
519 520
	struct pp_hwmgr *hwmgr;
	struct pp_power_state *state;
521 522
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
523
	enum amd_pm_state_type pm_type;
524

525
	ret = pp_check(pp_handle);
526

527 528
	if (ret != 0)
		return ret;
529

530 531 532
	hwmgr = pp_handle->hwmgr;

	if (hwmgr->current_ps == NULL)
533 534
		return -EINVAL;

535 536
	mutex_lock(&pp_handle->pp_lock);

537 538 539 540
	state = hwmgr->current_ps;

	switch (state->classification.ui_label) {
	case PP_StateUILabel_Battery:
541
		pm_type = POWER_STATE_TYPE_BATTERY;
542
	case PP_StateUILabel_Balanced:
543
		pm_type = POWER_STATE_TYPE_BALANCED;
544
	case PP_StateUILabel_Performance:
545
		pm_type = POWER_STATE_TYPE_PERFORMANCE;
546
	default:
547
		if (state->classification.flags & PP_StateClassificationFlag_Boot)
548
			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
549
		else
550
			pm_type = POWER_STATE_TYPE_DEFAULT;
551
	}
552 553 554
	mutex_unlock(&pp_handle->pp_lock);

	return pm_type;
555
}
556

557 558 559
static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
{
	struct pp_hwmgr  *hwmgr;
560 561
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
562

563
	ret = pp_check(pp_handle);
564

565 566
	if (ret != 0)
		return ret;
567

568
	hwmgr = pp_handle->hwmgr;
569 570

	if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
571
		pr_info("%s was not implemented.\n", __func__);
572 573
		return 0;
	}
574 575 576 577
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
578 579 580 581 582
}

static int pp_dpm_get_fan_control_mode(void *handle)
{
	struct pp_hwmgr  *hwmgr;
583 584
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
585

586
	ret = pp_check(pp_handle);
587

588 589
	if (ret != 0)
		return ret;
590

591
	hwmgr = pp_handle->hwmgr;
592 593

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

static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
{
	struct pp_hwmgr  *hwmgr;
606 607
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
608

609
	ret = pp_check(pp_handle);
610

611 612
	if (ret != 0)
		return ret;
613

614
	hwmgr = pp_handle->hwmgr;
615 616

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

static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
{
	struct pp_hwmgr  *hwmgr;
629 630
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
631

632
	ret = pp_check(pp_handle);
633

634 635
	if (ret != 0)
		return ret;
636

637
	hwmgr = pp_handle->hwmgr;
638 639

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

644 645 646 647
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
648 649
}

650 651 652
static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
{
	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 659
	if (ret != 0)
		return ret;
660

661
	hwmgr = pp_handle->hwmgr;
662 663 664 665

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

666 667 668 669
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
670 671
}

672 673 674
static int pp_dpm_get_temperature(void *handle)
{
	struct pp_hwmgr  *hwmgr;
675 676
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
677

678
	ret = pp_check(pp_handle);
679

680 681
	if (ret != 0)
		return ret;
682

683
	hwmgr = pp_handle->hwmgr;
684 685

	if (hwmgr->hwmgr_func->get_temperature == NULL) {
686
		pr_info("%s was not implemented.\n", __func__);
687 688
		return 0;
	}
689 690 691 692
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
693
}
694

695 696 697 698 699
static int pp_dpm_get_pp_num_states(void *handle,
		struct pp_states_info *data)
{
	struct pp_hwmgr *hwmgr;
	int i;
700 701
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
702

703
	ret = pp_check(pp_handle);
704

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

	hwmgr = pp_handle->hwmgr;
709

710
	if (hwmgr->ps == NULL)
711 712
		return -EINVAL;

713 714
	mutex_lock(&pp_handle->pp_lock);

715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
	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;
		}
	}
737
	mutex_unlock(&pp_handle->pp_lock);
738 739 740 741 742 743
	return 0;
}

static int pp_dpm_get_pp_table(void *handle, char **table)
{
	struct pp_hwmgr *hwmgr;
744 745
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
746
	int size = 0;
747

748
	ret = pp_check(pp_handle);
749

750 751
	if (ret != 0)
		return ret;
752

753
	hwmgr = pp_handle->hwmgr;
754

755 756 757
	if (!hwmgr->soft_pp_table)
		return -EINVAL;

758
	mutex_lock(&pp_handle->pp_lock);
759
	*table = (char *)hwmgr->soft_pp_table;
760 761 762
	size = hwmgr->soft_pp_table_size;
	mutex_unlock(&pp_handle->pp_lock);
	return size;
763 764 765 766 767
}

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

771
	ret = pp_check(pp_handle);
772

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

776
	hwmgr = pp_handle->hwmgr;
777
	mutex_lock(&pp_handle->pp_lock);
778
	if (!hwmgr->hardcode_pp_table) {
779 780 781
		hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
						   hwmgr->soft_pp_table_size,
						   GFP_KERNEL);
782 783
		if (!hwmgr->hardcode_pp_table) {
			mutex_unlock(&pp_handle->pp_lock);
784
			return -ENOMEM;
785
		}
786
	}
787

788 789 790
	memcpy(hwmgr->hardcode_pp_table, buf, size);

	hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
791
	mutex_unlock(&pp_handle->pp_lock);
792

793 794 795 796 797 798 799 800 801 802 803
	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;
804 805 806
}

static int pp_dpm_force_clock_level(void *handle,
807
		enum pp_clock_type type, uint32_t mask)
808 809
{
	struct pp_hwmgr *hwmgr;
810 811
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
812

813
	ret = pp_check(pp_handle);
814

815 816
	if (ret != 0)
		return ret;
817

818
	hwmgr = pp_handle->hwmgr;
819 820

	if (hwmgr->hwmgr_func->force_clock_level == NULL) {
821
		pr_info("%s was not implemented.\n", __func__);
822 823
		return 0;
	}
824 825 826 827
	mutex_lock(&pp_handle->pp_lock);
	hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
828 829 830 831 832 833
}

static int pp_dpm_print_clock_levels(void *handle,
		enum pp_clock_type type, char *buf)
{
	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 840
	if (ret != 0)
		return ret;
841

842
	hwmgr = pp_handle->hwmgr;
843

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

854 855 856
static int pp_dpm_get_sclk_od(void *handle)
{
	struct pp_hwmgr *hwmgr;
857 858
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
859

860
	ret = pp_check(pp_handle);
861

862 863
	if (ret != 0)
		return ret;
864

865
	hwmgr = pp_handle->hwmgr;
866 867

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

static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
880 881
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
882

883
	ret = pp_check(pp_handle);
884

885 886
	if (ret != 0)
		return ret;
887

888
	hwmgr = pp_handle->hwmgr;
889 890

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

895 896
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
897
	mutex_unlock(&pp_handle->pp_lock);
898
	return ret;
899 900
}

901 902 903
static int pp_dpm_get_mclk_od(void *handle)
{
	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 910
	if (ret != 0)
		return ret;
911

912
	hwmgr = pp_handle->hwmgr;
913 914

	if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
915
		pr_info("%s was not implemented.\n", __func__);
916 917
		return 0;
	}
918 919 920 921
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
922 923 924 925 926
}

static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
{
	struct pp_hwmgr *hwmgr;
927 928
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
929

930
	ret = pp_check(pp_handle);
931

932 933
	if (ret != 0)
		return ret;
934

935
	hwmgr = pp_handle->hwmgr;
936 937

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

947 948
static int pp_dpm_read_sensor(void *handle, int idx,
			      void *value, int *size)
949 950
{
	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 957
	if (ret != 0)
		return ret;
958

959
	hwmgr = pp_handle->hwmgr;
960 961

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

966 967 968 969 970
	mutex_lock(&pp_handle->pp_lock);
	ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
	mutex_unlock(&pp_handle->pp_lock);

	return ret;
971 972
}

973 974 975 976
static struct amd_vce_state*
pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
{
	struct pp_hwmgr *hwmgr;
977 978
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
979

980
	ret = pp_check(pp_handle);
981

982 983 984 985 986 987 988
	if (ret != 0)
		return NULL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr && idx < hwmgr->num_vce_state_tables)
		return &hwmgr->vce_states[idx];
989 990 991
	return NULL;
}

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 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
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;
}

1123
const struct amd_powerplay_funcs pp_dpm_funcs = {
1124
	.get_temperature = pp_dpm_get_temperature,
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
	.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,
1135 1136 1137 1138
	.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,
1139
	.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1140 1141 1142 1143 1144
	.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,
1145 1146
	.get_sclk_od = pp_dpm_get_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
1147 1148
	.get_mclk_od = pp_dpm_get_mclk_od,
	.set_mclk_od = pp_dpm_set_mclk_od,
1149
	.read_sensor = pp_dpm_read_sensor,
1150
	.get_vce_clock_state = pp_dpm_get_vce_clock_state,
1151 1152 1153 1154
	.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,
1155 1156
};

1157 1158
int amd_powerplay_create(struct amd_pp_init *pp_init,
				void **handle)
1159
{
1160
	struct pp_instance *instance;
1161

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

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

1169 1170 1171 1172 1173 1174
	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;
1175
	mutex_init(&instance->pp_lock);
1176
	*handle = instance;
1177 1178 1179
	return 0;
}

1180
int amd_powerplay_destroy(void *handle)
1181 1182
{
	struct pp_instance *instance = (struct pp_instance *)handle;
1183

1184 1185 1186 1187 1188
	if (instance->pm_en) {
		kfree(instance->eventmgr);
		kfree(instance->hwmgr);
		instance->hwmgr = NULL;
		instance->eventmgr = NULL;
1189
	}
1190

1191 1192 1193 1194
	kfree(instance->smu_mgr);
	instance->smu_mgr = NULL;
	kfree(instance);
	instance = NULL;
1195 1196
	return 0;
}
1197

1198 1199 1200 1201 1202 1203 1204
int amd_powerplay_reset(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;
	struct pp_eventmgr *eventmgr;
	struct pem_event_data event_data = { {0} };
	int ret;

1205 1206
	if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
		return PP_DPM_DISABLED;
1207

1208 1209
	ret = pp_check(instance);
	if (ret != 0)
1210 1211
		return ret;

1212
	ret = pp_hw_fini(handle);
1213 1214 1215
	if (ret)
		return ret;

1216 1217 1218
	ret = hwmgr_hw_init(instance);
	if (ret)
		return PP_DPM_DISABLED;
1219

1220
	eventmgr = instance->eventmgr;
1221

1222 1223
	if (eventmgr->pp_eventmgr_init == NULL)
		return PP_DPM_DISABLED;
1224 1225 1226 1227 1228 1229 1230 1231

	ret = eventmgr->pp_eventmgr_init(eventmgr);
	if (ret)
		return ret;

	return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
}

1232 1233
/* export this function to DAL */

1234 1235
int amd_powerplay_display_configuration_change(void *handle,
	const struct amd_pp_display_configuration *display_config)
1236 1237
{
	struct pp_hwmgr  *hwmgr;
1238 1239
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1240

1241
	ret = pp_check(pp_handle);
1242

1243 1244
	if (ret != 0)
		return ret;
1245

1246
	hwmgr = pp_handle->hwmgr;
1247
	mutex_lock(&pp_handle->pp_lock);
1248
	phm_store_dal_configuration_data(hwmgr, display_config);
1249
	mutex_unlock(&pp_handle->pp_lock);
1250 1251
	return 0;
}
1252

1253
int amd_powerplay_get_display_power_level(void *handle,
R
Rex Zhu 已提交
1254
		struct amd_pp_simple_clock_info *output)
1255 1256
{
	struct pp_hwmgr  *hwmgr;
1257 1258
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1259

1260
	ret = pp_check(pp_handle);
1261

1262 1263
	if (ret != 0)
		return ret;
1264

1265
	hwmgr = pp_handle->hwmgr;
1266

1267 1268
	if (output == NULL)
		return -EINVAL;
1269

1270 1271 1272 1273
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_dal_power_level(hwmgr, output);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1274
}
1275 1276

int amd_powerplay_get_current_clocks(void *handle,
1277
		struct amd_pp_clock_info *clocks)
1278 1279 1280
{
	struct amd_pp_simple_clock_info simple_clocks;
	struct pp_clock_info hw_clocks;
1281 1282 1283
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1284

1285
	ret = pp_check(pp_handle);
1286

1287 1288
	if (ret != 0)
		return ret;
1289

1290
	hwmgr = pp_handle->hwmgr;
1291

1292 1293
	mutex_lock(&pp_handle->pp_lock);

1294 1295
	phm_get_dal_power_level(hwmgr, &simple_clocks);

1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
	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;
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
	}

	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;
	}
1326
	mutex_unlock(&pp_handle->pp_lock);
1327 1328 1329 1330 1331
	return 0;
}

int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
{
1332 1333 1334
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1335

1336
	ret = pp_check(pp_handle);
1337

1338 1339 1340 1341
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
1342 1343

	if (clocks == NULL)
1344 1345
		return -EINVAL;

1346 1347 1348 1349
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_clock_by_type(hwmgr, type, clocks);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
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 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
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;
}

1446 1447
int amd_powerplay_get_display_mode_validation_clocks(void *handle,
		struct amd_pp_simple_clock_info *clocks)
1448 1449
{
	struct pp_hwmgr  *hwmgr;
1450 1451
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1452

1453
	ret = pp_check(pp_handle);
1454

1455 1456 1457 1458
	if (ret != 0)
		return ret;

	hwmgr = pp_handle->hwmgr;
1459

1460 1461
	if (clocks == NULL)
		return -EINVAL;
1462

1463 1464
	mutex_lock(&pp_handle->pp_lock);

1465
	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1466
		ret = phm_get_max_high_clocks(hwmgr, clocks);
1467

1468
	mutex_unlock(&pp_handle->pp_lock);
1469
	return ret;
1470 1471
}