amd_powerplay.c 34.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
#include "amdgpu.h"
R
Rex Zhu 已提交
33
#include "hwmgr.h"
34

35 36
#define PP_DPM_DISABLED 0xCCCC

R
Rex Zhu 已提交
37
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
38
		enum amd_pm_state_type *user_state);
R
Rex Zhu 已提交
39

40
static inline int pp_check(struct pp_instance *handle)
41
{
R
Rex Zhu 已提交
42
	if (handle == NULL)
43
		return -EINVAL;
44

45
	if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL)
46 47
		return -EINVAL;

48 49
	if (handle->pm_en == 0)
		return PP_DPM_DISABLED;
50

51
	if (handle->hwmgr->hwmgr_func == NULL)
52
		return PP_DPM_DISABLED;
53

54 55
	return 0;
}
56

57
static int amd_powerplay_create(struct amdgpu_device *adev)
58 59 60
{
	struct pp_instance *instance;

61
	if (adev == NULL)
62 63 64 65 66 67
		return -EINVAL;

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

R
Rex Zhu 已提交
68
	instance->parent = adev;
69 70
	instance->pm_en = (amdgpu_dpm != 0 && !amdgpu_sriov_vf(adev)) ? true : false;
	instance->device = adev->powerplay.cgs_device;
71
	mutex_init(&instance->pp_lock);
72 73
	adev->powerplay.pp_handle = instance;

74 75 76
	return 0;
}

77

78 79 80 81
static int amd_powerplay_destroy(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;

82 83 84
	kfree(instance->hwmgr->hardcode_pp_table);
	instance->hwmgr->hardcode_pp_table = NULL;

85 86 87 88 89 90 91 92
	kfree(instance->hwmgr);
	instance->hwmgr = NULL;

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

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

99
	ret = amd_powerplay_create(adev);
100

101 102 103 104
	if (ret != 0)
		return ret;

	pp_handle = adev->powerplay.pp_handle;
105

106
	ret = hwmgr_early_init(pp_handle);
107
	if (ret)
108
		return -EINVAL;
109

110
	return 0;
111 112
}

113
static int pp_sw_init(void *handle)
114
{
115
	struct pp_hwmgr *hwmgr;
116
	int ret = 0;
117
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
118

119
	ret = pp_check(pp_handle);
120

121
	if (ret >= 0) {
122
		hwmgr = pp_handle->hwmgr;
123

124
		if (hwmgr->smumgr_funcs->smu_init == NULL)
125
			return -EINVAL;
126

127
		ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
128

129
		pr_debug("amdgpu: powerplay sw initialized\n");
130 131 132
	}
	return ret;
}
133

134 135
static int pp_sw_fini(void *handle)
{
136
	struct pp_hwmgr *hwmgr;
137 138 139 140
	int ret = 0;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	ret = pp_check(pp_handle);
141
	if (ret >= 0) {
142
		hwmgr = pp_handle->hwmgr;
143

144
		if (hwmgr->smumgr_funcs->smu_fini == NULL)
145 146
			return -EINVAL;

147
		ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
148
	}
149
	return ret;
150 151 152 153
}

static int pp_hw_init(void *handle)
{
154
	int ret = 0;
155
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
156
	struct pp_hwmgr *hwmgr;
157

158
	ret = pp_check(pp_handle);
159

160
	if (ret >= 0) {
161
		hwmgr = pp_handle->hwmgr;
162

163
		if (hwmgr->smumgr_funcs->start_smu == NULL)
164
			return -EINVAL;
165

166
		if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
167
			pr_err("smc start failed\n");
168
			hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
169
			return -EINVAL;
170 171
		}
		if (ret == PP_DPM_DISABLED)
172 173 174 175
			goto exit;
		ret = hwmgr_hw_init(pp_handle);
		if (ret)
			goto exit;
176
	}
177 178
	return ret;
exit:
179
	pp_handle->pm_en = 0;
180 181 182
	cgs_notify_dpm_enabled(hwmgr->device, false);
	return 0;

183 184 185 186
}

static int pp_hw_fini(void *handle)
{
187 188
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
189

190
	ret = pp_check(pp_handle);
191
	if (ret == 0)
192
		hwmgr_hw_fini(pp_handle);
193

194 195 196
	return 0;
}

