drm/amd/display: Fix dm-pp clks type convert error
[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{
b905090d
RZ
224 struct amdgpu_device *adev = handle;
225 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
775b0c11 226 int ret;
65f85e7d 227
ba8ab90e
RZ
228 if (!hwmgr || !hwmgr->pm_en)
229 return 0;
65f85e7d 230
775b0c11
HR
231 if (hwmgr->hwmgr_func->gfx_off_control) {
232 /* Enable/disable GFX off through SMU */
233 ret = hwmgr->hwmgr_func->gfx_off_control(hwmgr,
234 state == AMD_PG_STATE_GATE);
235 if (ret)
236 pr_err("gfx off control failed!\n");
237 }
238
7383bcb9 239 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
06b18f61 240 pr_debug("%s was not implemented.\n", __func__);
7383bcb9
RZ
241 return 0;
242 }
65f85e7d
EH
243
244 /* Enable/disable GFX per cu powergating through SMU */
245 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
93a4aec2 246 state == AMD_PG_STATE_GATE);
1f7371b2
AD
247}
248
249static int pp_suspend(void *handle)
250{
b905090d
RZ
251 struct amdgpu_device *adev = handle;
252 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
577bbe01 253
ba8ab90e 254 return hwmgr_suspend(hwmgr);
1f7371b2
AD
255}
256
257static int pp_resume(void *handle)
258{
b905090d
RZ
259 struct amdgpu_device *adev = handle;
260 struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
1c863802 261
ba8ab90e 262 return hwmgr_resume(hwmgr);
1f7371b2
AD
263}
264
f004938f
AG
265static int pp_set_clockgating_state(void *handle,
266 enum amd_clockgating_state state)
267{
268 return 0;
269}
270
b905090d 271static const struct amd_ip_funcs pp_ip_funcs = {
88a907d6 272 .name = "powerplay",
1f7371b2 273 .early_init = pp_early_init,
6d07fe7b 274 .late_init = pp_late_init,
1f7371b2
AD
275 .sw_init = pp_sw_init,
276 .sw_fini = pp_sw_fini,
277 .hw_init = pp_hw_init,
278 .hw_fini = pp_hw_fini,
139a285f 279 .late_fini = pp_late_fini,
1f7371b2
AD
280 .suspend = pp_suspend,
281 .resume = pp_resume,
282 .is_idle = pp_is_idle,
283 .wait_for_idle = pp_wait_for_idle,
284 .soft_reset = pp_sw_reset,
f004938f 285 .set_clockgating_state = pp_set_clockgating_state,
1f7371b2
AD
286 .set_powergating_state = pp_set_powergating_state,
287};
288
b905090d
RZ
289const struct amdgpu_ip_block_version pp_smu_ip_block =
290{
291 .type = AMD_IP_BLOCK_TYPE_SMC,
292 .major = 1,
293 .minor = 0,
294 .rev = 0,
295 .funcs = &pp_ip_funcs,
296};
297
1f7371b2
AD
298static int pp_dpm_load_fw(void *handle)
299{
300 return 0;
301}
302
303static int pp_dpm_fw_loading_complete(void *handle)
304{
305 return 0;
306}
307
3811f8f0
RZ
308static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
309{
b905090d 310 struct pp_hwmgr *hwmgr = handle;
3811f8f0 311
ba8ab90e
RZ
312 if (!hwmgr || !hwmgr->pm_en)
313 return -EINVAL;
3811f8f0 314
3811f8f0
RZ
315 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
316 pr_info("%s was not implemented.\n", __func__);
317 return 0;
318 }
319
320 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
321}
322
9947f704
RZ
323static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
324 enum amd_dpm_forced_level *level)
325{
326 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
327 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
328 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
329 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
330
331 if (!(hwmgr->dpm_level & profile_mode_mask)) {
332 /* enter umd pstate, save current level, disable gfx cg*/
333 if (*level & profile_mode_mask) {
334 hwmgr->saved_dpm_level = hwmgr->dpm_level;
335 hwmgr->en_umd_pstate = true;
43fa561f 336 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
9947f704
RZ
337 AMD_IP_BLOCK_TYPE_GFX,
338 AMD_CG_STATE_UNGATE);
43fa561f 339 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
9947f704
RZ
340 AMD_IP_BLOCK_TYPE_GFX,
341 AMD_PG_STATE_UNGATE);
342 }
343 } else {
344 /* exit umd pstate, restore level, enable gfx cg*/
345 if (!(*level & profile_mode_mask)) {
346 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
347 *level = hwmgr->saved_dpm_level;
348 hwmgr->en_umd_pstate = false;
43fa561f 349 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
9947f704
RZ
350 AMD_IP_BLOCK_TYPE_GFX,
351 AMD_CG_STATE_GATE);
43fa561f 352 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
9947f704
RZ
353 AMD_IP_BLOCK_TYPE_GFX,
354 AMD_PG_STATE_GATE);
355 }
356 }
357}
358
1f7371b2
AD
359static int pp_dpm_force_performance_level(void *handle,
360 enum amd_dpm_forced_level level)
361{
b905090d 362 struct pp_hwmgr *hwmgr = handle;
577bbe01 363
ba8ab90e
RZ
364 if (!hwmgr || !hwmgr->pm_en)
365 return -EINVAL;
577bbe01 366
9947f704
RZ
367 if (level == hwmgr->dpm_level)
368 return 0;
369
b905090d 370 mutex_lock(&hwmgr->smu_lock);
9947f704
RZ
371 pp_dpm_en_umd_pstate(hwmgr, &level);
372 hwmgr->request_dpm_level = level;
b905090d
RZ
373 hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
374 mutex_unlock(&hwmgr->smu_lock);
8621bbbb 375
1f7371b2
AD
376 return 0;
377}
577bbe01 378
1f7371b2
AD
379static enum amd_dpm_forced_level pp_dpm_get_performance_level(
380 void *handle)
381{
b905090d 382 struct pp_hwmgr *hwmgr = handle;
2a507105 383 enum amd_dpm_forced_level level;
577bbe01 384
ba8ab90e
RZ
385 if (!hwmgr || !hwmgr->pm_en)
386 return -EINVAL;
577bbe01 387
b905090d 388 mutex_lock(&hwmgr->smu_lock);
2a507105 389 level = hwmgr->dpm_level;
b905090d 390 mutex_unlock(&hwmgr->smu_lock);
2a507105 391 return level;
1f7371b2 392}
577bbe01 393
f93f0c3a 394static uint32_t pp_dpm_get_sclk(void *handle, bool low)
1f7371b2 395{
b905090d 396 struct pp_hwmgr *hwmgr = handle;
f93f0c3a 397 uint32_t clk = 0;
577bbe01 398
ba8ab90e
RZ
399 if (!hwmgr || !hwmgr->pm_en)
400 return 0;
577bbe01 401
7383bcb9 402 if (hwmgr->hwmgr_func->get_sclk == NULL) {
0fb829de 403 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
404 return 0;
405 }
b905090d 406 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 407 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
b905090d 408 mutex_unlock(&hwmgr->smu_lock);
f93f0c3a 409 return clk;
1f7371b2 410}
577bbe01 411
f93f0c3a 412static uint32_t pp_dpm_get_mclk(void *handle, bool low)
1f7371b2 413{
b905090d 414 struct pp_hwmgr *hwmgr = handle;
f93f0c3a 415 uint32_t clk = 0;
577bbe01 416
ba8ab90e
RZ
417 if (!hwmgr || !hwmgr->pm_en)
418 return 0;
577bbe01 419
7383bcb9 420 if (hwmgr->hwmgr_func->get_mclk == NULL) {
0fb829de 421 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
422 return 0;
423 }
b905090d 424 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 425 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
b905090d 426 mutex_unlock(&hwmgr->smu_lock);
f93f0c3a 427 return clk;
1f7371b2 428}
577bbe01 429
f93f0c3a 430static void pp_dpm_powergate_vce(void *handle, bool gate)
1f7371b2 431{
b905090d 432 struct pp_hwmgr *hwmgr = handle;
577bbe01 433
ba8ab90e 434 if (!hwmgr || !hwmgr->pm_en)
f93f0c3a 435 return;
577bbe01 436
7383bcb9 437 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
0fb829de 438 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 439 return;
7383bcb9 440 }
b905090d 441 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 442 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
b905090d 443 mutex_unlock(&hwmgr->smu_lock);
1f7371b2 444}
577bbe01 445
f93f0c3a 446static void pp_dpm_powergate_uvd(void *handle, bool gate)
1f7371b2 447{
b905090d 448 struct pp_hwmgr *hwmgr = handle;
577bbe01 449
ba8ab90e 450 if (!hwmgr || !hwmgr->pm_en)
f93f0c3a 451 return;
577bbe01 452
7383bcb9 453 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
0fb829de 454 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 455 return;
7383bcb9 456 }
b905090d 457 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 458 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
b905090d 459 mutex_unlock(&hwmgr->smu_lock);
577bbe01
RZ
460}
461
df1e6394 462static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
39199b80 463 enum amd_pm_state_type *user_state)
1f7371b2 464{
577bbe01 465 int ret = 0;
b905090d 466 struct pp_hwmgr *hwmgr = handle;
577bbe01 467
ba8ab90e
RZ
468 if (!hwmgr || !hwmgr->pm_en)
469 return -EINVAL;
577bbe01 470
b905090d
RZ
471 mutex_lock(&hwmgr->smu_lock);
472 ret = hwmgr_handle_task(hwmgr, task_id, user_state);
473 mutex_unlock(&hwmgr->smu_lock);
df1e6394 474
577bbe01 475 return ret;
1f7371b2 476}
577bbe01 477
f8a4c11b 478static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
1f7371b2 479{
b905090d 480 struct pp_hwmgr *hwmgr = handle;
577bbe01 481 struct pp_power_state *state;
2a507105 482 enum amd_pm_state_type pm_type;
577bbe01 483
ba8ab90e 484 if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)
577bbe01
RZ
485 return -EINVAL;
486
b905090d 487 mutex_lock(&hwmgr->smu_lock);
2a507105 488
577bbe01
RZ
489 state = hwmgr->current_ps;
490
491 switch (state->classification.ui_label) {
492 case PP_StateUILabel_Battery:
2a507105 493 pm_type = POWER_STATE_TYPE_BATTERY;
0f987cd0 494 break;
577bbe01 495 case PP_StateUILabel_Balanced:
2a507105 496 pm_type = POWER_STATE_TYPE_BALANCED;
0f987cd0 497 break;
577bbe01 498 case PP_StateUILabel_Performance:
2a507105 499 pm_type = POWER_STATE_TYPE_PERFORMANCE;
0f987cd0 500 break;
577bbe01 501 default:
f3898ea1 502 if (state->classification.flags & PP_StateClassificationFlag_Boot)
2a507105 503 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
f3898ea1 504 else
2a507105 505 pm_type = POWER_STATE_TYPE_DEFAULT;
0f987cd0 506 break;
577bbe01 507 }
b905090d 508 mutex_unlock(&hwmgr->smu_lock);
2a507105
RZ
509
510 return pm_type;
1f7371b2 511}
577bbe01 512
f93f0c3a 513static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
cac9a199 514{
b905090d 515 struct pp_hwmgr *hwmgr = handle;
cac9a199 516
ba8ab90e 517 if (!hwmgr || !hwmgr->pm_en)
f93f0c3a 518 return;
cac9a199 519
7383bcb9 520 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
0fb829de 521 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 522 return;
7383bcb9 523 }
b905090d 524 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 525 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
b905090d 526 mutex_unlock(&hwmgr->smu_lock);
cac9a199
RZ
527}
528
f93f0c3a 529static uint32_t pp_dpm_get_fan_control_mode(void *handle)
cac9a199 530{
b905090d 531 struct pp_hwmgr *hwmgr = handle;
f93f0c3a 532 uint32_t mode = 0;
cac9a199 533
ba8ab90e
RZ
534 if (!hwmgr || !hwmgr->pm_en)
535 return 0;
cac9a199 536
7383bcb9 537 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
0fb829de 538 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
539 return 0;
540 }
b905090d 541 mutex_lock(&hwmgr->smu_lock);
f93f0c3a 542 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
b905090d 543 mutex_unlock(&hwmgr->smu_lock);
f93f0c3a 544 return mode;
cac9a199
RZ
545}
546
547static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
548{
b905090d 549 struct pp_hwmgr *hwmgr = handle;
1c863802 550 int ret = 0;
cac9a199 551
ba8ab90e
RZ
552 if (!hwmgr || !hwmgr->pm_en)
553 return -EINVAL;
cac9a199 554
7383bcb9 555 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
0fb829de 556 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
557 return 0;
558 }
b905090d 559 mutex_lock(&hwmgr->smu_lock);
2a507105 560 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
b905090d 561 mutex_unlock(&hwmgr->smu_lock);
2a507105 562 return ret;
cac9a199
RZ
563}
564
565static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
566{
b905090d 567 struct pp_hwmgr *hwmgr = handle;
1c863802 568 int ret = 0;
cac9a199 569
ba8ab90e
RZ
570 if (!hwmgr || !hwmgr->pm_en)
571 return -EINVAL;
cac9a199 572
7383bcb9 573 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
0fb829de 574 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
575 return 0;
576 }
cac9a199 577
b905090d 578 mutex_lock(&hwmgr->smu_lock);
2a507105 579 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
b905090d 580 mutex_unlock(&hwmgr->smu_lock);
2a507105 581 return ret;
cac9a199
RZ
582}
583
72a16a9d
GI
584static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
585{
b905090d 586 struct pp_hwmgr *hwmgr = handle;
1c863802 587 int ret = 0;
72a16a9d 588
ba8ab90e
RZ
589 if (!hwmgr || !hwmgr->pm_en)
590 return -EINVAL;
72a16a9d 591
72a16a9d
GI
592 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
593 return -EINVAL;
594
b905090d 595 mutex_lock(&hwmgr->smu_lock);
2a507105 596 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
b905090d 597 mutex_unlock(&hwmgr->smu_lock);
2a507105 598 return ret;
72a16a9d
GI
599}
600
f3898ea1
EH
601static int pp_dpm_get_pp_num_states(void *handle,
602 struct pp_states_info *data)
603{
b905090d 604 struct pp_hwmgr *hwmgr = handle;
f3898ea1
EH
605 int i;
606
4dbda35f
EQ
607 memset(data, 0, sizeof(*data));
608
ba8ab90e 609 if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps)
f3898ea1
EH
610 return -EINVAL;
611
b905090d 612 mutex_lock(&hwmgr->smu_lock);
2a507105 613
f3898ea1
EH
614 data->nums = hwmgr->num_ps;
615
616 for (i = 0; i < hwmgr->num_ps; i++) {
617 struct pp_power_state *state = (struct pp_power_state *)
618 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
619 switch (state->classification.ui_label) {
620 case PP_StateUILabel_Battery:
621 data->states[i] = POWER_STATE_TYPE_BATTERY;
622 break;
623 case PP_StateUILabel_Balanced:
624 data->states[i] = POWER_STATE_TYPE_BALANCED;
625 break;
626 case PP_StateUILabel_Performance:
627 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
628 break;
629 default:
630 if (state->classification.flags & PP_StateClassificationFlag_Boot)
631 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
632 else
633 data->states[i] = POWER_STATE_TYPE_DEFAULT;
634 }
635 }
b905090d 636 mutex_unlock(&hwmgr->smu_lock);
f3898ea1
EH
637 return 0;
638}
639
640static int pp_dpm_get_pp_table(void *handle, char **table)
641{
b905090d 642 struct pp_hwmgr *hwmgr = handle;
2a507105 643 int size = 0;
f3898ea1 644
ba8ab90e 645 if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table)
4dcf9e6f
EH
646 return -EINVAL;
647
b905090d 648 mutex_lock(&hwmgr->smu_lock);
4dcf9e6f 649 *table = (char *)hwmgr->soft_pp_table;
2a507105 650 size = hwmgr->soft_pp_table_size;
b905090d 651 mutex_unlock(&hwmgr->smu_lock);
2a507105 652 return size;
f3898ea1
EH
653}
654
f685d714
RZ
655static int amd_powerplay_reset(void *handle)
656{
b905090d 657 struct pp_hwmgr *hwmgr = handle;
f685d714
RZ
658 int ret;
659
46b27ee9 660 ret = hwmgr_hw_fini(hwmgr);
f685d714
RZ
661 if (ret)
662 return ret;
663
b905090d 664 ret = hwmgr_hw_init(hwmgr);
f685d714
RZ
665 if (ret)
666 return ret;
667
b905090d 668 return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL);
f685d714
RZ
669}
670
f3898ea1
EH
671static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
672{
b905090d 673 struct pp_hwmgr *hwmgr = handle;
b61e54cb 674 int ret = -ENOMEM;
f3898ea1 675
ba8ab90e
RZ
676 if (!hwmgr || !hwmgr->pm_en)
677 return -EINVAL;
f3898ea1 678
b905090d 679 mutex_lock(&hwmgr->smu_lock);
4dcf9e6f 680 if (!hwmgr->hardcode_pp_table) {
efdf7a93
EC
681 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
682 hwmgr->soft_pp_table_size,
683 GFP_KERNEL);
b61e54cb
RZ
684 if (!hwmgr->hardcode_pp_table)
685 goto err;
7383bcb9 686 }
f3898ea1 687
4dcf9e6f
EH
688 memcpy(hwmgr->hardcode_pp_table, buf, size);
689
690 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
691
dd4bdf3b
EH
692 ret = amd_powerplay_reset(handle);
693 if (ret)
b61e54cb 694 goto err;
dd4bdf3b
EH
695
696 if (hwmgr->hwmgr_func->avfs_control) {
697 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
698 if (ret)
b61e54cb 699 goto err;
dd4bdf3b 700 }
b61e54cb 701 mutex_unlock(&hwmgr->smu_lock);
dd4bdf3b 702 return 0;
b61e54cb
RZ
703err:
704 mutex_unlock(&hwmgr->smu_lock);
705 return ret;
f3898ea1
EH
706}
707
708static int pp_dpm_force_clock_level(void *handle,
5632708f 709 enum pp_clock_type type, uint32_t mask)
f3898ea1 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->force_clock_level == NULL) {
0fb829de 718 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
719 return 0;
720 }
b905090d 721 mutex_lock(&hwmgr->smu_lock);
948fd66c
RZ
722 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
723 ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
724 else
725 ret = -EINVAL;
b905090d 726 mutex_unlock(&hwmgr->smu_lock);
2a507105 727 return ret;
f3898ea1
EH
728}
729
730static int pp_dpm_print_clock_levels(void *handle,
731 enum pp_clock_type type, char *buf)
732{
b905090d 733 struct pp_hwmgr *hwmgr = handle;
1c863802 734 int ret = 0;
f3898ea1 735
ba8ab90e
RZ
736 if (!hwmgr || !hwmgr->pm_en)
737 return -EINVAL;
f3898ea1 738
7383bcb9 739 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
0fb829de 740 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
741 return 0;
742 }
b905090d 743 mutex_lock(&hwmgr->smu_lock);
2a507105 744 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
b905090d 745 mutex_unlock(&hwmgr->smu_lock);
2a507105 746 return ret;
f3898ea1
EH
747}
748
428bafa8
EH
749static int pp_dpm_get_sclk_od(void *handle)
750{
b905090d 751 struct pp_hwmgr *hwmgr = handle;
1c863802 752 int ret = 0;
428bafa8 753
ba8ab90e
RZ
754 if (!hwmgr || !hwmgr->pm_en)
755 return -EINVAL;
428bafa8 756
428bafa8 757 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
0fb829de 758 pr_info("%s was not implemented.\n", __func__);
428bafa8
EH
759 return 0;
760 }
b905090d 761 mutex_lock(&hwmgr->smu_lock);
2a507105 762 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
b905090d 763 mutex_unlock(&hwmgr->smu_lock);
2a507105 764 return ret;
428bafa8
EH
765}
766
767static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
768{
b905090d 769 struct pp_hwmgr *hwmgr = handle;
1c863802 770 int ret = 0;
428bafa8 771
ba8ab90e
RZ
772 if (!hwmgr || !hwmgr->pm_en)
773 return -EINVAL;
428bafa8 774
428bafa8 775 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
0fb829de 776 pr_info("%s was not implemented.\n", __func__);
428bafa8
EH
777 return 0;
778 }
779
b905090d 780 mutex_lock(&hwmgr->smu_lock);
2a507105 781 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
b905090d 782 mutex_unlock(&hwmgr->smu_lock);
2a507105 783 return ret;
428bafa8
EH
784}
785
f2bdc05f
EH
786static int pp_dpm_get_mclk_od(void *handle)
787{
b905090d 788 struct pp_hwmgr *hwmgr = handle;
1c863802 789 int ret = 0;
f2bdc05f 790
ba8ab90e
RZ
791 if (!hwmgr || !hwmgr->pm_en)
792 return -EINVAL;
f2bdc05f 793
f2bdc05f 794 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
0fb829de 795 pr_info("%s was not implemented.\n", __func__);
f2bdc05f
EH
796 return 0;
797 }
b905090d 798 mutex_lock(&hwmgr->smu_lock);
2a507105 799 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
b905090d 800 mutex_unlock(&hwmgr->smu_lock);
2a507105 801 return ret;
f2bdc05f
EH
802}
803
804static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
805{
b905090d 806 struct pp_hwmgr *hwmgr = handle;
1c863802 807 int ret = 0;
f2bdc05f 808
ba8ab90e
RZ
809 if (!hwmgr || !hwmgr->pm_en)
810 return -EINVAL;
f2bdc05f 811
f2bdc05f 812 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
0fb829de 813 pr_info("%s was not implemented.\n", __func__);
f2bdc05f
EH
814 return 0;
815 }
b905090d 816 mutex_lock(&hwmgr->smu_lock);
2a507105 817 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
b905090d 818 mutex_unlock(&hwmgr->smu_lock);
2a507105 819 return ret;
f2bdc05f
EH
820}
821
9f8df7d7
TSD
822static int pp_dpm_read_sensor(void *handle, int idx,
823 void *value, int *size)
a6e36952 824{
b905090d 825 struct pp_hwmgr *hwmgr = handle;
1c863802 826 int ret = 0;
a6e36952 827
ba8ab90e 828 if (!hwmgr || !hwmgr->pm_en || !value)
5ed8d656
RZ
829 return -EINVAL;
830
5ed8d656
RZ
831 switch (idx) {
832 case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
833 *((uint32_t *)value) = hwmgr->pstate_sclk;
834 return 0;
835 case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
836 *((uint32_t *)value) = hwmgr->pstate_mclk;
a6e36952 837 return 0;
5ed8d656 838 default:
b905090d 839 mutex_lock(&hwmgr->smu_lock);
5ed8d656 840 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
b905090d 841 mutex_unlock(&hwmgr->smu_lock);
5ed8d656 842 return ret;
a6e36952 843 }
a6e36952
TSD
844}
845
597be302
AD
846static struct amd_vce_state*
847pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
848{
b905090d 849 struct pp_hwmgr *hwmgr = handle;
597be302 850
ba8ab90e 851 if (!hwmgr || !hwmgr->pm_en)
1c863802
RZ
852 return NULL;
853
ba8ab90e 854 if (idx < hwmgr->num_vce_state_tables)
1c863802 855 return &hwmgr->vce_states[idx];
597be302
AD
856 return NULL;
857}
858
6390258a
RZ
859static int pp_get_power_profile_mode(void *handle, char *buf)
860{
b905090d 861 struct pp_hwmgr *hwmgr = handle;
6390258a 862
ba8ab90e 863 if (!hwmgr || !hwmgr->pm_en || !buf)
6390258a
RZ
864 return -EINVAL;
865
6390258a
RZ
866 if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) {
867 pr_info("%s was not implemented.\n", __func__);
868 return snprintf(buf, PAGE_SIZE, "\n");
869 }
870
871 return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
872}
873
874static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
875{
b905090d 876 struct pp_hwmgr *hwmgr = handle;
337ecd6a 877 int ret = -EINVAL;
6390258a 878
ba8ab90e
RZ
879 if (!hwmgr || !hwmgr->pm_en)
880 return ret;
6390258a 881
6390258a
RZ
882 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
883 pr_info("%s was not implemented.\n", __func__);
ba8ab90e 884 return ret;
6390258a 885 }
b905090d 886 mutex_lock(&hwmgr->smu_lock);
337ecd6a
RZ
887 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
888 ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
b905090d 889 mutex_unlock(&hwmgr->smu_lock);
337ecd6a 890 return ret;
6390258a
RZ
891}
892
e3933f26
RZ
893static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
894{
b905090d 895 struct pp_hwmgr *hwmgr = handle;
e3933f26 896
ba8ab90e 897 if (!hwmgr || !hwmgr->pm_en)
e3933f26
RZ
898 return -EINVAL;
899
e3933f26
RZ
900 if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {
901 pr_info("%s was not implemented.\n", __func__);
902 return -EINVAL;
903 }
904
905 return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
906}
907
34bb2734 908static int pp_dpm_switch_power_profile(void *handle,
052fe96d 909 enum PP_SMC_POWER_PROFILE type, bool en)
34bb2734 910{
b905090d 911 struct pp_hwmgr *hwmgr = handle;
052fe96d
RZ
912 long workload;
913 uint32_t index;
34bb2734 914
ba8ab90e 915 if (!hwmgr || !hwmgr->pm_en)
34bb2734
EH
916 return -EINVAL;
917
052fe96d
RZ
918 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
919 pr_info("%s was not implemented.\n", __func__);
920 return -EINVAL;
921 }
922
923 if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
924 return -EINVAL;
925
b905090d 926 mutex_lock(&hwmgr->smu_lock);
052fe96d
RZ
927
928 if (!en) {
929 hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
930 index = fls(hwmgr->workload_mask);
931 index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
932 workload = hwmgr->workload_setting[index];
933 } else {
934 hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
935 index = fls(hwmgr->workload_mask);
936 index = index <= Workload_Policy_Max ? index - 1 : 0;
937 workload = hwmgr->workload_setting[index];
34bb2734
EH
938 }
939
052fe96d
RZ
940 if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
941 hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
b905090d 942 mutex_unlock(&hwmgr->smu_lock);
052fe96d 943
34bb2734
EH
944 return 0;
945}
946
6ab8555e
RZ
947static int pp_set_power_limit(void *handle, uint32_t limit)
948{
b905090d 949 struct pp_hwmgr *hwmgr = handle;
6ab8555e 950
ba8ab90e
RZ
951 if (!hwmgr || !hwmgr->pm_en)
952 return -EINVAL;
6ab8555e 953
6ab8555e
RZ
954 if (hwmgr->hwmgr_func->set_power_limit == NULL) {
955 pr_info("%s was not implemented.\n", __func__);
956 return -EINVAL;
957 }
958
959 if (limit == 0)
960 limit = hwmgr->default_power_limit;
961
962 if (limit > hwmgr->default_power_limit)
963 return -EINVAL;
964
b905090d 965 mutex_lock(&hwmgr->smu_lock);
6ab8555e
RZ
966 hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
967 hwmgr->power_limit = limit;
b905090d 968 mutex_unlock(&hwmgr->smu_lock);
ba8ab90e 969 return 0;
6ab8555e
RZ
970}
971
972static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
973{
b905090d 974 struct pp_hwmgr *hwmgr = handle;
6ab8555e 975
ba8ab90e 976 if (!hwmgr || !hwmgr->pm_en ||!limit)
6ab8555e
RZ
977 return -EINVAL;
978
b905090d 979 mutex_lock(&hwmgr->smu_lock);
6ab8555e
RZ
980
981 if (default_limit)
982 *limit = hwmgr->default_power_limit;
983 else
984 *limit = hwmgr->power_limit;
985
b905090d 986 mutex_unlock(&hwmgr->smu_lock);
6ab8555e 987
ba8ab90e 988 return 0;
6ab8555e
RZ
989}
990
f685d714 991static int pp_display_configuration_change(void *handle,
155f1127 992 const struct amd_pp_display_configuration *display_config)
7fb72a1f 993{
b905090d 994 struct pp_hwmgr *hwmgr = handle;
7fb72a1f 995
ba8ab90e
RZ
996 if (!hwmgr || !hwmgr->pm_en)
997 return -EINVAL;
7fb72a1f 998
b905090d 999 mutex_lock(&hwmgr->smu_lock);
7fb72a1f 1000 phm_store_dal_configuration_data(hwmgr, display_config);
b905090d 1001 mutex_unlock(&hwmgr->smu_lock);
7fb72a1f
RZ
1002 return 0;
1003}
c4dd206b 1004
f685d714 1005static int pp_get_display_power_level(void *handle,
47329134 1006 struct amd_pp_simple_clock_info *output)
c4dd206b 1007{
b905090d 1008 struct pp_hwmgr *hwmgr = handle;
1c863802 1009 int ret = 0;
c4dd206b 1010
ba8ab90e 1011 if (!hwmgr || !hwmgr->pm_en ||!output)
1c863802 1012 return -EINVAL;
ba5f884c 1013
b905090d 1014 mutex_lock(&hwmgr->smu_lock);
2a507105 1015 ret = phm_get_dal_power_level(hwmgr, output);
b905090d 1016 mutex_unlock(&hwmgr->smu_lock);
2a507105 1017 return ret;
c4dd206b 1018}
e273b041 1019
f685d714 1020static int pp_get_current_clocks(void *handle,
155f1127 1021 struct amd_pp_clock_info *clocks)
e273b041 1022{
e273b041
RZ
1023 struct amd_pp_simple_clock_info simple_clocks;
1024 struct pp_clock_info hw_clocks;
b905090d 1025 struct pp_hwmgr *hwmgr = handle;
1c863802 1026 int ret = 0;
e273b041 1027
ba8ab90e
RZ
1028 if (!hwmgr || !hwmgr->pm_en)
1029 return -EINVAL;
e273b041 1030
b905090d 1031 mutex_lock(&hwmgr->smu_lock);
2a507105 1032
e273b041
RZ
1033 phm_get_dal_power_level(hwmgr, &simple_clocks);
1034
2a507105
RZ
1035 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1036 PHM_PlatformCaps_PowerContainment))
1037 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1038 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1039 else
1040 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1041 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1042
ae97988f 1043 if (ret) {
2a507105 1044 pr_info("Error in phm_get_clock_info \n");
b905090d 1045 mutex_unlock(&hwmgr->smu_lock);
2a507105 1046 return -EINVAL;
e273b041
RZ
1047 }
1048
1049 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1050 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1051 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1052 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1053 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1054 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1055
1056 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1057 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1058
1059 clocks->max_clocks_state = simple_clocks.level;
1060
1061 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1062 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1063 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1064 }
b905090d 1065 mutex_unlock(&hwmgr->smu_lock);
e273b041 1066 return 0;
e273b041
RZ
1067}
1068
f685d714 1069static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
e273b041 1070{
b905090d 1071 struct pp_hwmgr *hwmgr = handle;
1c863802 1072 int ret = 0;
e273b041 1073
ba8ab90e
RZ
1074 if (!hwmgr || !hwmgr->pm_en)
1075 return -EINVAL;
1c863802 1076
fa9e6991 1077 if (clocks == NULL)
e273b041
RZ
1078 return -EINVAL;
1079
b905090d 1080 mutex_lock(&hwmgr->smu_lock);
2a507105 1081 ret = phm_get_clock_by_type(hwmgr, type, clocks);
b905090d 1082 mutex_unlock(&hwmgr->smu_lock);
2a507105 1083 return ret;
e273b041
RZ
1084}
1085
f685d714 1086static int pp_get_clock_by_type_with_latency(void *handle,
d0187727
EH
1087 enum amd_pp_clock_type type,
1088 struct pp_clock_levels_with_latency *clocks)
1089{
b905090d 1090 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1091 int ret = 0;
1092
ba8ab90e 1093 if (!hwmgr || !hwmgr->pm_en ||!clocks)
d0187727
EH
1094 return -EINVAL;
1095
b905090d 1096 mutex_lock(&hwmgr->smu_lock);
d0187727 1097 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
b905090d 1098 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1099 return ret;
1100}
1101
f685d714 1102static int pp_get_clock_by_type_with_voltage(void *handle,
d0187727
EH
1103 enum amd_pp_clock_type type,
1104 struct pp_clock_levels_with_voltage *clocks)
1105{
b905090d 1106 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1107 int ret = 0;
1108
ba8ab90e 1109 if (!hwmgr || !hwmgr->pm_en ||!clocks)
d0187727
EH
1110 return -EINVAL;
1111
b905090d 1112 mutex_lock(&hwmgr->smu_lock);
d0187727
EH
1113
1114 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1115
b905090d 1116 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1117 return ret;
1118}
1119
f685d714 1120static int pp_set_watermarks_for_clocks_ranges(void *handle,
d0187727
EH
1121 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1122{
b905090d 1123 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1124 int ret = 0;
1125
ba8ab90e 1126 if (!hwmgr || !hwmgr->pm_en ||!wm_with_clock_ranges)
d0187727
EH
1127 return -EINVAL;
1128
b905090d 1129 mutex_lock(&hwmgr->smu_lock);
d0187727
EH
1130 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1131 wm_with_clock_ranges);
b905090d 1132 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1133
1134 return ret;
1135}
1136
f685d714 1137static int pp_display_clock_voltage_request(void *handle,
d0187727
EH
1138 struct pp_display_clock_request *clock)
1139{
b905090d 1140 struct pp_hwmgr *hwmgr = handle;
d0187727
EH
1141 int ret = 0;
1142
ba8ab90e 1143 if (!hwmgr || !hwmgr->pm_en ||!clock)
d0187727
EH
1144 return -EINVAL;
1145
b905090d 1146 mutex_lock(&hwmgr->smu_lock);
d0187727 1147 ret = phm_display_clock_voltage_request(hwmgr, clock);
b905090d 1148 mutex_unlock(&hwmgr->smu_lock);
d0187727
EH
1149
1150 return ret;
1151}
1152
f685d714 1153static int pp_get_display_mode_validation_clocks(void *handle,
155f1127 1154 struct amd_pp_simple_clock_info *clocks)
e273b041 1155{
b905090d 1156 struct pp_hwmgr *hwmgr = handle;
1c863802 1157 int ret = 0;
e273b041 1158
ba8ab90e 1159 if (!hwmgr || !hwmgr->pm_en ||!clocks)
1c863802 1160 return -EINVAL;
ba5f884c 1161
b905090d 1162 mutex_lock(&hwmgr->smu_lock);
2a507105 1163
e273b041 1164 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1c863802 1165 ret = phm_get_max_high_clocks(hwmgr, clocks);
e273b041 1166
b905090d 1167 mutex_unlock(&hwmgr->smu_lock);
1c863802 1168 return ret;
e273b041
RZ
1169}
1170
72d76191
EH
1171static int pp_set_mmhub_powergating_by_smu(void *handle)
1172{
b905090d 1173 struct pp_hwmgr *hwmgr = handle;
72d76191 1174
ba8ab90e
RZ
1175 if (!hwmgr || !hwmgr->pm_en)
1176 return -EINVAL;
72d76191 1177
72d76191
EH
1178 if (hwmgr->hwmgr_func->set_mmhub_powergating_by_smu == NULL) {
1179 pr_info("%s was not implemented.\n", __func__);
1180 return 0;
1181 }
1182
1183 return hwmgr->hwmgr_func->set_mmhub_powergating_by_smu(hwmgr);
1184}
1185
b905090d 1186static const struct amd_pm_funcs pp_dpm_funcs = {
f685d714
RZ
1187 .load_firmware = pp_dpm_load_fw,
1188 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1189 .force_performance_level = pp_dpm_force_performance_level,
1190 .get_performance_level = pp_dpm_get_performance_level,
1191 .get_current_power_state = pp_dpm_get_current_power_state,
1192 .powergate_vce = pp_dpm_powergate_vce,
1193 .powergate_uvd = pp_dpm_powergate_uvd,
1194 .dispatch_tasks = pp_dpm_dispatch_tasks,
1195 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1196 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1197 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1198 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
1199 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1200 .get_pp_num_states = pp_dpm_get_pp_num_states,
1201 .get_pp_table = pp_dpm_get_pp_table,
1202 .set_pp_table = pp_dpm_set_pp_table,
1203 .force_clock_level = pp_dpm_force_clock_level,
1204 .print_clock_levels = pp_dpm_print_clock_levels,
1205 .get_sclk_od = pp_dpm_get_sclk_od,
1206 .set_sclk_od = pp_dpm_set_sclk_od,
1207 .get_mclk_od = pp_dpm_get_mclk_od,
1208 .set_mclk_od = pp_dpm_set_mclk_od,
1209 .read_sensor = pp_dpm_read_sensor,
1210 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
f685d714
RZ
1211 .switch_power_profile = pp_dpm_switch_power_profile,
1212 .set_clockgating_by_smu = pp_set_clockgating_by_smu,
6390258a
RZ
1213 .get_power_profile_mode = pp_get_power_profile_mode,
1214 .set_power_profile_mode = pp_set_power_profile_mode,
e3933f26 1215 .odn_edit_dpm_table = pp_odn_edit_dpm_table,
6ab8555e
RZ
1216 .set_power_limit = pp_set_power_limit,
1217 .get_power_limit = pp_get_power_limit,
f685d714
RZ
1218/* export to DC */
1219 .get_sclk = pp_dpm_get_sclk,
1220 .get_mclk = pp_dpm_get_mclk,
1221 .display_configuration_change = pp_display_configuration_change,
1222 .get_display_power_level = pp_get_display_power_level,
1223 .get_current_clocks = pp_get_current_clocks,
1224 .get_clock_by_type = pp_get_clock_by_type,
1225 .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
1226 .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
1227 .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
1228 .display_clock_voltage_request = pp_display_clock_voltage_request,
1229 .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
72d76191 1230 .set_mmhub_powergating_by_smu = pp_set_mmhub_powergating_by_smu,
f685d714 1231};