drm/amdgpu: Add new AMDGPU_PP_SENSOR_MIN/MAX_FAN_RPM sensor
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / amd_powerplay.c
CommitLineData
1f7371b2
AD
1/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
7bd55429 23#include "pp_debug.h"
1f7371b2
AD
24#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/gfp.h>
ac885b3a 27#include <linux/slab.h>
64f6db77 28#include <linux/firmware.h>
1f7371b2
AD
29#include "amd_shared.h"
30#include "amd_powerplay.h"
577bbe01 31#include "power_state.h"
a2c120ce 32#include "amdgpu.h"
65ad7cac 33#include "hwmgr.h"
1f7371b2 34
6d07fe7b 35
b905090d 36static const struct amd_pm_funcs pp_dpm_funcs;
3bace359 37
a2c120ce 38static int amd_powerplay_create(struct amdgpu_device *adev)
139a285f 39{
b905090d 40 struct pp_hwmgr *hwmgr;
139a285f 41
a2c120ce 42 if (adev == NULL)
139a285f
RZ
43 return -EINVAL;
44
b905090d
RZ
45 hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
46 if (hwmgr == NULL)
139a285f
RZ
47 return -ENOMEM;
48
b905090d 49 hwmgr->adev = adev;
8bb575a2
RZ
50 hwmgr->not_vf = !amdgpu_sriov_vf(adev);
51 hwmgr->pm_en = (amdgpu_dpm && hwmgr->not_vf) ? true : false;
b905090d
RZ
52 hwmgr->device = amdgpu_cgs_create_device(adev);
53 mutex_init(&hwmgr->smu_lock);
54 hwmgr->chip_family = adev->family;
55 hwmgr->chip_id = adev->asic_type;
00f54b97 56 hwmgr->feature_mask = adev->powerplay.pp_feature;
555fd70c 57 hwmgr->display_config = &adev->pm.pm_display_cfg;
b905090d
RZ
58 adev->powerplay.pp_handle = hwmgr;
59 adev->powerplay.pp_funcs = &pp_dpm_funcs;
139a285f
RZ
60 return 0;
61}
62
a2c120ce 63
ba8ab90e 64static void amd_powerplay_destroy(struct amdgpu_device *adev)
139a285f 65{
b905090d 66 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
139a285f 67
b905090d
RZ
68 kfree(hwmgr->hardcode_pp_table);
69 hwmgr->hardcode_pp_table = NULL;
7b38a49d 70
b905090d
RZ
71 kfree(hwmgr);
72 hwmgr = NULL;
139a285f
RZ
73}
74
1c863802
RZ
75static int pp_early_init(void *handle)
76{
77 int ret;
b905090d 78 struct amdgpu_device *adev = handle;
139a285f 79
a2c120ce 80 ret = amd_powerplay_create(adev);
139a285f 81
a2c120ce
RZ
82 if (ret != 0)
83 return ret;
84
b905090d 85 ret = hwmgr_early_init(adev->powerplay.pp_handle);
9441f964 86 if (ret)
b3b03052 87 return -EINVAL;
1c863802 88
b4eeed59 89 return 0;
1f7371b2
AD
90}
91
1c863802 92static int pp_sw_init(void *handle)
1f7371b2 93{
b905090d
RZ
94 struct amdgpu_device *adev = handle;
95 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
3bace359
JZ
96 int ret = 0;
97
ba8ab90e 98 ret = hwmgr_sw_init(hwmgr);
7383bcb9 99
ba8ab90e 100 pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");
b905090d 101
1c863802
RZ
102 return ret;
103}
3bace359 104
1c863802
RZ
105static int pp_sw_fini(void *handle)
106{
b905090d
RZ
107 struct amdgpu_device *adev = handle;
108 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
1c863802 109
ba8ab90e 110 hwmgr_sw_fini(hwmgr);
2dac5936 111
64f6db77
RZ
112 if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
113 release_firmware(adev->pm.fw);
114 adev->pm.fw = NULL;
2dac5936 115 amdgpu_ucode_fini_bo(adev);
64f6db77 116 }
2dac5936 117
b905090d 118 return 0;
1f7371b2
AD
119}
120
121static int pp_hw_init(void *handle)
122{
ac885b3a 123 int ret = 0;
b905090d
RZ
124 struct amdgpu_device *adev = handle;
125 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
ac885b3a 126
b905090d
RZ
127 if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
128 amdgpu_ucode_init_bo(adev);
ac885b3a 129
ba8ab90e 130 ret = hwmgr_hw_init(hwmgr);
ac885b3a 131
ba8ab90e
RZ
132 if (ret)
133 pr_err("powerplay hw init failed\n");
ac885b3a 134
e5f23736 135 return ret;
1f7371b2
AD
136}
137
138static int pp_hw_fini(void *handle)
139{
b905090d
RZ
140 struct amdgpu_device *adev = handle;
141 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
ac885b3a 142
ba8ab90e 143 hwmgr_hw_fini(hwmgr);
df1e6394 144
1f7371b2
AD
145 return 0;
146}
147
7951e376
RZ
148static void pp_reserve_vram_for_smu(struct amdgpu_device *adev)
149{
150 int r = -EINVAL;
151 void *cpu_ptr = NULL;
152 uint64_t gpu_addr;
153 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
154
155 if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size,
156 PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
157 &adev->pm.smu_prv_buffer,
158 &gpu_addr,
159 &cpu_ptr)) {
160 DRM_ERROR("amdgpu: failed to create smu prv buffer\n");
161 return;
162 }
163
164 if (hwmgr->hwmgr_func->notify_cac_buffer_info)
165 r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr,
166 lower_32_bits((unsigned long)cpu_ptr),
167 upper_32_bits((unsigned long)cpu_ptr),
168 lower_32_bits(gpu_addr),
169 upper_32_bits(gpu_addr),
170 adev->pm.smu_prv_buffer_size);
171
172 if (r) {
173 amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
174 adev->pm.smu_prv_buffer = NULL;
175 DRM_ERROR("amdgpu: failed to notify SMU buffer address\n");
176 }
177}
178
6d07fe7b
RZ
179static int pp_late_init(void *handle)
180{
b905090d
RZ
181 struct amdgpu_device *adev = handle;
182 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
b905090d 183
b61e54cb
RZ
184 if (hwmgr && hwmgr->pm_en) {
185 mutex_lock(&hwmgr->smu_lock);
186 hwmgr_handle_task(hwmgr,
39199b80 187 AMD_PP_TASK_COMPLETE_INIT, NULL);
b61e54cb
RZ
188 mutex_unlock(&hwmgr->smu_lock);
189 }
7951e376
RZ
190 if (adev->pm.smu_prv_buffer_size != 0)
191 pp_reserve_vram_for_smu(adev);
9667849b 192
6d07fe7b
RZ
193 return 0;
194}
195
139a285f
RZ
196static void pp_late_fini(void *handle)
197{
2dac5936
RZ
198 struct amdgpu_device *adev = handle;
199
7951e376
RZ
200 if (adev->pm.smu_prv_buffer)
201 amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
2dac5936 202 amd_powerplay_destroy(adev);
139a285f
RZ
203}
204
205
1f7371b2
AD
206static bool pp_is_idle(void *handle)
207{
ed5121a3 208 return false;
1f7371b2
AD
209}
210
211static int pp_wait_for_idle(void *handle)
212{
213 return 0;
214}
215
216static int pp_sw_reset(void *handle)
217{
218 return 0;
219}
220
1f7371b2
AD
221static int pp_set_powergating_state(void *handle,
222 enum amd_powergating_state state)
223{
85f80cb3 224 return 0;
1f7371b2
AD
225}
226
227static int pp_suspend(void *handle)
228{
b905090d
RZ
229 struct amdgpu_device *adev = handle;
230 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
577bbe01 231
ba8ab90e 232 return hwmgr_suspend(hwmgr);
1f7371b2
AD
233}
234
235static int pp_resume(void *handle)
236{
b905090d
RZ
237 struct amdgpu_device *adev = handle;
238 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
1c863802 239
ba8ab90e 240 return hwmgr_resume(hwmgr);
1f7371b2
AD
241}
242
f004938f
AG
243static int pp_set_clockgating_state(void *handle,
244 enum amd_clockgating_state state)
245{
246 return 0;
247}
248
b905090d 249static const struct amd_ip_funcs pp_ip_funcs = {
88a907d6 250 .name = "powerplay",
1f7371b2 251 .early_init = pp_early_init,
6d07fe7b 252 .late_init = pp_late_init,
1f7371b2
AD
253 .sw_init = pp_sw_init,
254 .sw_fini = pp_sw_fini,
255 .hw_init = pp_hw_init,
256 .hw_fini = pp_hw_fini,
139a285f 257 .late_fini = pp_late_fini,
1f7371b2
AD
258 .suspend = pp_suspend,
259 .resume = pp_resume,
260 .is_idle = pp_is_idle,
261 .wait_for_idle = pp_wait_for_idle,
262 .soft_reset = pp_sw_reset,
f004938f 263 .set_clockgating_state = pp_set_clockgating_state,
1f7371b2
AD
264 .set_powergating_state = pp_set_powergating_state,
265};
266
b905090d
RZ
267const struct amdgpu_ip_block_version pp_smu_ip_block =
268{
269 .type = AMD_IP_BLOCK_TYPE_SMC,
270 .major = 1,
271 .minor = 0,
272 .rev = 0,
273 .funcs = &pp_ip_funcs,
274};
275
1f7371b2
AD
276static int pp_dpm_load_fw(void *handle)
277{
278 return 0;
279}
280
281static int pp_dpm_fw_loading_complete(void *handle)
282{
283 return 0;
284}
285
3811f8f0
RZ
286static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
287{
b905090d 288 struct pp_hwmgr *hwmgr = handle;
3811f8f0 289
ba8ab90e
RZ
290 if (!hwmgr || !hwmgr->pm_en)
291 return -EINVAL;
3811f8f0 292
3811f8f0
RZ
293 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
294 pr_info("%s was not implemented.\n", __func__);
295 return 0;
296 }
297
298 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
299}
300
9947f704
RZ
301static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
302 enum amd_dpm_forced_level *level)
303{
304 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
305 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
306 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
307 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
308
309 if (!(hwmgr->dpm_level & profile_mode_mask)) {
310 /* enter umd pstate, save current level, disable gfx cg*/
311 if (*level & profile_mode_mask) {
312 hwmgr->saved_dpm_level = hwmgr->dpm_level;
313 hwmgr->en_umd_pstate = true;
43fa561f 314 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
9947f704
RZ
315 AMD_IP_BLOCK_TYPE_GFX,
316 AMD_CG_STATE_UNGATE);
43fa561f 317 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
9947f704
RZ
318 AMD_IP_BLOCK_TYPE_GFX,
319 AMD_PG_STATE_UNGATE);
320 }
321 } else {
322 /* exit umd pstate, restore level, enable gfx cg*/
323 if (!(*level & profile_mode_mask)) {
324 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
325 *level = hwmgr->saved_dpm_level;
326 hwmgr->en_umd_pstate = false;
43fa561f 327 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
9947f704
RZ
328 AMD_IP_BLOCK_TYPE_GFX,
329 AMD_CG_STATE_GATE);
43fa561f 330 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
9947f704
RZ
331 AMD_IP_BLOCK_TYPE_GFX,
332 AMD_PG_STATE_GATE);
333 }
334 }
335}
336
1f7371b2
AD
337static int pp_dpm_force_performance_level(void *handle,
338 enum amd_dpm_forced_level level)
339{
b905090d 340 struct pp_hwmgr *hwmgr = handle;
577bbe01 341
ba8ab90e
RZ
342 if (!hwmgr || !hwmgr->pm_en)
343 return -EINVAL;
577bbe01 344
9947f704
RZ
345 if (level == hwmgr->dpm_level)
346 return 0;
347
b905090d 348 mutex_lock(&hwmgr->smu_lock);
9947f704
RZ
349 pp_dpm_en_umd_pstate(hwmgr, &level);
350 hwmgr->request_dpm_level = level;
b905090d
RZ
351 hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
352 mutex_unlock(&hwmgr->smu_lock);
8621bbbb 353
1f7371b2
AD
354 return 0;
355}
577bbe01 356
1f7371b2
AD
357static enum amd_dpm_forced_level pp_dpm_get_performance_level(
358 void *handle)
359{
b905090d 360 struct pp_hwmgr *hwmgr = handle;
2a507105 361 enum amd_dpm_forced_level level;
577bbe01 362
ba8ab90e
RZ
363 if (!hwmgr || !hwmgr->pm_en)
364 return -EINVAL;
577bbe01 365
b905090d 366 mutex_lock(&hwmgr->smu_lock);
2a507105 367 level = hwmgr->dpm_level;
b905090d 368 mutex_unlock(&hwmgr->smu_lock);
2a507105 369 return level;
1f7371b2 370}
577bbe01 371
f93f0c3a 372static uint32_t pp_dpm_get_sclk(void *handle, bool low)
1f7371b2 373{
b905090d 374 struct pp_hwmgr *hwmgr = handle;
f93f0c3a 375 uint32_t clk = 0;
577bbe01 376
ba8ab90e
RZ
377 if (!hwmgr || !hwmgr->pm_en)
378 return 0;
577bbe01 379
7383bcb9 380 if (hwmgr->hwmgr_func->get_sclk == NULL) {
0fb829de 381 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
382 return 0;
383 }
b905090d 384 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 385 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
b905090d 386 mutex_unlock(&hwmgr->smu_lock);
f93f0c3a 387 return clk;
1f7371b2 388}
577bbe01 389
f93f0c3a 390static uint32_t pp_dpm_get_mclk(void *handle, bool low)
1f7371b2 391{
b905090d 392 struct pp_hwmgr *hwmgr = handle;
f93f0c3a 393 uint32_t clk = 0;
577bbe01 394
ba8ab90e
RZ
395 if (!hwmgr || !hwmgr->pm_en)
396 return 0;
577bbe01 397
7383bcb9 398 if (hwmgr->hwmgr_func->get_mclk == NULL) {
0fb829de 399 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
400 return 0;
401 }
b905090d 402 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 403 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
b905090d 404 mutex_unlock(&hwmgr->smu_lock);
f93f0c3a 405 return clk;
1f7371b2 406}
577bbe01 407
f93f0c3a 408static void pp_dpm_powergate_vce(void *handle, bool gate)
1f7371b2 409{
b905090d 410 struct pp_hwmgr *hwmgr = handle;
577bbe01 411
ba8ab90e 412 if (!hwmgr || !hwmgr->pm_en)
f93f0c3a 413 return;
577bbe01 414
7383bcb9 415 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
0fb829de 416 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 417 return;
7383bcb9 418 }
b905090d 419 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 420 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
b905090d 421 mutex_unlock(&hwmgr->smu_lock);
1f7371b2 422}
577bbe01 423
f93f0c3a 424static void pp_dpm_powergate_uvd(void *handle, bool gate)
1f7371b2 425{
b905090d 426 struct pp_hwmgr *hwmgr = handle;
577bbe01 427
ba8ab90e 428 if (!hwmgr || !hwmgr->pm_en)
f93f0c3a 429 return;
577bbe01 430
7383bcb9 431 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
0fb829de 432 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 433 return;
7383bcb9 434 }
b905090d 435 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 436 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
b905090d 437 mutex_unlock(&hwmgr->smu_lock);
577bbe01
RZ
438}
439
df1e6394 440static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
39199b80 441 enum amd_pm_state_type *user_state)
1f7371b2 442{
577bbe01 443 int ret = 0;
b905090d 444 struct pp_hwmgr *hwmgr = handle;
577bbe01 445
ba8ab90e
RZ
446 if (!hwmgr || !hwmgr->pm_en)
447 return -EINVAL;
577bbe01 448
b905090d
RZ
449 mutex_lock(&hwmgr->smu_lock);
450 ret = hwmgr_handle_task(hwmgr, task_id, user_state);
451 mutex_unlock(&hwmgr->smu_lock);
df1e6394 452
577bbe01 453 return ret;
1f7371b2 454}
577bbe01 455
f8a4c11b 456static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
1f7371b2 457{
b905090d 458 struct pp_hwmgr *hwmgr = handle;
577bbe01 459 struct pp_power_state *state;
2a507105 460 enum amd_pm_state_type pm_type;
577bbe01 461
ba8ab90e 462 if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)
577bbe01
RZ
463 return -EINVAL;
464
b905090d 465 mutex_lock(&hwmgr->smu_lock);
2a507105 466
577bbe01
RZ
467 state = hwmgr->current_ps;
468
469 switch (state->classification.ui_label) {
470 case PP_StateUILabel_Battery:
2a507105 471 pm_type = POWER_STATE_TYPE_BATTERY;
0f987cd0 472 break;
577bbe01 473 case PP_StateUILabel_Balanced:
2a507105 474 pm_type = POWER_STATE_TYPE_BALANCED;
0f987cd0 475 break;
577bbe01 476 case PP_StateUILabel_Performance:
2a507105 477 pm_type = POWER_STATE_TYPE_PERFORMANCE;
0f987cd0 478 break;
577bbe01 479 default:
f3898ea1 480 if (state->classification.flags & PP_StateClassificationFlag_Boot)
2a507105 481 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
f3898ea1 482 else
2a507105 483 pm_type = POWER_STATE_TYPE_DEFAULT;
0f987cd0 484 break;
577bbe01 485 }
b905090d 486 mutex_unlock(&hwmgr->smu_lock);
2a507105
RZ
487
488 return pm_type;
1f7371b2 489}
577bbe01 490
f93f0c3a 491static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
cac9a199 492{
b905090d 493 struct pp_hwmgr *hwmgr = handle;
cac9a199 494
ba8ab90e 495 if (!hwmgr || !hwmgr->pm_en)
f93f0c3a 496 return;
cac9a199 497
7383bcb9 498 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
0fb829de 499 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 500 return;
7383bcb9 501 }
b905090d 502 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 503 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
b905090d 504 mutex_unlock(&hwmgr->smu_lock);
cac9a199
RZ
505}
506
f93f0c3a 507static uint32_t pp_dpm_get_fan_control_mode(void *handle)
cac9a199 508{
b905090d 509 struct pp_hwmgr *hwmgr = handle;
f93f0c3a 510 uint32_t mode = 0;
cac9a199 511
ba8ab90e
RZ
512 if (!hwmgr || !hwmgr->pm_en)
513 return 0;
cac9a199 514
7383bcb9 515 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
0fb829de 516 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
517 return 0;
518 }
b905090d 519 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 520 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
b905090d 521 mutex_unlock(&hwmgr->smu_lock);
f93f0c3a 522 return mode;
cac9a199
RZ
523}
524
525static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
526{
b905090d 527 struct pp_hwmgr *hwmgr = handle;
1c863802 528 int ret = 0;
cac9a199 529
ba8ab90e
RZ
530 if (!hwmgr || !hwmgr->pm_en)
531 return -EINVAL;
cac9a199 532
7383bcb9 533 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
0fb829de 534 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
535 return 0;
536 }
b905090d 537 mutex_lock(&hwmgr->smu_lock);
2a507105 538 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
b905090d 539 mutex_unlock(&hwmgr->smu_lock);
2a507105 540 return ret;
cac9a199
RZ
541}
542
543static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
544{
b905090d 545 struct pp_hwmgr *hwmgr = handle;
1c863802 546 int ret = 0;
cac9a199 547
ba8ab90e
RZ
548 if (!hwmgr || !hwmgr->pm_en)
549 return -EINVAL;
cac9a199 550
7383bcb9 551 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
0fb829de 552 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
553 return 0;
554 }
cac9a199 555
b905090d 556 mutex_lock(&hwmgr->smu_lock);
2a507105 557 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
b905090d 558 mutex_unlock(&hwmgr->smu_lock);
2a507105 559 return ret;
cac9a199
RZ
560}
561
72a16a9d
GI
562static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
563{
b905090d 564 struct pp_hwmgr *hwmgr = handle;
1c863802 565 int ret = 0;
72a16a9d 566
ba8ab90e
RZ
567 if (!hwmgr || !hwmgr->pm_en)
568 return -EINVAL;
72a16a9d 569
72a16a9d
GI
570 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
571 return -EINVAL;
572
b905090d 573 mutex_lock(&hwmgr->smu_lock);
2a507105 574 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
b905090d 575 mutex_unlock(&hwmgr->smu_lock);
2a507105 576 return ret;
72a16a9d
GI
577}
578
f3898ea1
EH
579static int pp_dpm_get_pp_num_states(void *handle,
580 struct pp_states_info *data)
581{
b905090d 582 struct pp_hwmgr *hwmgr = handle;
f3898ea1
EH
583 int i;
584
4dbda35f
EQ
585 memset(data, 0, sizeof(*data));
586
ba8ab90e 587 if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps)
f3898ea1
EH
588 return -EINVAL;
589
b905090d 590 mutex_lock(&hwmgr->smu_lock);
2a507105 591
f3898ea1
EH
592 data->nums = hwmgr->num_ps;
593
594 for (i = 0; i < hwmgr->num_ps; i++) {
595 struct pp_power_state *state = (struct pp_power_state *)
596 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
597 switch (state->classification.ui_label) {
598 case PP_StateUILabel_Battery:
599 data->states[i] = POWER_STATE_TYPE_BATTERY;
600 break;
601 case PP_StateUILabel_Balanced:
602 data->states[i] = POWER_STATE_TYPE_BALANCED;
603 break;
604 case PP_StateUILabel_Performance:
605 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
606 break;
607 default:
608 if (state->classification.flags & PP_StateClassificationFlag_Boot)
609 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
610 else
611 data->states[i] = POWER_STATE_TYPE_DEFAULT;
612 }
613 }
b905090d 614 mutex_unlock(&hwmgr->smu_lock);
f3898ea1
EH
615 return 0;
616}
617
618static int pp_dpm_get_pp_table(void *handle, char **table)
619{
b905090d 620 struct pp_hwmgr *hwmgr = handle;
2a507105 621 int size = 0;
f3898ea1 622
ba8ab90e 623 if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table)
4dcf9e6f
EH
624 return -EINVAL;
625
b905090d 626 mutex_lock(&hwmgr->smu_lock);
4dcf9e6f 627 *table = (char *)hwmgr->soft_pp_table;
2a507105 628 size = hwmgr->soft_pp_table_size;
b905090d 629 mutex_unlock(&hwmgr->smu_lock);
2a507105 630 return size;
f3898ea1
EH
631}
632
f685d714
RZ
633static int amd_powerplay_reset(void *handle)
634{
b905090d 635 struct pp_hwmgr *hwmgr = handle;
f685d714
RZ
636 int ret;
637
46b27ee9 638 ret = hwmgr_hw_fini(hwmgr);
f685d714
RZ
639 if (ret)
640 return ret;
641
b905090d 642 ret = hwmgr_hw_init(hwmgr);
f685d714
RZ
643 if (ret)
644 return ret;
645
b905090d 646 return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL);
f685d714
RZ
647}
648
f3898ea1
EH
649static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
650{
b905090d 651 struct pp_hwmgr *hwmgr = handle;
b61e54cb 652 int ret = -ENOMEM;
f3898ea1 653
ba8ab90e
RZ
654 if (!hwmgr || !hwmgr->pm_en)
655 return -EINVAL;
f3898ea1 656
b905090d 657 mutex_lock(&hwmgr->smu_lock);
4dcf9e6f 658 if (!hwmgr->hardcode_pp_table) {
efdf7a93
EC
659 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
660 hwmgr->soft_pp_table_size,
661 GFP_KERNEL);
b61e54cb
RZ
662 if (!hwmgr->hardcode_pp_table)
663 goto err;
7383bcb9 664 }
f3898ea1 665
4dcf9e6f
EH
666 memcpy(hwmgr->hardcode_pp_table, buf, size);
667
668 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
669
dd4bdf3b
EH
670 ret = amd_powerplay_reset(handle);
671 if (ret)
b61e54cb 672 goto err;
dd4bdf3b
EH
673
674 if (hwmgr->hwmgr_func->avfs_control) {
675 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
676 if (ret)
b61e54cb 677 goto err;
dd4bdf3b 678 }
b61e54cb 679 mutex_unlock(&hwmgr->smu_lock);
dd4bdf3b 680 return 0;
b61e54cb
RZ
681err:
682 mutex_unlock(&hwmgr->smu_lock);
683 return ret;
f3898ea1
EH
684}
685
686static int pp_dpm_force_clock_level(void *handle,
5632708f 687 enum pp_clock_type type, uint32_t mask)
f3898ea1 688{
b905090d 689 struct pp_hwmgr *hwmgr = handle;
1c863802 690 int ret = 0;
f3898ea1 691
ba8ab90e
RZ
692 if (!hwmgr || !hwmgr->pm_en)
693 return -EINVAL;
f3898ea1 694
7383bcb9 695 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
0fb829de 696 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
697 return 0;
698 }
b905090d 699 mutex_lock(&hwmgr->smu_lock);
948fd66c
RZ
700 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
701 ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
702 else
703 ret = -EINVAL;
b905090d 704 mutex_unlock(&hwmgr->smu_lock);
2a507105 705 return ret;
f3898ea1
EH
706}
707
708static int pp_dpm_print_clock_levels(void *handle,
709 enum pp_clock_type type, char *buf)
710{
b905090d 711 struct pp_hwmgr *hwmgr = handle;
1c863802 712 int ret = 0;
f3898ea1 713
ba8ab90e
RZ
714 if (!hwmgr || !hwmgr->pm_en)
715 return -EINVAL;
f3898ea1 716
7383bcb9 717 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
0fb829de 718 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
719 return 0;
720 }
b905090d 721 mutex_lock(&hwmgr->smu_lock);
2a507105 722 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
b905090d 723 mutex_unlock(&hwmgr->smu_lock);
2a507105 724 return ret;
f3898ea1
EH
725}
726
428bafa8
EH
727static int pp_dpm_get_sclk_od(void *handle)
728{
b905090d 729 struct pp_hwmgr *hwmgr = handle;
1c863802 730 int ret = 0;
428bafa8 731
ba8ab90e
RZ
732 if (!hwmgr || !hwmgr->pm_en)
733 return -EINVAL;
428bafa8 734
428bafa8 735 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
0fb829de 736 pr_info("%s was not implemented.\n", __func__);
428bafa8
EH
737 return 0;
738 }
b905090d 739 mutex_lock(&hwmgr->smu_lock);
2a507105 740 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
b905090d 741 mutex_unlock(&hwmgr->smu_lock);
2a507105 742 return ret;
428bafa8
EH
743}
744
745static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
746{
b905090d 747 struct pp_hwmgr *hwmgr = handle;
1c863802 748 int ret = 0;
428bafa8 749
ba8ab90e
RZ
750 if (!hwmgr || !hwmgr->pm_en)
751 return -EINVAL;
428bafa8 752
428bafa8 753 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
0fb829de 754 pr_info("%s was not implemented.\n", __func__);
428bafa8
EH
755 return 0;
756 }
757
b905090d 758 mutex_lock(&hwmgr->smu_lock);
2a507105 759 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
b905090d 760 mutex_unlock(&hwmgr->smu_lock);
2a507105 761 return ret;
428bafa8
EH
762}
763
f2bdc05f
EH
764static int pp_dpm_get_mclk_od(void *handle)
765{
b905090d 766 struct pp_hwmgr *hwmgr = handle;
1c863802 767 int ret = 0;
f2bdc05f 768
ba8ab90e
RZ
769 if (!hwmgr || !hwmgr->pm_en)
770 return -EINVAL;
f2bdc05f 771
f2bdc05f 772 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
0fb829de 773 pr_info("%s was not implemented.\n", __func__);
f2bdc05f
EH
774 return 0;
775 }
b905090d 776 mutex_lock(&hwmgr->smu_lock);
2a507105 777 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
b905090d 778 mutex_unlock(&hwmgr->smu_lock);
2a507105 779 return ret;
f2bdc05f
EH
780}
781
782static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
783{
b905090d 784 struct pp_hwmgr *hwmgr = handle;
1c863802 785 int ret = 0;
f2bdc05f 786
ba8ab90e
RZ
787 if (!hwmgr || !hwmgr->pm_en)
788 return -EINVAL;
f2bdc05f 789
f2bdc05f 790 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
0fb829de 791 pr_info("%s was not implemented.\n", __func__);
f2bdc05f
EH
792 return 0;
793 }
b905090d 794 mutex_lock(&hwmgr->smu_lock);
2a507105 795 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
b905090d 796 mutex_unlock(&hwmgr->smu_lock);
2a507105 797 return ret;
f2bdc05f
EH
798}
799
9f8df7d7
TSD
800static int pp_dpm_read_sensor(void *handle, int idx,
801 void *value, int *size)
a6e36952 802{
b905090d 803 struct pp_hwmgr *hwmgr = handle;
1c863802 804 int ret = 0;
a6e36952 805
ba8ab90e 806 if (!hwmgr || !hwmgr->pm_en || !value)
5ed8d656
RZ
807 return -EINVAL;
808
5ed8d656
RZ
809 switch (idx) {
810 case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
811 *((uint32_t *)value) = hwmgr->pstate_sclk;
812 return 0;
813 case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
814 *((uint32_t *)value) = hwmgr->pstate_mclk;
a6e36952 815 return 0;
5ed8d656 816 default:
b905090d 817 mutex_lock(&hwmgr->smu_lock);
5ed8d656 818 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
b905090d 819 mutex_unlock(&hwmgr->smu_lock);
5ed8d656 820 return ret;
a6e36952 821 }
a6e36952
TSD
822}
823
597be302
AD
824static struct amd_vce_state*
825pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
826{
b905090d 827 struct pp_hwmgr *hwmgr = handle;
597be302 828
ba8ab90e 829 if (!hwmgr || !hwmgr->pm_en)
1c863802
RZ
830 return NULL;
831
ba8ab90e 832 if (idx < hwmgr->num_vce_state_tables)
1c863802 833 return &hwmgr->vce_states[idx];
597be302
AD
834 return NULL;
835}
836
6390258a
RZ
837static int pp_get_power_profile_mode(void *handle, char *buf)
838{
b905090d 839 struct pp_hwmgr *hwmgr = handle;
6390258a 840
ba8ab90e 841 if (!hwmgr || !hwmgr->pm_en || !buf)
6390258a
RZ
842 return -EINVAL;
843
6390258a
RZ
844 if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) {
845 pr_info("%s was not implemented.\n", __func__);
846 return snprintf(buf, PAGE_SIZE, "\n");
847 }
848
849 return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
850}
851
852static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
853{
b905090d 854 struct pp_hwmgr *hwmgr = handle;
337ecd6a 855 int ret = -EINVAL;
6390258a 856
ba8ab90e
RZ
857 if (!hwmgr || !hwmgr->pm_en)
858 return ret;
6390258a 859
6390258a
RZ
860 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
861 pr_info("%s was not implemented.\n", __func__);
ba8ab90e 862 return ret;
6390258a 863 }
b905090d 864 mutex_lock(&hwmgr->smu_lock);
337ecd6a
RZ
865 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
866 ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
b905090d 867 mutex_unlock(&hwmgr->smu_lock);
337ecd6a 868 return ret;
6390258a
RZ
869}
870
e3933f26
RZ
871static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
872{
b905090d 873 struct pp_hwmgr *hwmgr = handle;
e3933f26 874
ba8ab90e 875 if (!hwmgr || !hwmgr->pm_en)
e3933f26
RZ
876 return -EINVAL;
877
e3933f26
RZ
878 if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {
879 pr_info("%s was not implemented.\n", __func__);
880 return -EINVAL;
881 }
882
883 return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
884}
885
34bb2734 886static int pp_dpm_switch_power_profile(void *handle,
052fe96d 887 enum PP_SMC_POWER_PROFILE type, bool en)
34bb2734 888{
b905090d 889 struct pp_hwmgr *hwmgr = handle;
052fe96d
RZ
890 long workload;
891 uint32_t index;
34bb2734 892
ba8ab90e 893 if (!hwmgr || !hwmgr->pm_en)
34bb2734
EH
894 return -EINVAL;
895
052fe96d
RZ
896 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
897 pr_info("%s was not implemented.\n", __func__);
898 return -EINVAL;
899 }
900
901 if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
902 return -EINVAL;
903
b905090d 904 mutex_lock(&hwmgr->smu_lock);
052fe96d
RZ
905
906 if (!en) {
907 hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
908 index = fls(hwmgr->workload_mask);
909 index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
910 workload = hwmgr->workload_setting[index];
911 } else {
912 hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
913 index = fls(hwmgr->workload_mask);
914 index = index <= Workload_Policy_Max ? index - 1 : 0;
915 workload = hwmgr->workload_setting[index];
34bb2734
EH
916 }
917
052fe96d
RZ
918 if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
919 hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
b905090d 920 mutex_unlock(&hwmgr->smu_lock);
052fe96d 921
34bb2734
EH
922 return 0;
923}
924
6ab8555e
RZ
925static int pp_set_power_limit(void *handle, uint32_t limit)
926{
b905090d 927 struct pp_hwmgr *hwmgr = handle;
6ab8555e 928
ba8ab90e
RZ
929 if (!hwmgr || !hwmgr->pm_en)
930 return -EINVAL;
6ab8555e 931
6ab8555e
RZ
932 if (hwmgr->hwmgr_func->set_power_limit == NULL) {
933 pr_info("%s was not implemented.\n", __func__);
934 return -EINVAL;
935 }
936
937 if (limit == 0)
938 limit = hwmgr->default_power_limit;
939
940 if (limit > hwmgr->default_power_limit)
941 return -EINVAL;
942
b905090d 943 mutex_lock(&hwmgr->smu_lock);
6ab8555e
RZ
944 hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
945 hwmgr->power_limit = limit;
b905090d 946 mutex_unlock(&hwmgr->smu_lock);
ba8ab90e 947 return 0;
6ab8555e
RZ
948}
949
950static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
951{
b905090d 952 struct pp_hwmgr *hwmgr = handle;
6ab8555e 953
ba8ab90e 954 if (!hwmgr || !hwmgr->pm_en ||!limit)
6ab8555e
RZ
955 return -EINVAL;
956
b905090d 957 mutex_lock(&hwmgr->smu_lock);
6ab8555e
RZ
958
959 if (default_limit)
960 *limit = hwmgr->default_power_limit;
961 else
962 *limit = hwmgr->power_limit;
963
b905090d 964 mutex_unlock(&hwmgr->smu_lock);
6ab8555e 965
ba8ab90e 966 return 0;
6ab8555e
RZ
967}
968
f685d714 969static int pp_display_configuration_change(void *handle,
155f1127 970 const struct amd_pp_display_configuration *display_config)
7fb72a1f 971{
b905090d 972 struct pp_hwmgr *hwmgr = handle;
7fb72a1f 973
ba8ab90e
RZ
974 if (!hwmgr || !hwmgr->pm_en)
975 return -EINVAL;
7fb72a1f 976
b905090d 977 mutex_lock(&hwmgr->smu_lock);
7fb72a1f 978 phm_store_dal_configuration_data(hwmgr, display_config);
b905090d 979 mutex_unlock(&hwmgr->smu_lock);
7fb72a1f
RZ
980 return 0;
981}
c4dd206b 982
f685d714 983static int pp_get_display_power_level(void *handle,
47329134 984 struct amd_pp_simple_clock_info *output)
c4dd206b 985{
b905090d 986 struct pp_hwmgr *hwmgr = handle;
1c863802 987 int ret = 0;
c4dd206b 988
ba8ab90e 989 if (!hwmgr || !hwmgr->pm_en ||!output)
1c863802 990 return -EINVAL;
ba5f884c 991
b905090d 992 mutex_lock(&hwmgr->smu_lock);
2a507105 993 ret = phm_get_dal_power_level(hwmgr, output);
b905090d 994 mutex_unlock(&hwmgr->smu_lock);
2a507105 995 return ret;
c4dd206b 996}
e273b041 997
f685d714 998static int pp_get_current_clocks(void *handle,
155f1127 999 struct amd_pp_clock_info *clocks)
e273b041 1000{
97e8f102 1001 struct amd_pp_simple_clock_info simple_clocks = { 0 };
e273b041 1002 struct pp_clock_info hw_clocks;
b905090d 1003 struct pp_hwmgr *hwmgr = handle;
1c863802 1004 int ret = 0;
e273b041 1005
ba8ab90e
RZ
1006 if (!hwmgr || !hwmgr->pm_en)
1007 return -EINVAL;
e273b041 1008
b905090d 1009 mutex_lock(&hwmgr->smu_lock);
2a507105 1010
e273b041
RZ
1011 phm_get_dal_power_level(hwmgr, &simple_clocks);
1012
2a507105
RZ
1013 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1014 PHM_PlatformCaps_PowerContainment))
1015 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1016 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1017 else
1018 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1019 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1020
ae97988f 1021 if (ret) {
2a507105 1022 pr_info("Error in phm_get_clock_info \n");
b905090d 1023 mutex_unlock(&hwmgr->smu_lock);
2a507105 1024 return -EINVAL;
e273b041
RZ
1025 }
1026
1027 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1028 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1029 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1030 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1031 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1032 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1033
1034 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1035 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1036
97e8f102
RZ
1037 if (simple_clocks.level == 0)
1038 clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;
1039 else
1040 clocks->max_clocks_state = simple_clocks.level;
e273b041
RZ
1041
1042 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1043 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1044 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1045 }
b905090d 1046 mutex_unlock(&hwmgr->smu_lock);
e273b041 1047 return 0;
e273b041
RZ
1048}
1049
f685d714 1050static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
e273b041 1051{
b905090d 1052 struct pp_hwmgr *hwmgr = handle;
1c863802 1053 int ret = 0;
e273b041 1054
ba8ab90e
RZ
1055 if (!hwmgr || !hwmgr->pm_en)
1056 return -EINVAL;
1c863802 1057
fa9e6991 1058 if (clocks == NULL)
e273b041
RZ
1059 return -EINVAL;
1060
b905090d 1061 mutex_lock(&hwmgr->smu_lock);
2a507105 1062 ret = phm_get_clock_by_type(hwmgr, type, clocks);
b905090d 1063 mutex_unlock(&hwmgr->smu_lock);
2a507105 1064 return ret;
e273b041
RZ
1065}
1066
f685d714 1067static int pp_get_clock_by_type_with_latency(void *handle,
d0187727
EH
1068 enum amd_pp_clock_type type,
1069 struct pp_clock_levels_with_latency *clocks)
1070{
b905090d 1071 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1072 int ret = 0;
1073
ba8ab90e 1074 if (!hwmgr || !hwmgr->pm_en ||!clocks)
d0187727
EH
1075 return -EINVAL;
1076
b905090d 1077 mutex_lock(&hwmgr->smu_lock);
d0187727 1078 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
b905090d 1079 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1080 return ret;
1081}
1082
f685d714 1083static int pp_get_clock_by_type_with_voltage(void *handle,
d0187727
EH
1084 enum amd_pp_clock_type type,
1085 struct pp_clock_levels_with_voltage *clocks)
1086{
b905090d 1087 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1088 int ret = 0;
1089
ba8ab90e 1090 if (!hwmgr || !hwmgr->pm_en ||!clocks)
d0187727
EH
1091 return -EINVAL;
1092
b905090d 1093 mutex_lock(&hwmgr->smu_lock);
d0187727
EH
1094
1095 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1096
b905090d 1097 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1098 return ret;
1099}
1100
f685d714 1101static int pp_set_watermarks_for_clocks_ranges(void *handle,
99c5e27d 1102 void *clock_ranges)
d0187727 1103{
b905090d 1104 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1105 int ret = 0;
1106
99c5e27d 1107 if (!hwmgr || !hwmgr->pm_en || !clock_ranges)
d0187727
EH
1108 return -EINVAL;
1109
b905090d 1110 mutex_lock(&hwmgr->smu_lock);
d0187727 1111 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
99c5e27d 1112 clock_ranges);
b905090d 1113 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1114
1115 return ret;
1116}
1117
f685d714 1118static int pp_display_clock_voltage_request(void *handle,
d0187727
EH
1119 struct pp_display_clock_request *clock)
1120{
b905090d 1121 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1122 int ret = 0;
1123
ba8ab90e 1124 if (!hwmgr || !hwmgr->pm_en ||!clock)
d0187727
EH
1125 return -EINVAL;
1126
b905090d 1127 mutex_lock(&hwmgr->smu_lock);
d0187727 1128 ret = phm_display_clock_voltage_request(hwmgr, clock);
b905090d 1129 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1130
1131 return ret;
1132}
1133
f685d714 1134static int pp_get_display_mode_validation_clocks(void *handle,
155f1127 1135 struct amd_pp_simple_clock_info *clocks)
e273b041 1136{
b905090d 1137 struct pp_hwmgr *hwmgr = handle;
1c863802 1138 int ret = 0;
e273b041 1139
ba8ab90e 1140 if (!hwmgr || !hwmgr->pm_en ||!clocks)
1c863802 1141 return -EINVAL;
ba5f884c 1142
97e8f102
RZ
1143 clocks->level = PP_DAL_POWERLEVEL_7;
1144
b905090d 1145 mutex_lock(&hwmgr->smu_lock);
2a507105 1146
e273b041 1147 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1c863802 1148 ret = phm_get_max_high_clocks(hwmgr, clocks);
e273b041 1149
b905090d 1150 mutex_unlock(&hwmgr->smu_lock);
1c863802 1151 return ret;
e273b041
RZ
1152}
1153
a8da8ff3 1154static int pp_dpm_powergate_mmhub(void *handle)
72d76191 1155{
b905090d 1156 struct pp_hwmgr *hwmgr = handle;
72d76191 1157
ba8ab90e
RZ
1158 if (!hwmgr || !hwmgr->pm_en)
1159 return -EINVAL;
72d76191 1160
a8da8ff3 1161 if (hwmgr->hwmgr_func->powergate_mmhub == NULL) {
72d76191
EH
1162 pr_info("%s was not implemented.\n", __func__);
1163 return 0;
1164 }
1165
a8da8ff3 1166 return hwmgr->hwmgr_func->powergate_mmhub(hwmgr);
72d76191
EH
1167}
1168
85f80cb3
RZ
1169static int pp_dpm_powergate_gfx(void *handle, bool gate)
1170{
1171 struct pp_hwmgr *hwmgr = handle;
1172
1173 if (!hwmgr || !hwmgr->pm_en)
1174 return 0;
1175
1176 if (hwmgr->hwmgr_func->powergate_gfx == NULL) {
1177 pr_info("%s was not implemented.\n", __func__);
1178 return 0;
1179 }
1180
1181 return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate);
1182}
1183
982976d9
RZ
1184static void pp_dpm_powergate_acp(void *handle, bool gate)
1185{
1186 struct pp_hwmgr *hwmgr = handle;
1187
1188 if (!hwmgr || !hwmgr->pm_en)
1189 return;
1190
1191 if (hwmgr->hwmgr_func->powergate_acp == NULL) {
1192 pr_info("%s was not implemented.\n", __func__);
1193 return;
1194 }
1195
1196 hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);
1197}
1198
40bea02f
RZ
1199static void pp_dpm_powergate_sdma(void *handle, bool gate)
1200{
1201 struct pp_hwmgr *hwmgr = handle;
1202
1203 if (!hwmgr)
1204 return;
1205
1206 if (hwmgr->hwmgr_func->powergate_sdma == NULL) {
1207 pr_info("%s was not implemented.\n", __func__);
1208 return;
1209 }
1210
1211 hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);
1212}
1213
b92c6287
RZ
1214static int pp_set_powergating_by_smu(void *handle,
1215 uint32_t block_type, bool gate)
1216{
1217 int ret = 0;
1218
1219 switch (block_type) {
1220 case AMD_IP_BLOCK_TYPE_UVD:
1221 case AMD_IP_BLOCK_TYPE_VCN:
1222 pp_dpm_powergate_uvd(handle, gate);
1223 break;
1224 case AMD_IP_BLOCK_TYPE_VCE:
1225 pp_dpm_powergate_vce(handle, gate);
1226 break;
1227 case AMD_IP_BLOCK_TYPE_GMC:
1228 pp_dpm_powergate_mmhub(handle);
1229 break;
1230 case AMD_IP_BLOCK_TYPE_GFX:
85f80cb3 1231 ret = pp_dpm_powergate_gfx(handle, gate);
b92c6287 1232 break;
982976d9
RZ
1233 case AMD_IP_BLOCK_TYPE_ACP:
1234 pp_dpm_powergate_acp(handle, gate);
1235 break;
40bea02f
RZ
1236 case AMD_IP_BLOCK_TYPE_SDMA:
1237 pp_dpm_powergate_sdma(handle, gate);
1238 break;
b92c6287
RZ
1239 default:
1240 break;
1241 }
1242 return ret;
1243}
1244
ea870e44
RZ
1245static int pp_notify_smu_enable_pwe(void *handle)
1246{
1247 struct pp_hwmgr *hwmgr = handle;
1248
1249 if (!hwmgr || !hwmgr->pm_en)
0d7f824b 1250 return -EINVAL;
ea870e44
RZ
1251
1252 if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) {
1253 pr_info("%s was not implemented.\n", __func__);
1254 return -EINVAL;;
1255 }
1256
1257 mutex_lock(&hwmgr->smu_lock);
1258 hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);
1259 mutex_unlock(&hwmgr->smu_lock);
1260
1261 return 0;
1262}
1263
b55c9e7a
EQ
1264static int pp_enable_mgpu_fan_boost(void *handle)
1265{
1266 struct pp_hwmgr *hwmgr = handle;
1267
1268 if (!hwmgr || !hwmgr->pm_en)
1269 return -EINVAL;
1270
1271 if (hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) {
1272 return 0;
1273 }
1274
1275 mutex_lock(&hwmgr->smu_lock);
1276 hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);
1277 mutex_unlock(&hwmgr->smu_lock);
1278
1279 return 0;
1280}
1281
b905090d 1282static const struct amd_pm_funcs pp_dpm_funcs = {
f685d714
RZ
1283 .load_firmware = pp_dpm_load_fw,
1284 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1285 .force_performance_level = pp_dpm_force_performance_level,
1286 .get_performance_level = pp_dpm_get_performance_level,
1287 .get_current_power_state = pp_dpm_get_current_power_state,
f685d714
RZ
1288 .dispatch_tasks = pp_dpm_dispatch_tasks,
1289 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1290 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1291 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1292 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
1293 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1294 .get_pp_num_states = pp_dpm_get_pp_num_states,
1295 .get_pp_table = pp_dpm_get_pp_table,
1296 .set_pp_table = pp_dpm_set_pp_table,
1297 .force_clock_level = pp_dpm_force_clock_level,
1298 .print_clock_levels = pp_dpm_print_clock_levels,
1299 .get_sclk_od = pp_dpm_get_sclk_od,
1300 .set_sclk_od = pp_dpm_set_sclk_od,
1301 .get_mclk_od = pp_dpm_get_mclk_od,
1302 .set_mclk_od = pp_dpm_set_mclk_od,
1303 .read_sensor = pp_dpm_read_sensor,
1304 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
f685d714
RZ
1305 .switch_power_profile = pp_dpm_switch_power_profile,
1306 .set_clockgating_by_smu = pp_set_clockgating_by_smu,
b92c6287 1307 .set_powergating_by_smu = pp_set_powergating_by_smu,
6390258a
RZ
1308 .get_power_profile_mode = pp_get_power_profile_mode,
1309 .set_power_profile_mode = pp_set_power_profile_mode,
e3933f26 1310 .odn_edit_dpm_table = pp_odn_edit_dpm_table,
6ab8555e
RZ
1311 .set_power_limit = pp_set_power_limit,
1312 .get_power_limit = pp_get_power_limit,
f685d714
RZ
1313/* export to DC */
1314 .get_sclk = pp_dpm_get_sclk,
1315 .get_mclk = pp_dpm_get_mclk,
1316 .display_configuration_change = pp_display_configuration_change,
1317 .get_display_power_level = pp_get_display_power_level,
1318 .get_current_clocks = pp_get_current_clocks,
1319 .get_clock_by_type = pp_get_clock_by_type,
1320 .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
1321 .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
1322 .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
1323 .display_clock_voltage_request = pp_display_clock_voltage_request,
1324 .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
ea870e44 1325 .notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
b55c9e7a 1326 .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,
f685d714 1327};