R
Rex Zhu 已提交
197 198 199 200 201 202 203 204
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,
205
					AMD_PP_TASK_COMPLETE_INIT, NULL);
R
Rex Zhu 已提交
206 207 208 209

	return 0;
}

210 211 212 213 214 215
static void pp_late_fini(void *handle)
{
	amd_powerplay_destroy(handle);
}


216 217
static bool pp_is_idle(void *handle)
{
218
	return false;
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
}

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)
{
234
	struct pp_hwmgr  *hwmgr;
235 236
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
237

238
	ret = pp_check(pp_handle);
239

240
	if (ret)
241
		return ret;
242

243
	hwmgr = pp_handle->hwmgr;
244 245

	if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
246
		pr_info("%s was not implemented.\n", __func__);
247 248
		return 0;
	}
249 250 251

	/* Enable/disable GFX per cu powergating through SMU */
	return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
252
			state == AMD_PG_STATE_GATE);
253 254 255 256
}

static int pp_suspend(void *handle)
{
257 258
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
259

260
	ret = pp_check(pp_handle);
261 262 263
	if (ret == 0)
		hwmgr_hw_suspend(pp_handle);
	return 0;
264 265 266 267
}

static int pp_resume(void *handle)
{
268
	struct pp_hwmgr  *hwmgr;
269
	int ret;
270
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
271

272
	ret = pp_check(pp_handle);
273

274 275
	if (ret < 0)
		return ret;
276

277
	hwmgr = pp_handle->hwmgr;
278

279
	if (hwmgr->smumgr_funcs->start_smu == NULL)
280 281
		return -EINVAL;

282
	if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
283
		pr_err("smc start failed\n");
284
		hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
285
		return -EINVAL;
286 287
	}

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

291
	return hwmgr_hw_resume(pp_handle);
292 293 294
}

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

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
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);
}

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 373 374 375 376 377 378
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);
		}
	}
}

379 380 381
static int pp_dpm_force_performance_level(void *handle,
					enum amd_dpm_forced_level level)
{
382
	struct pp_hwmgr  *hwmgr;
383 384
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
385

386
	ret = pp_check(pp_handle);
387

388
	if (ret)
389
		return ret;
390 391 392

	hwmgr = pp_handle->hwmgr;

393 394 395
	if (level == hwmgr->dpm_level)
		return 0;

396
	mutex_lock(&pp_handle->pp_lock);
397 398
	pp_dpm_en_umd_pstate(hwmgr, &level);
	hwmgr->request_dpm_level = level;
399
	hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
400
	mutex_unlock(&pp_handle->pp_lock);
401

402 403
	return 0;
}
404

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

413
	ret = pp_check(pp_handle);
414

415
	if (ret)
416
		return ret;
417

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

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

432
	ret = pp_check(pp_handle);
433

434
	if (ret)
435
		return ret;
436

437
	hwmgr = pp_handle->hwmgr;
438 439

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

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

456
	ret = pp_check(pp_handle);
457

458
	if (ret)
459
		return ret;
460

461
	hwmgr = pp_handle->hwmgr;
462 463

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

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

479
	ret = pp_check(pp_handle);
480

481
	if (ret)
482
		return;
483

484
	hwmgr = pp_handle->hwmgr;
485 486

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

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

501
	ret = pp_check(pp_handle);
502

503
	if (ret)
504
		return;
505

506
	hwmgr = pp_handle->hwmgr;
507 508

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

517
static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
518
		enum amd_pm_state_type *user_state)
519
{
520
	int ret = 0;
521
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
522

523
	ret = pp_check(pp_handle);
524

525
	if (ret)
526
		return ret;
527

528
	mutex_lock(&pp_handle->pp_lock);
529
	ret = hwmgr_handle_task(pp_handle, task_id, user_state);
530
	mutex_unlock(&pp_handle->pp_lock);
531

532
	return ret;
533
}
534

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

543
	ret = pp_check(pp_handle);
544

545
	if (ret)
546
		return ret;
547

548 549 550
	hwmgr = pp_handle->hwmgr;

	if (hwmgr->current_ps == NULL)
551 552
		return -EINVAL;

553 554
	mutex_lock(&pp_handle->pp_lock);

555 556 557 558
	state = hwmgr->current_ps;

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

	return pm_type;
577
}
578

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

585
	ret = pp_check(pp_handle);
586

587
	if (ret)
588
		return;
589

590
	hwmgr = pp_handle->hwmgr;
591 592

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

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

608
	ret = pp_check(pp_handle);
609

610
	if (ret)
611
		return ret;
612

613
	hwmgr = pp_handle->hwmgr;
614 615

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

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

631
	ret = pp_check(pp_handle);
632

633
	if (ret)
634
		return ret;
635

636
	hwmgr = pp_handle->hwmgr;
637 638

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

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

654
	ret = pp_check(pp_handle);
655

656
	if (ret)
657
		return ret;
658

659
	hwmgr = pp_handle->hwmgr;
660 661

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

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

672 673 674
static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
{
	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
	if (ret)
681
		return ret;
682

683
	hwmgr = pp_handle->hwmgr;
684 685 686 687

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

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

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

702 703
	memset(data, 0, sizeof(*data));

704
	ret = pp_check(pp_handle);
705

706
	if (ret)
707 708 709
		return ret;

	hwmgr = pp_handle->hwmgr;
710

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

714 715
	mutex_lock(&pp_handle->pp_lock);

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

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

749
	ret = pp_check(pp_handle);
750

751
	if (ret)
752
		return ret;
753

754
	hwmgr = pp_handle->hwmgr;
755

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

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

766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
static int amd_powerplay_reset(void *handle)
{
	struct pp_instance *instance = (struct pp_instance *)handle;
	int ret;

	ret = pp_check(instance);
	if (ret)
		return ret;

	ret = pp_hw_fini(instance);
	if (ret)
		return ret;

	ret = hwmgr_hw_init(instance);
	if (ret)
		return ret;

783
	return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL);
784 785
}

786 787 788
static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
{
	struct pp_hwmgr *hwmgr;
789 790
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
791

792
	ret = pp_check(pp_handle);
793

794
	if (ret)
795
		return ret;
796

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

809 810 811
	memcpy(hwmgr->hardcode_pp_table, buf, size);

	hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
812
	mutex_unlock(&pp_handle->pp_lock);
813

814 815 816 817 818 819 820 821 822 823 824
	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;
825 826 827
}

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

834
	ret = pp_check(pp_handle);
835

836
	if (ret)
837
		return ret;
838

839
	hwmgr = pp_handle->hwmgr;
840 841

	if (hwmgr->hwmgr_func->force_clock_level == NULL) {
842
		pr_info("%s was not implemented.\n", __func__);
843 844
		return 0;
	}
845
	mutex_lock(&pp_handle->pp_lock);
846 847 848 849
	if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
		ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
	else
		ret = -EINVAL;
850 851
	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
	if (ret)
980
		return ret;
981

982 983 984
	if (value == NULL)
		return -EINVAL;

985
	hwmgr = pp_handle->hwmgr;
986

987 988 989 990 991 992
	switch (idx) {
	case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
		*((uint32_t *)value) = hwmgr->pstate_sclk;
		return 0;
	case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
		*((uint32_t *)value) = hwmgr->pstate_mclk;
993
		return 0;
994 995 996 997 998
	default:
		mutex_lock(&pp_handle->pp_lock);
		ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
		mutex_unlock(&pp_handle->pp_lock);
		return ret;
999 1000 1001
	}
}

1002 1003 1004 1005
static struct amd_vce_state*
pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
{
	struct pp_hwmgr *hwmgr;
1006 1007
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1008

1009
	ret = pp_check(pp_handle);
1010

1011
	if (ret)
1012 1013 1014 1015 1016 1017
		return NULL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr && idx < hwmgr->num_vce_state_tables)
		return &hwmgr->vce_states[idx];
1018 1019 1020
	return NULL;
}

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
static int pp_get_power_profile_mode(void *handle, char *buf)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

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

	hwmgr = pp_handle->hwmgr;

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

	return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
}

static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
1043
	int ret = -EINVAL;
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053

	if (pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

	if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return -EINVAL;
	}
1054 1055 1056 1057 1058
	mutex_lock(&pp_handle->pp_lock);
	if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
		ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1059 1060
}

1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;

	if (pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

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

	return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
}

1079
static int pp_dpm_switch_power_profile(void *handle,
1080
		enum PP_SMC_POWER_PROFILE type, bool en)
1081 1082 1083
{
	struct pp_hwmgr *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
1084 1085
	long workload;
	uint32_t index;
1086 1087 1088 1089 1090 1091

	if (pp_check(pp_handle))
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
	if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return -EINVAL;
	}

	if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
		return -EINVAL;

	mutex_lock(&pp_handle->pp_lock);

	if (!en) {
		hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
		index = fls(hwmgr->workload_mask);
		index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
		workload = hwmgr->workload_setting[index];
	} else {
		hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
		index = fls(hwmgr->workload_mask);
		index = index <= Workload_Policy_Max ? index - 1 : 0;
		workload = hwmgr->workload_setting[index];
1112 1113
	}

1114 1115 1116 1117
	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
		hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
	mutex_unlock(&pp_handle->pp_lock);

1118 1119 1120
	return 0;
}

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 1147 1148 1149 1150 1151 1152 1153 1154
static int pp_dpm_notify_smu_memory_info(void *handle,
					uint32_t virtual_addr_low,
					uint32_t virtual_addr_hi,
					uint32_t mc_addr_low,
					uint32_t mc_addr_hi,
					uint32_t size)
{
	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->notify_cac_buffer_info == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&pp_handle->pp_lock);

	ret = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr, virtual_addr_low,
					virtual_addr_hi, mc_addr_low, mc_addr_hi,
					size);

	mutex_unlock(&pp_handle->pp_lock);

	return ret;
}

1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
static int pp_set_power_limit(void *handle, uint32_t limit)
{
	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->set_power_limit == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return -EINVAL;
	}

	if (limit == 0)
		limit = hwmgr->default_power_limit;

	if (limit > hwmgr->default_power_limit)
		return -EINVAL;

	mutex_lock(&pp_handle->pp_lock);
	hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
	hwmgr->power_limit = limit;
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
}

static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
{
	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;

	if (limit == NULL)
		return -EINVAL;

	hwmgr = pp_handle->hwmgr;

	mutex_lock(&pp_handle->pp_lock);

	if (default_limit)
		*limit = hwmgr->default_power_limit;
	else
		*limit = hwmgr->power_limit;

	mutex_unlock(&pp_handle->pp_lock);

	return ret;
}

1214
static int pp_display_configuration_change(void *handle,
1215
	const struct amd_pp_display_configuration *display_config)
1216 1217
{
	struct pp_hwmgr  *hwmgr;
1218 1219
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1220

1221
	ret = pp_check(pp_handle);
1222

1223
	if (ret)
1224
		return ret;
1225

1226
	hwmgr = pp_handle->hwmgr;
1227
	mutex_lock(&pp_handle->pp_lock);
1228
	phm_store_dal_configuration_data(hwmgr, display_config);
1229
	mutex_unlock(&pp_handle->pp_lock);
1230 1231
	return 0;
}
1232

1233
static int pp_get_display_power_level(void *handle,
R
Rex Zhu 已提交
1234
		struct amd_pp_simple_clock_info *output)
1235 1236
{
	struct pp_hwmgr  *hwmgr;
1237 1238
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1239

1240
	ret = pp_check(pp_handle);
1241

1242
	if (ret)
1243
		return ret;
1244

1245
	hwmgr = pp_handle->hwmgr;
1246

1247 1248
	if (output == NULL)
		return -EINVAL;
1249

1250 1251 1252 1253
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_dal_power_level(hwmgr, output);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1254
}
1255

1256
static int pp_get_current_clocks(void *handle,
1257
		struct amd_pp_clock_info *clocks)
1258 1259 1260
{
	struct amd_pp_simple_clock_info simple_clocks;
	struct pp_clock_info hw_clocks;
1261 1262 1263
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1264

1265
	ret = pp_check(pp_handle);
1266

1267
	if (ret)
1268
		return ret;
1269

1270
	hwmgr = pp_handle->hwmgr;
1271

1272 1273
	mutex_lock(&pp_handle->pp_lock);

1274 1275
	phm_get_dal_power_level(hwmgr, &simple_clocks);

1276 1277 1278 1279 1280 1281 1282 1283
	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);

1284
	if (ret) {
1285 1286 1287
		pr_info("Error in phm_get_clock_info \n");
		mutex_unlock(&pp_handle->pp_lock);
		return -EINVAL;
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
	}

	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;
	}
1306
	mutex_unlock(&pp_handle->pp_lock);
1307 1308 1309
	return 0;
}

1310
static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1311
{
1312 1313 1314
	struct pp_hwmgr  *hwmgr;
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1315

1316
	ret = pp_check(pp_handle);
1317

1318
	if (ret)
1319 1320 1321
		return ret;

	hwmgr = pp_handle->hwmgr;
1322 1323

	if (clocks == NULL)
1324 1325
		return -EINVAL;

1326 1327 1328 1329
	mutex_lock(&pp_handle->pp_lock);
	ret = phm_get_clock_by_type(hwmgr, type, clocks);
	mutex_unlock(&pp_handle->pp_lock);
	return ret;
1330 1331
}

1332
static int pp_get_clock_by_type_with_latency(void *handle,
1333 1334 1335 1336 1337 1338 1339 1340
		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);
1341
	if (ret)
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
		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;
}

1354
static int pp_get_clock_by_type_with_voltage(void *handle,
1355 1356 1357 1358 1359 1360 1361 1362
		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);
1363
	if (ret)
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
		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;
}

1379
static int pp_set_watermarks_for_clocks_ranges(void *handle,
1380 1381 1382 1383 1384 1385 1386
		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);
1387
	if (ret)
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
		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;
}

1403
static int pp_display_clock_voltage_request(void *handle,
1404 1405 1406 1407 1408 1409 1410
		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);
1411
	if (ret)
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
		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;
}

1426
static int pp_get_display_mode_validation_clocks(void *handle,
1427
		struct amd_pp_simple_clock_info *clocks)
1428 1429
{
	struct pp_hwmgr  *hwmgr;
1430 1431
	struct pp_instance *pp_handle = (struct pp_instance *)handle;
	int ret = 0;
1432

1433
	ret = pp_check(pp_handle);
1434

1435
	if (ret)
1436 1437 1438
		return ret;

	hwmgr = pp_handle->hwmgr;
1439

1440 1441
	if (clocks == NULL)
		return -EINVAL;
1442

1443 1444
	mutex_lock(&pp_handle->pp_lock);

1445
	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1446
		ret = phm_get_max_high_clocks(hwmgr, clocks);
1447

1448
	mutex_unlock(&pp_handle->pp_lock);
1449
	return ret;
1450 1451
}

1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
static int pp_set_mmhub_powergating_by_smu(void *handle)
{
	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->set_mmhub_powergating_by_smu == NULL) {
		pr_info("%s was not implemented.\n", __func__);
		return 0;
	}

	return hwmgr->hwmgr_func->set_mmhub_powergating_by_smu(hwmgr);
}

1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
const struct amd_pm_funcs pp_dpm_funcs = {
	.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,
	.powergate_vce = pp_dpm_powergate_vce,
	.powergate_uvd = pp_dpm_powergate_uvd,
	.dispatch_tasks = pp_dpm_dispatch_tasks,
	.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,
	.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
	.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,
	.get_sclk_od = pp_dpm_get_sclk_od,
	.set_sclk_od = pp_dpm_set_sclk_od,
	.get_mclk_od = pp_dpm_get_mclk_od,
	.set_mclk_od = pp_dpm_set_mclk_od,
	.read_sensor = pp_dpm_read_sensor,
	.get_vce_clock_state = pp_dpm_get_vce_clock_state,
	.switch_power_profile = pp_dpm_switch_power_profile,
	.set_clockgating_by_smu = pp_set_clockgating_by_smu,
1500
	.notify_smu_memory_info = pp_dpm_notify_smu_memory_info,
1501 1502
	.get_power_profile_mode = pp_get_power_profile_mode,
	.set_power_profile_mode = pp_set_power_profile_mode,
1503
	.odn_edit_dpm_table = pp_odn_edit_dpm_table,
1504 1505
	.set_power_limit = pp_set_power_limit,
	.get_power_limit = pp_get_power_limit,
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
/* export to DC */
	.get_sclk = pp_dpm_get_sclk,
	.get_mclk = pp_dpm_get_mclk,
	.display_configuration_change = pp_display_configuration_change,
	.get_display_power_level = pp_get_display_power_level,
	.get_current_clocks = pp_get_current_clocks,
	.get_clock_by_type = pp_get_clock_by_type,
	.get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
	.get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
	.set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
	.display_clock_voltage_request = pp_display_clock_voltage_request,
	.get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
1518
	.set_mmhub_powergating_by_smu = pp_set_mmhub_powergating_by_smu,
1519
};