drm/amd/pp: Enable pp_set_power_profile_mode under manual mode
[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>
1f7371b2
AD
28#include "amd_shared.h"
29#include "amd_powerplay.h"
ac885b3a 30#include "pp_instance.h"
577bbe01 31#include "power_state.h"
1f7371b2 32
e5f23736
RZ
33#define PP_DPM_DISABLED 0xCCCC
34
6d07fe7b 35static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
39199b80 36 enum amd_pm_state_type *user_state);
6d07fe7b 37
1c863802 38static inline int pp_check(struct pp_instance *handle)
1f7371b2 39{
e1827a30 40 if (handle == NULL)
1c863802 41 return -EINVAL;
3bace359 42
b3b03052 43 if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL)
3bace359
JZ
44 return -EINVAL;
45
1c863802
RZ
46 if (handle->pm_en == 0)
47 return PP_DPM_DISABLED;
3bace359 48
b3b03052 49 if (handle->hwmgr->hwmgr_func == NULL)
1c863802 50 return PP_DPM_DISABLED;
7383bcb9 51
1c863802
RZ
52 return 0;
53}
3bace359 54
139a285f
RZ
55static int amd_powerplay_create(struct amd_pp_init *pp_init,
56 void **handle)
57{
58 struct pp_instance *instance;
59
60 if (pp_init == NULL || handle == NULL)
61 return -EINVAL;
62
63 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
64 if (instance == NULL)
65 return -ENOMEM;
66
139a285f
RZ
67 instance->chip_family = pp_init->chip_family;
68 instance->chip_id = pp_init->chip_id;
69 instance->pm_en = pp_init->pm_en;
70 instance->feature_mask = pp_init->feature_mask;
71 instance->device = pp_init->device;
72 mutex_init(&instance->pp_lock);
73 *handle = instance;
74 return 0;
75}
76
77static int amd_powerplay_destroy(void *handle)
78{
79 struct pp_instance *instance = (struct pp_instance *)handle;
80
7b38a49d
EH
81 kfree(instance->hwmgr->hardcode_pp_table);
82 instance->hwmgr->hardcode_pp_table = NULL;
83
139a285f
RZ
84 kfree(instance->hwmgr);
85 instance->hwmgr = NULL;
86
87 kfree(instance);
88 instance = NULL;
89 return 0;
90}
91
1c863802
RZ
92static int pp_early_init(void *handle)
93{
94 int ret;
139a285f
RZ
95 struct pp_instance *pp_handle = NULL;
96
97 pp_handle = cgs_register_pp_handle(handle, amd_powerplay_create);
98
99 if (!pp_handle)
100 return -EINVAL;
e92a0370 101
b3b03052 102 ret = hwmgr_early_init(pp_handle);
9441f964 103 if (ret)
b3b03052 104 return -EINVAL;
1c863802 105
b4eeed59 106 return 0;
1f7371b2
AD
107}
108
1c863802 109static int pp_sw_init(void *handle)
1f7371b2 110{
b3b03052 111 struct pp_hwmgr *hwmgr;
3bace359 112 int ret = 0;
1c863802 113 struct pp_instance *pp_handle = (struct pp_instance *)handle;
3bace359 114
1c863802 115 ret = pp_check(pp_handle);
3bace359 116
e5f23736 117 if (ret >= 0) {
b3b03052 118 hwmgr = pp_handle->hwmgr;
3bace359 119
b3b03052 120 if (hwmgr->smumgr_funcs->smu_init == NULL)
1c863802 121 return -EINVAL;
7383bcb9 122
b3b03052 123 ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
167112bf 124
9953b72f 125 pr_debug("amdgpu: powerplay sw initialized\n");
1c863802
RZ
126 }
127 return ret;
128}
3bace359 129
1c863802
RZ
130static int pp_sw_fini(void *handle)
131{
b3b03052 132 struct pp_hwmgr *hwmgr;
1c863802
RZ
133 int ret = 0;
134 struct pp_instance *pp_handle = (struct pp_instance *)handle;
135
136 ret = pp_check(pp_handle);
e5f23736 137 if (ret >= 0) {
b3b03052 138 hwmgr = pp_handle->hwmgr;
9d8f086c 139
b3b03052 140 if (hwmgr->smumgr_funcs->smu_fini == NULL)
1c863802
RZ
141 return -EINVAL;
142
b3b03052 143 ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
1c863802 144 }
3bace359 145 return ret;
1f7371b2
AD
146}
147
148static int pp_hw_init(void *handle)
149{
ac885b3a 150 int ret = 0;
1c863802 151 struct pp_instance *pp_handle = (struct pp_instance *)handle;
b3b03052 152 struct pp_hwmgr *hwmgr;
ac885b3a 153
1c863802 154 ret = pp_check(pp_handle);
ac885b3a 155
e5f23736 156 if (ret >= 0) {
b3b03052 157 hwmgr = pp_handle->hwmgr;
ac885b3a 158
b3b03052 159 if (hwmgr->smumgr_funcs->start_smu == NULL)
1c863802 160 return -EINVAL;
ac885b3a 161
b3b03052 162 if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
1c863802 163 pr_err("smc start failed\n");
b3b03052 164 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
122fe39d 165 return -EINVAL;
1c863802
RZ
166 }
167 if (ret == PP_DPM_DISABLED)
e5f23736
RZ
168 goto exit;
169 ret = hwmgr_hw_init(pp_handle);
170 if (ret)
171 goto exit;
ac885b3a 172 }
e5f23736
RZ
173 return ret;
174exit:
1c863802 175 pp_handle->pm_en = 0;
e5f23736
RZ
176 cgs_notify_dpm_enabled(hwmgr->device, false);
177 return 0;
178
1f7371b2
AD
179}
180
181static int pp_hw_fini(void *handle)
182{
1c863802
RZ
183 struct pp_instance *pp_handle = (struct pp_instance *)handle;
184 int ret = 0;
ac885b3a 185
1c863802 186 ret = pp_check(pp_handle);
df1e6394 187 if (ret == 0)
1c863802 188 hwmgr_hw_fini(pp_handle);
df1e6394 189
1f7371b2
AD
190 return 0;
191}
192
6d07fe7b
RZ
193static int pp_late_init(void *handle)
194{
195 struct pp_instance *pp_handle = (struct pp_instance *)handle;
196 int ret = 0;
197
198 ret = pp_check(pp_handle);
199 if (ret == 0)
200 pp_dpm_dispatch_tasks(pp_handle,
39199b80 201 AMD_PP_TASK_COMPLETE_INIT, NULL);
6d07fe7b
RZ
202
203 return 0;
204}
205
139a285f
RZ
206static void pp_late_fini(void *handle)
207{
208 amd_powerplay_destroy(handle);
209}
210
211
1f7371b2
AD
212static bool pp_is_idle(void *handle)
213{
ed5121a3 214 return false;
1f7371b2
AD
215}
216
217static int pp_wait_for_idle(void *handle)
218{
219 return 0;
220}
221
222static int pp_sw_reset(void *handle)
223{
224 return 0;
225}
226
1f7371b2
AD
227static int pp_set_powergating_state(void *handle,
228 enum amd_powergating_state state)
229{
65f85e7d 230 struct pp_hwmgr *hwmgr;
1c863802
RZ
231 struct pp_instance *pp_handle = (struct pp_instance *)handle;
232 int ret = 0;
65f85e7d 233
1c863802 234 ret = pp_check(pp_handle);
65f85e7d 235
ae97988f 236 if (ret)
1c863802 237 return ret;
65f85e7d 238
1c863802 239 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
240
241 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
0fb829de 242 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
243 return 0;
244 }
65f85e7d
EH
245
246 /* Enable/disable GFX per cu powergating through SMU */
247 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
93a4aec2 248 state == AMD_PG_STATE_GATE);
1f7371b2
AD
249}
250
251static int pp_suspend(void *handle)
252{
1c863802
RZ
253 struct pp_instance *pp_handle = (struct pp_instance *)handle;
254 int ret = 0;
577bbe01 255
1c863802 256 ret = pp_check(pp_handle);
e5f23736
RZ
257 if (ret == 0)
258 hwmgr_hw_suspend(pp_handle);
259 return 0;
1f7371b2
AD
260}
261
262static int pp_resume(void *handle)
263{
b3b03052 264 struct pp_hwmgr *hwmgr;
e5f23736 265 int ret;
1c863802 266 struct pp_instance *pp_handle = (struct pp_instance *)handle;
577bbe01 267
e5f23736 268 ret = pp_check(pp_handle);
1c863802 269
e5f23736
RZ
270 if (ret < 0)
271 return ret;
577bbe01 272
b3b03052 273 hwmgr = pp_handle->hwmgr;
e0b71a7e 274
b3b03052 275 if (hwmgr->smumgr_funcs->start_smu == NULL)
e0b71a7e
RZ
276 return -EINVAL;
277
e5f23736 278 if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
0fb829de 279 pr_err("smc start failed\n");
b3b03052 280 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
e5f23736 281 return -EINVAL;
e0b71a7e
RZ
282 }
283
e5f23736 284 if (ret == PP_DPM_DISABLED)
8fdf2692 285 return 0;
1c863802 286
df1e6394 287 return hwmgr_hw_resume(pp_handle);
1f7371b2
AD
288}
289
290const struct amd_ip_funcs pp_ip_funcs = {
88a907d6 291 .name = "powerplay",
1f7371b2 292 .early_init = pp_early_init,
6d07fe7b 293 .late_init = pp_late_init,
1f7371b2
AD
294 .sw_init = pp_sw_init,
295 .sw_fini = pp_sw_fini,
296 .hw_init = pp_hw_init,
297 .hw_fini = pp_hw_fini,
139a285f 298 .late_fini = pp_late_fini,
1f7371b2
AD
299 .suspend = pp_suspend,
300 .resume = pp_resume,
301 .is_idle = pp_is_idle,
302 .wait_for_idle = pp_wait_for_idle,
303 .soft_reset = pp_sw_reset,
465f96e2 304 .set_clockgating_state = NULL,
1f7371b2
AD
305 .set_powergating_state = pp_set_powergating_state,
306};
307
308static int pp_dpm_load_fw(void *handle)
309{
310 return 0;
311}
312
313static int pp_dpm_fw_loading_complete(void *handle)
314{
315 return 0;
316}
317
3811f8f0
RZ
318static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
319{
320 struct pp_hwmgr *hwmgr;
321 struct pp_instance *pp_handle = (struct pp_instance *)handle;
322 int ret = 0;
323
324 ret = pp_check(pp_handle);
325
326 if (ret)
327 return ret;
328
329 hwmgr = pp_handle->hwmgr;
330
331 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
332 pr_info("%s was not implemented.\n", __func__);
333 return 0;
334 }
335
336 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
337}
338
9947f704
RZ
339static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
340 enum amd_dpm_forced_level *level)
341{
342 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
343 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
344 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
345 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
346
347 if (!(hwmgr->dpm_level & profile_mode_mask)) {
348 /* enter umd pstate, save current level, disable gfx cg*/
349 if (*level & profile_mode_mask) {
350 hwmgr->saved_dpm_level = hwmgr->dpm_level;
351 hwmgr->en_umd_pstate = true;
352 cgs_set_clockgating_state(hwmgr->device,
353 AMD_IP_BLOCK_TYPE_GFX,
354 AMD_CG_STATE_UNGATE);
355 cgs_set_powergating_state(hwmgr->device,
356 AMD_IP_BLOCK_TYPE_GFX,
357 AMD_PG_STATE_UNGATE);
358 }
359 } else {
360 /* exit umd pstate, restore level, enable gfx cg*/
361 if (!(*level & profile_mode_mask)) {
362 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
363 *level = hwmgr->saved_dpm_level;
364 hwmgr->en_umd_pstate = false;
365 cgs_set_clockgating_state(hwmgr->device,
366 AMD_IP_BLOCK_TYPE_GFX,
367 AMD_CG_STATE_GATE);
368 cgs_set_powergating_state(hwmgr->device,
369 AMD_IP_BLOCK_TYPE_GFX,
370 AMD_PG_STATE_GATE);
371 }
372 }
373}
374
1f7371b2
AD
375static int pp_dpm_force_performance_level(void *handle,
376 enum amd_dpm_forced_level level)
377{
577bbe01 378 struct pp_hwmgr *hwmgr;
1c863802
RZ
379 struct pp_instance *pp_handle = (struct pp_instance *)handle;
380 int ret = 0;
577bbe01 381
1c863802 382 ret = pp_check(pp_handle);
577bbe01 383
ae97988f 384 if (ret)
1c863802 385 return ret;
577bbe01
RZ
386
387 hwmgr = pp_handle->hwmgr;
388
9947f704
RZ
389 if (level == hwmgr->dpm_level)
390 return 0;
391
2a507105 392 mutex_lock(&pp_handle->pp_lock);
9947f704
RZ
393 pp_dpm_en_umd_pstate(hwmgr, &level);
394 hwmgr->request_dpm_level = level;
39199b80 395 hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
2a507105 396 mutex_unlock(&pp_handle->pp_lock);
8621bbbb 397
1f7371b2
AD
398 return 0;
399}
577bbe01 400
1f7371b2
AD
401static enum amd_dpm_forced_level pp_dpm_get_performance_level(
402 void *handle)
403{
577bbe01 404 struct pp_hwmgr *hwmgr;
1c863802
RZ
405 struct pp_instance *pp_handle = (struct pp_instance *)handle;
406 int ret = 0;
2a507105 407 enum amd_dpm_forced_level level;
577bbe01 408
1c863802 409 ret = pp_check(pp_handle);
577bbe01 410
ae97988f 411 if (ret)
1c863802 412 return ret;
577bbe01 413
1c863802 414 hwmgr = pp_handle->hwmgr;
2a507105
RZ
415 mutex_lock(&pp_handle->pp_lock);
416 level = hwmgr->dpm_level;
417 mutex_unlock(&pp_handle->pp_lock);
418 return level;
1f7371b2 419}
577bbe01 420
f93f0c3a 421static uint32_t pp_dpm_get_sclk(void *handle, bool low)
1f7371b2 422{
577bbe01 423 struct pp_hwmgr *hwmgr;
1c863802
RZ
424 struct pp_instance *pp_handle = (struct pp_instance *)handle;
425 int ret = 0;
f93f0c3a 426 uint32_t clk = 0;
577bbe01 427
1c863802 428 ret = pp_check(pp_handle);
577bbe01 429
ae97988f 430 if (ret)
1c863802 431 return ret;
577bbe01 432
1c863802 433 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
434
435 if (hwmgr->hwmgr_func->get_sclk == NULL) {
0fb829de 436 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
437 return 0;
438 }
2a507105 439 mutex_lock(&pp_handle->pp_lock);
f93f0c3a 440 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
2a507105 441 mutex_unlock(&pp_handle->pp_lock);
f93f0c3a 442 return clk;
1f7371b2 443}
577bbe01 444
f93f0c3a 445static uint32_t pp_dpm_get_mclk(void *handle, bool low)
1f7371b2 446{
577bbe01 447 struct pp_hwmgr *hwmgr;
1c863802
RZ
448 struct pp_instance *pp_handle = (struct pp_instance *)handle;
449 int ret = 0;
f93f0c3a 450 uint32_t clk = 0;
577bbe01 451
1c863802 452 ret = pp_check(pp_handle);
577bbe01 453
ae97988f 454 if (ret)
1c863802 455 return ret;
577bbe01 456
1c863802 457 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
458
459 if (hwmgr->hwmgr_func->get_mclk == NULL) {
0fb829de 460 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
461 return 0;
462 }
2a507105 463 mutex_lock(&pp_handle->pp_lock);
f93f0c3a 464 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
2a507105 465 mutex_unlock(&pp_handle->pp_lock);
f93f0c3a 466 return clk;
1f7371b2 467}
577bbe01 468
f93f0c3a 469static void pp_dpm_powergate_vce(void *handle, bool gate)
1f7371b2 470{
577bbe01 471 struct pp_hwmgr *hwmgr;
1c863802
RZ
472 struct pp_instance *pp_handle = (struct pp_instance *)handle;
473 int ret = 0;
577bbe01 474
1c863802 475 ret = pp_check(pp_handle);
577bbe01 476
ae97988f 477 if (ret)
f93f0c3a 478 return;
577bbe01 479
1c863802 480 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
481
482 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
0fb829de 483 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 484 return;
7383bcb9 485 }
2a507105 486 mutex_lock(&pp_handle->pp_lock);
f93f0c3a 487 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
2a507105 488 mutex_unlock(&pp_handle->pp_lock);
1f7371b2 489}
577bbe01 490
f93f0c3a 491static void pp_dpm_powergate_uvd(void *handle, bool gate)
1f7371b2 492{
577bbe01 493 struct pp_hwmgr *hwmgr;
1c863802
RZ
494 struct pp_instance *pp_handle = (struct pp_instance *)handle;
495 int ret = 0;
577bbe01 496
1c863802 497 ret = pp_check(pp_handle);
577bbe01 498
ae97988f 499 if (ret)
f93f0c3a 500 return;
577bbe01 501
1c863802 502 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
503
504 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
0fb829de 505 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 506 return;
7383bcb9 507 }
2a507105 508 mutex_lock(&pp_handle->pp_lock);
f93f0c3a 509 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
2a507105 510 mutex_unlock(&pp_handle->pp_lock);
577bbe01
RZ
511}
512
df1e6394 513static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
39199b80 514 enum amd_pm_state_type *user_state)
1f7371b2 515{
577bbe01 516 int ret = 0;
1c863802 517 struct pp_instance *pp_handle = (struct pp_instance *)handle;
577bbe01 518
1c863802 519 ret = pp_check(pp_handle);
577bbe01 520
ae97988f 521 if (ret)
1c863802 522 return ret;
577bbe01 523
df1e6394 524 mutex_lock(&pp_handle->pp_lock);
39199b80 525 ret = hwmgr_handle_task(pp_handle, task_id, user_state);
2a507105 526 mutex_unlock(&pp_handle->pp_lock);
df1e6394 527
577bbe01 528 return ret;
1f7371b2 529}
577bbe01 530
f8a4c11b 531static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
1f7371b2 532{
577bbe01
RZ
533 struct pp_hwmgr *hwmgr;
534 struct pp_power_state *state;
1c863802
RZ
535 struct pp_instance *pp_handle = (struct pp_instance *)handle;
536 int ret = 0;
2a507105 537 enum amd_pm_state_type pm_type;
577bbe01 538
1c863802 539 ret = pp_check(pp_handle);
577bbe01 540
ae97988f 541 if (ret)
1c863802 542 return ret;
577bbe01 543
1c863802
RZ
544 hwmgr = pp_handle->hwmgr;
545
546 if (hwmgr->current_ps == NULL)
577bbe01
RZ
547 return -EINVAL;
548
2a507105
RZ
549 mutex_lock(&pp_handle->pp_lock);
550
577bbe01
RZ
551 state = hwmgr->current_ps;
552
553 switch (state->classification.ui_label) {
554 case PP_StateUILabel_Battery:
2a507105 555 pm_type = POWER_STATE_TYPE_BATTERY;
0f987cd0 556 break;
577bbe01 557 case PP_StateUILabel_Balanced:
2a507105 558 pm_type = POWER_STATE_TYPE_BALANCED;
0f987cd0 559 break;
577bbe01 560 case PP_StateUILabel_Performance:
2a507105 561 pm_type = POWER_STATE_TYPE_PERFORMANCE;
0f987cd0 562 break;
577bbe01 563 default:
f3898ea1 564 if (state->classification.flags & PP_StateClassificationFlag_Boot)
2a507105 565 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
f3898ea1 566 else
2a507105 567 pm_type = POWER_STATE_TYPE_DEFAULT;
0f987cd0 568 break;
577bbe01 569 }
2a507105
RZ
570 mutex_unlock(&pp_handle->pp_lock);
571
572 return pm_type;
1f7371b2 573}
577bbe01 574
f93f0c3a 575static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
cac9a199
RZ
576{
577 struct pp_hwmgr *hwmgr;
1c863802
RZ
578 struct pp_instance *pp_handle = (struct pp_instance *)handle;
579 int ret = 0;
cac9a199 580
1c863802 581 ret = pp_check(pp_handle);
cac9a199 582
ae97988f 583 if (ret)
f93f0c3a 584 return;
cac9a199 585
1c863802 586 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
587
588 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
0fb829de 589 pr_info("%s was not implemented.\n", __func__);
f93f0c3a 590 return;
7383bcb9 591 }
2a507105 592 mutex_lock(&pp_handle->pp_lock);
f93f0c3a 593 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
2a507105 594 mutex_unlock(&pp_handle->pp_lock);
cac9a199
RZ
595}
596
f93f0c3a 597static uint32_t pp_dpm_get_fan_control_mode(void *handle)
cac9a199
RZ
598{
599 struct pp_hwmgr *hwmgr;
1c863802
RZ
600 struct pp_instance *pp_handle = (struct pp_instance *)handle;
601 int ret = 0;
f93f0c3a 602 uint32_t mode = 0;
cac9a199 603
1c863802 604 ret = pp_check(pp_handle);
cac9a199 605
ae97988f 606 if (ret)
1c863802 607 return ret;
cac9a199 608
1c863802 609 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
610
611 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
0fb829de 612 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
613 return 0;
614 }
2a507105 615 mutex_lock(&pp_handle->pp_lock);
f93f0c3a 616 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
2a507105 617 mutex_unlock(&pp_handle->pp_lock);
f93f0c3a 618 return mode;
cac9a199
RZ
619}
620
621static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
622{
623 struct pp_hwmgr *hwmgr;
1c863802
RZ
624 struct pp_instance *pp_handle = (struct pp_instance *)handle;
625 int ret = 0;
cac9a199 626
1c863802 627 ret = pp_check(pp_handle);
cac9a199 628
ae97988f 629 if (ret)
1c863802 630 return ret;
cac9a199 631
1c863802 632 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
633
634 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
0fb829de 635 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
636 return 0;
637 }
2a507105
RZ
638 mutex_lock(&pp_handle->pp_lock);
639 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
640 mutex_unlock(&pp_handle->pp_lock);
641 return ret;
cac9a199
RZ
642}
643
644static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
645{
646 struct pp_hwmgr *hwmgr;
1c863802
RZ
647 struct pp_instance *pp_handle = (struct pp_instance *)handle;
648 int ret = 0;
cac9a199 649
1c863802 650 ret = pp_check(pp_handle);
cac9a199 651
ae97988f 652 if (ret)
1c863802 653 return ret;
cac9a199 654
1c863802 655 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
656
657 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
0fb829de 658 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
659 return 0;
660 }
cac9a199 661
2a507105
RZ
662 mutex_lock(&pp_handle->pp_lock);
663 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
664 mutex_unlock(&pp_handle->pp_lock);
665 return ret;
cac9a199
RZ
666}
667
72a16a9d
GI
668static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
669{
670 struct pp_hwmgr *hwmgr;
1c863802
RZ
671 struct pp_instance *pp_handle = (struct pp_instance *)handle;
672 int ret = 0;
72a16a9d 673
1c863802 674 ret = pp_check(pp_handle);
72a16a9d 675
ae97988f 676 if (ret)
1c863802 677 return ret;
72a16a9d 678
1c863802 679 hwmgr = pp_handle->hwmgr;
72a16a9d
GI
680
681 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
682 return -EINVAL;
683
2a507105
RZ
684 mutex_lock(&pp_handle->pp_lock);
685 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
686 mutex_unlock(&pp_handle->pp_lock);
687 return ret;
72a16a9d
GI
688}
689
f3898ea1
EH
690static int pp_dpm_get_pp_num_states(void *handle,
691 struct pp_states_info *data)
692{
693 struct pp_hwmgr *hwmgr;
694 int i;
1c863802
RZ
695 struct pp_instance *pp_handle = (struct pp_instance *)handle;
696 int ret = 0;
f3898ea1 697
4dbda35f
EQ
698 memset(data, 0, sizeof(*data));
699
1c863802 700 ret = pp_check(pp_handle);
f3898ea1 701
ae97988f 702 if (ret)
1c863802
RZ
703 return ret;
704
705 hwmgr = pp_handle->hwmgr;
f3898ea1 706
1c863802 707 if (hwmgr->ps == NULL)
f3898ea1
EH
708 return -EINVAL;
709
2a507105
RZ
710 mutex_lock(&pp_handle->pp_lock);
711
f3898ea1
EH
712 data->nums = hwmgr->num_ps;
713
714 for (i = 0; i < hwmgr->num_ps; i++) {
715 struct pp_power_state *state = (struct pp_power_state *)
716 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
717 switch (state->classification.ui_label) {
718 case PP_StateUILabel_Battery:
719 data->states[i] = POWER_STATE_TYPE_BATTERY;
720 break;
721 case PP_StateUILabel_Balanced:
722 data->states[i] = POWER_STATE_TYPE_BALANCED;
723 break;
724 case PP_StateUILabel_Performance:
725 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
726 break;
727 default:
728 if (state->classification.flags & PP_StateClassificationFlag_Boot)
729 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
730 else
731 data->states[i] = POWER_STATE_TYPE_DEFAULT;
732 }
733 }
2a507105 734 mutex_unlock(&pp_handle->pp_lock);
f3898ea1
EH
735 return 0;
736}
737
738static int pp_dpm_get_pp_table(void *handle, char **table)
739{
740 struct pp_hwmgr *hwmgr;
1c863802
RZ
741 struct pp_instance *pp_handle = (struct pp_instance *)handle;
742 int ret = 0;
2a507105 743 int size = 0;
f3898ea1 744
1c863802 745 ret = pp_check(pp_handle);
f3898ea1 746
ae97988f 747 if (ret)
1c863802 748 return ret;
f3898ea1 749
1c863802 750 hwmgr = pp_handle->hwmgr;
7383bcb9 751
4dcf9e6f
EH
752 if (!hwmgr->soft_pp_table)
753 return -EINVAL;
754
2a507105 755 mutex_lock(&pp_handle->pp_lock);
4dcf9e6f 756 *table = (char *)hwmgr->soft_pp_table;
2a507105
RZ
757 size = hwmgr->soft_pp_table_size;
758 mutex_unlock(&pp_handle->pp_lock);
759 return size;
f3898ea1
EH
760}
761
f685d714
RZ
762static int amd_powerplay_reset(void *handle)
763{
764 struct pp_instance *instance = (struct pp_instance *)handle;
765 int ret;
766
767 ret = pp_check(instance);
768 if (ret)
769 return ret;
770
771 ret = pp_hw_fini(instance);
772 if (ret)
773 return ret;
774
775 ret = hwmgr_hw_init(instance);
776 if (ret)
777 return ret;
778
39199b80 779 return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL);
f685d714
RZ
780}
781
f3898ea1
EH
782static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
783{
784 struct pp_hwmgr *hwmgr;
1c863802
RZ
785 struct pp_instance *pp_handle = (struct pp_instance *)handle;
786 int ret = 0;
f3898ea1 787
1c863802 788 ret = pp_check(pp_handle);
f3898ea1 789
ae97988f 790 if (ret)
1c863802 791 return ret;
f3898ea1 792
1c863802 793 hwmgr = pp_handle->hwmgr;
2a507105 794 mutex_lock(&pp_handle->pp_lock);
4dcf9e6f 795 if (!hwmgr->hardcode_pp_table) {
efdf7a93
EC
796 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
797 hwmgr->soft_pp_table_size,
798 GFP_KERNEL);
2a507105
RZ
799 if (!hwmgr->hardcode_pp_table) {
800 mutex_unlock(&pp_handle->pp_lock);
4dcf9e6f 801 return -ENOMEM;
2a507105 802 }
7383bcb9 803 }
f3898ea1 804
4dcf9e6f
EH
805 memcpy(hwmgr->hardcode_pp_table, buf, size);
806
807 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
2a507105 808 mutex_unlock(&pp_handle->pp_lock);
4dcf9e6f 809
dd4bdf3b
EH
810 ret = amd_powerplay_reset(handle);
811 if (ret)
812 return ret;
813
814 if (hwmgr->hwmgr_func->avfs_control) {
815 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
816 if (ret)
817 return ret;
818 }
819
820 return 0;
f3898ea1
EH
821}
822
823static int pp_dpm_force_clock_level(void *handle,
5632708f 824 enum pp_clock_type type, uint32_t mask)
f3898ea1
EH
825{
826 struct pp_hwmgr *hwmgr;
1c863802
RZ
827 struct pp_instance *pp_handle = (struct pp_instance *)handle;
828 int ret = 0;
f3898ea1 829
1c863802 830 ret = pp_check(pp_handle);
f3898ea1 831
ae97988f 832 if (ret)
1c863802 833 return ret;
f3898ea1 834
1c863802 835 hwmgr = pp_handle->hwmgr;
7383bcb9
RZ
836
837 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
0fb829de 838 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
839 return 0;
840 }
2a507105 841 mutex_lock(&pp_handle->pp_lock);
948fd66c
RZ
842 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
843 ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
844 else
845 ret = -EINVAL;
2a507105
RZ
846 mutex_unlock(&pp_handle->pp_lock);
847 return ret;
f3898ea1
EH
848}
849
850static int pp_dpm_print_clock_levels(void *handle,
851 enum pp_clock_type type, char *buf)
852{
853 struct pp_hwmgr *hwmgr;
1c863802
RZ
854 struct pp_instance *pp_handle = (struct pp_instance *)handle;
855 int ret = 0;
f3898ea1 856
1c863802 857 ret = pp_check(pp_handle);
f3898ea1 858
ae97988f 859 if (ret)
1c863802 860 return ret;
f3898ea1 861
1c863802 862 hwmgr = pp_handle->hwmgr;
f3898ea1 863
7383bcb9 864 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
0fb829de 865 pr_info("%s was not implemented.\n", __func__);
7383bcb9
RZ
866 return 0;
867 }
2a507105
RZ
868 mutex_lock(&pp_handle->pp_lock);
869 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
870 mutex_unlock(&pp_handle->pp_lock);
871 return ret;
f3898ea1
EH
872}
873
428bafa8
EH
874static int pp_dpm_get_sclk_od(void *handle)
875{
876 struct pp_hwmgr *hwmgr;
1c863802
RZ
877 struct pp_instance *pp_handle = (struct pp_instance *)handle;
878 int ret = 0;
428bafa8 879
1c863802 880 ret = pp_check(pp_handle);
428bafa8 881
ae97988f 882 if (ret)
1c863802 883 return ret;
428bafa8 884
1c863802 885 hwmgr = pp_handle->hwmgr;
428bafa8
EH
886
887 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
0fb829de 888 pr_info("%s was not implemented.\n", __func__);
428bafa8
EH
889 return 0;
890 }
2a507105
RZ
891 mutex_lock(&pp_handle->pp_lock);
892 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
893 mutex_unlock(&pp_handle->pp_lock);
894 return ret;
428bafa8
EH
895}
896
897static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
898{
899 struct pp_hwmgr *hwmgr;
1c863802
RZ
900 struct pp_instance *pp_handle = (struct pp_instance *)handle;
901 int ret = 0;
428bafa8 902
1c863802 903 ret = pp_check(pp_handle);
428bafa8 904
ae97988f 905 if (ret)
1c863802 906 return ret;
428bafa8 907
1c863802 908 hwmgr = pp_handle->hwmgr;
428bafa8
EH
909
910 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
0fb829de 911 pr_info("%s was not implemented.\n", __func__);
428bafa8
EH
912 return 0;
913 }
914
2a507105
RZ
915 mutex_lock(&pp_handle->pp_lock);
916 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
ad4febd9 917 mutex_unlock(&pp_handle->pp_lock);
2a507105 918 return ret;
428bafa8
EH
919}
920
f2bdc05f
EH
921static int pp_dpm_get_mclk_od(void *handle)
922{
923 struct pp_hwmgr *hwmgr;
1c863802
RZ
924 struct pp_instance *pp_handle = (struct pp_instance *)handle;
925 int ret = 0;
f2bdc05f 926
1c863802 927 ret = pp_check(pp_handle);
f2bdc05f 928
ae97988f 929 if (ret)
1c863802 930 return ret;
f2bdc05f 931
1c863802 932 hwmgr = pp_handle->hwmgr;
f2bdc05f
EH
933
934 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
0fb829de 935 pr_info("%s was not implemented.\n", __func__);
f2bdc05f
EH
936 return 0;
937 }
2a507105
RZ
938 mutex_lock(&pp_handle->pp_lock);
939 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
940 mutex_unlock(&pp_handle->pp_lock);
941 return ret;
f2bdc05f
EH
942}
943
944static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
945{
946 struct pp_hwmgr *hwmgr;
1c863802
RZ
947 struct pp_instance *pp_handle = (struct pp_instance *)handle;
948 int ret = 0;
f2bdc05f 949
1c863802 950 ret = pp_check(pp_handle);
f2bdc05f 951
ae97988f 952 if (ret)
1c863802 953 return ret;
f2bdc05f 954
1c863802 955 hwmgr = pp_handle->hwmgr;
f2bdc05f
EH
956
957 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
0fb829de 958 pr_info("%s was not implemented.\n", __func__);
f2bdc05f
EH
959 return 0;
960 }
2a507105
RZ
961 mutex_lock(&pp_handle->pp_lock);
962 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
963 mutex_unlock(&pp_handle->pp_lock);
964 return ret;
f2bdc05f
EH
965}
966
9f8df7d7
TSD
967static int pp_dpm_read_sensor(void *handle, int idx,
968 void *value, int *size)
a6e36952
TSD
969{
970 struct pp_hwmgr *hwmgr;
1c863802
RZ
971 struct pp_instance *pp_handle = (struct pp_instance *)handle;
972 int ret = 0;
a6e36952 973
1c863802 974 ret = pp_check(pp_handle);
ae97988f 975 if (ret)
1c863802 976 return ret;
a6e36952 977
5ed8d656
RZ
978 if (value == NULL)
979 return -EINVAL;
980
1c863802 981 hwmgr = pp_handle->hwmgr;
a6e36952 982
5ed8d656
RZ
983 switch (idx) {
984 case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
985 *((uint32_t *)value) = hwmgr->pstate_sclk;
986 return 0;
987 case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
988 *((uint32_t *)value) = hwmgr->pstate_mclk;
a6e36952 989 return 0;
5ed8d656
RZ
990 default:
991 mutex_lock(&pp_handle->pp_lock);
992 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
993 mutex_unlock(&pp_handle->pp_lock);
994 return ret;
a6e36952 995 }
a6e36952
TSD
996}
997
597be302
AD
998static struct amd_vce_state*
999pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
1000{
1001 struct pp_hwmgr *hwmgr;
1c863802
RZ
1002 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1003 int ret = 0;
597be302 1004
1c863802 1005 ret = pp_check(pp_handle);
597be302 1006
ae97988f 1007 if (ret)
1c863802
RZ
1008 return NULL;
1009
1010 hwmgr = pp_handle->hwmgr;
1011
1012 if (hwmgr && idx < hwmgr->num_vce_state_tables)
1013 return &hwmgr->vce_states[idx];
597be302
AD
1014 return NULL;
1015}
1016
34bb2734
EH
1017static int pp_dpm_reset_power_profile_state(void *handle,
1018 struct amd_pp_profile *request)
1019{
1020 struct pp_hwmgr *hwmgr;
1021 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1022
1023 if (!request || pp_check(pp_handle))
1024 return -EINVAL;
1025
1026 hwmgr = pp_handle->hwmgr;
1027
1028 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1029 pr_info("%s was not implemented.\n", __func__);
1030 return 0;
1031 }
1032
1033 if (request->type == AMD_PP_GFX_PROFILE) {
1034 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1035 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1036 &hwmgr->gfx_power_profile);
1037 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1038 hwmgr->compute_power_profile =
1039 hwmgr->default_compute_power_profile;
1040 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1041 &hwmgr->compute_power_profile);
1042 } else
1043 return -EINVAL;
1044}
1045
1046static int pp_dpm_get_power_profile_state(void *handle,
1047 struct amd_pp_profile *query)
1048{
1049 struct pp_hwmgr *hwmgr;
1050 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1051
1052 if (!query || pp_check(pp_handle))
1053 return -EINVAL;
1054
1055 hwmgr = pp_handle->hwmgr;
1056
1057 if (query->type == AMD_PP_GFX_PROFILE)
1058 memcpy(query, &hwmgr->gfx_power_profile,
1059 sizeof(struct amd_pp_profile));
1060 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1061 memcpy(query, &hwmgr->compute_power_profile,
1062 sizeof(struct amd_pp_profile));
1063 else
1064 return -EINVAL;
1065
1066 return 0;
1067}
1068
6390258a
RZ
1069static int pp_get_power_profile_mode(void *handle, char *buf)
1070{
1071 struct pp_hwmgr *hwmgr;
1072 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1073
1074 if (!buf || pp_check(pp_handle))
1075 return -EINVAL;
1076
1077 hwmgr = pp_handle->hwmgr;
1078
1079 if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) {
1080 pr_info("%s was not implemented.\n", __func__);
1081 return snprintf(buf, PAGE_SIZE, "\n");
1082 }
1083
1084 return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
1085}
1086
1087static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
1088{
1089 struct pp_hwmgr *hwmgr;
1090 struct pp_instance *pp_handle = (struct pp_instance *)handle;
337ecd6a 1091 int ret = -EINVAL;
6390258a
RZ
1092
1093 if (pp_check(pp_handle))
1094 return -EINVAL;
1095
1096 hwmgr = pp_handle->hwmgr;
1097
1098 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
1099 pr_info("%s was not implemented.\n", __func__);
1100 return -EINVAL;
1101 }
337ecd6a
RZ
1102 mutex_lock(&pp_handle->pp_lock);
1103 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)
1104 ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
1105 mutex_unlock(&pp_handle->pp_lock);
1106 return ret;
6390258a
RZ
1107}
1108
e3933f26
RZ
1109static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
1110{
1111 struct pp_hwmgr *hwmgr;
1112 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1113
1114 if (pp_check(pp_handle))
1115 return -EINVAL;
1116
1117 hwmgr = pp_handle->hwmgr;
1118
1119 if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {
1120 pr_info("%s was not implemented.\n", __func__);
1121 return -EINVAL;
1122 }
1123
1124 return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
1125}
1126
34bb2734
EH
1127static int pp_dpm_set_power_profile_state(void *handle,
1128 struct amd_pp_profile *request)
1129{
1130 struct pp_hwmgr *hwmgr;
1131 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1132 int ret = -1;
1133
1134 if (!request || pp_check(pp_handle))
1135 return -EINVAL;
1136
1137 hwmgr = pp_handle->hwmgr;
1138
1139 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1140 pr_info("%s was not implemented.\n", __func__);
1141 return 0;
1142 }
1143
1144 if (request->min_sclk ||
1145 request->min_mclk ||
1146 request->activity_threshold ||
1147 request->up_hyst ||
1148 request->down_hyst) {
1149 if (request->type == AMD_PP_GFX_PROFILE)
1150 memcpy(&hwmgr->gfx_power_profile, request,
1151 sizeof(struct amd_pp_profile));
1152 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1153 memcpy(&hwmgr->compute_power_profile, request,
1154 sizeof(struct amd_pp_profile));
1155 else
1156 return -EINVAL;
1157
1158 if (request->type == hwmgr->current_power_profile)
1159 ret = hwmgr->hwmgr_func->set_power_profile_state(
1160 hwmgr,
1161 request);
1162 } else {
1163 /* set power profile if it exists */
1164 switch (request->type) {
1165 case AMD_PP_GFX_PROFILE:
1166 ret = hwmgr->hwmgr_func->set_power_profile_state(
1167 hwmgr,
1168 &hwmgr->gfx_power_profile);
1169 break;
1170 case AMD_PP_COMPUTE_PROFILE:
1171 ret = hwmgr->hwmgr_func->set_power_profile_state(
1172 hwmgr,
1173 &hwmgr->compute_power_profile);
1174 break;
1175 default:
1176 return -EINVAL;
1177 }
1178 }
1179
1180 if (!ret)
1181 hwmgr->current_power_profile = request->type;
1182
1183 return 0;
1184}
1185
1186static int pp_dpm_switch_power_profile(void *handle,
1187 enum amd_pp_profile_type type)
1188{
1189 struct pp_hwmgr *hwmgr;
1190 struct amd_pp_profile request = {0};
1191 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1192
1193 if (pp_check(pp_handle))
1194 return -EINVAL;
1195
1196 hwmgr = pp_handle->hwmgr;
1197
1198 if (hwmgr->current_power_profile != type) {
1199 request.type = type;
1200 pp_dpm_set_power_profile_state(handle, &request);
1201 }
1202
1203 return 0;
1204}
1205
4c7c8bbb
RZ
1206static int pp_dpm_notify_smu_memory_info(void *handle,
1207 uint32_t virtual_addr_low,
1208 uint32_t virtual_addr_hi,
1209 uint32_t mc_addr_low,
1210 uint32_t mc_addr_hi,
1211 uint32_t size)
1212{
1213 struct pp_hwmgr *hwmgr;
1214 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1215 int ret = 0;
1216
1217 ret = pp_check(pp_handle);
1218
1219 if (ret)
1220 return ret;
1221
1222 hwmgr = pp_handle->hwmgr;
1223
1224 if (hwmgr->hwmgr_func->notify_cac_buffer_info == NULL) {
1225 pr_info("%s was not implemented.\n", __func__);
1226 return -EINVAL;
1227 }
1228
1229 mutex_lock(&pp_handle->pp_lock);
1230
1231 ret = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr, virtual_addr_low,
1232 virtual_addr_hi, mc_addr_low, mc_addr_hi,
1233 size);
1234
1235 mutex_unlock(&pp_handle->pp_lock);
1236
1237 return ret;
1238}
1239
f685d714 1240static int pp_display_configuration_change(void *handle,
155f1127 1241 const struct amd_pp_display_configuration *display_config)
7fb72a1f
RZ
1242{
1243 struct pp_hwmgr *hwmgr;
1c863802
RZ
1244 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1245 int ret = 0;
7fb72a1f 1246
1c863802 1247 ret = pp_check(pp_handle);
7fb72a1f 1248
ae97988f 1249 if (ret)
1c863802 1250 return ret;
7fb72a1f 1251
1c863802 1252 hwmgr = pp_handle->hwmgr;
2a507105 1253 mutex_lock(&pp_handle->pp_lock);
7fb72a1f 1254 phm_store_dal_configuration_data(hwmgr, display_config);
2a507105 1255 mutex_unlock(&pp_handle->pp_lock);
7fb72a1f
RZ
1256 return 0;
1257}
c4dd206b 1258
f685d714 1259static int pp_get_display_power_level(void *handle,
47329134 1260 struct amd_pp_simple_clock_info *output)
c4dd206b
VP
1261{
1262 struct pp_hwmgr *hwmgr;
1c863802
RZ
1263 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1264 int ret = 0;
c4dd206b 1265
1c863802 1266 ret = pp_check(pp_handle);
a969e163 1267
ae97988f 1268 if (ret)
1c863802 1269 return ret;
c4dd206b 1270
1c863802 1271 hwmgr = pp_handle->hwmgr;
c4dd206b 1272
1c863802
RZ
1273 if (output == NULL)
1274 return -EINVAL;
ba5f884c 1275
2a507105
RZ
1276 mutex_lock(&pp_handle->pp_lock);
1277 ret = phm_get_dal_power_level(hwmgr, output);
1278 mutex_unlock(&pp_handle->pp_lock);
1279 return ret;
c4dd206b 1280}
e273b041 1281
f685d714 1282static int pp_get_current_clocks(void *handle,
155f1127 1283 struct amd_pp_clock_info *clocks)
e273b041 1284{
e273b041
RZ
1285 struct amd_pp_simple_clock_info simple_clocks;
1286 struct pp_clock_info hw_clocks;
1c863802
RZ
1287 struct pp_hwmgr *hwmgr;
1288 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1289 int ret = 0;
e273b041 1290
1c863802 1291 ret = pp_check(pp_handle);
e273b041 1292
ae97988f 1293 if (ret)
1c863802 1294 return ret;
e273b041 1295
1c863802 1296 hwmgr = pp_handle->hwmgr;
ba5f884c 1297
2a507105
RZ
1298 mutex_lock(&pp_handle->pp_lock);
1299
e273b041
RZ
1300 phm_get_dal_power_level(hwmgr, &simple_clocks);
1301
2a507105
RZ
1302 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1303 PHM_PlatformCaps_PowerContainment))
1304 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1305 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1306 else
1307 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1308 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1309
ae97988f 1310 if (ret) {
2a507105
RZ
1311 pr_info("Error in phm_get_clock_info \n");
1312 mutex_unlock(&pp_handle->pp_lock);
1313 return -EINVAL;
e273b041
RZ
1314 }
1315
1316 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1317 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1318 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1319 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1320 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1321 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1322
1323 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1324 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1325
1326 clocks->max_clocks_state = simple_clocks.level;
1327
1328 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1329 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1330 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1331 }
2a507105 1332 mutex_unlock(&pp_handle->pp_lock);
e273b041 1333 return 0;
e273b041
RZ
1334}
1335
f685d714 1336static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
e273b041 1337{
1c863802
RZ
1338 struct pp_hwmgr *hwmgr;
1339 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1340 int ret = 0;
e273b041 1341
1c863802 1342 ret = pp_check(pp_handle);
e273b041 1343
ae97988f 1344 if (ret)
1c863802
RZ
1345 return ret;
1346
1347 hwmgr = pp_handle->hwmgr;
fa9e6991
RZ
1348
1349 if (clocks == NULL)
e273b041
RZ
1350 return -EINVAL;
1351
2a507105
RZ
1352 mutex_lock(&pp_handle->pp_lock);
1353 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1354 mutex_unlock(&pp_handle->pp_lock);
1355 return ret;
e273b041
RZ
1356}
1357
f685d714 1358static int pp_get_clock_by_type_with_latency(void *handle,
d0187727
EH
1359 enum amd_pp_clock_type type,
1360 struct pp_clock_levels_with_latency *clocks)
1361{
1362 struct pp_hwmgr *hwmgr;
1363 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1364 int ret = 0;
1365
1366 ret = pp_check(pp_handle);
ae97988f 1367 if (ret)
d0187727
EH
1368 return ret;
1369
1370 if (!clocks)
1371 return -EINVAL;
1372
1373 mutex_lock(&pp_handle->pp_lock);
1374 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1375 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1376 mutex_unlock(&pp_handle->pp_lock);
1377 return ret;
1378}
1379
f685d714 1380static int pp_get_clock_by_type_with_voltage(void *handle,
d0187727
EH
1381 enum amd_pp_clock_type type,
1382 struct pp_clock_levels_with_voltage *clocks)
1383{
1384 struct pp_hwmgr *hwmgr;
1385 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1386 int ret = 0;
1387
1388 ret = pp_check(pp_handle);
ae97988f 1389 if (ret)
d0187727
EH
1390 return ret;
1391
1392 if (!clocks)
1393 return -EINVAL;
1394
1395 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1396
1397 mutex_lock(&pp_handle->pp_lock);
1398
1399 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1400
1401 mutex_unlock(&pp_handle->pp_lock);
1402 return ret;
1403}
1404
f685d714 1405static int pp_set_watermarks_for_clocks_ranges(void *handle,
d0187727
EH
1406 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1407{
1408 struct pp_hwmgr *hwmgr;
1409 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1410 int ret = 0;
1411
1412 ret = pp_check(pp_handle);
ae97988f 1413 if (ret)
d0187727
EH
1414 return ret;
1415
1416 if (!wm_with_clock_ranges)
1417 return -EINVAL;
1418
1419 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1420
1421 mutex_lock(&pp_handle->pp_lock);
1422 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1423 wm_with_clock_ranges);
1424 mutex_unlock(&pp_handle->pp_lock);
1425
1426 return ret;
1427}
1428
f685d714 1429static int pp_display_clock_voltage_request(void *handle,
d0187727
EH
1430 struct pp_display_clock_request *clock)
1431{
1432 struct pp_hwmgr *hwmgr;
1433 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1434 int ret = 0;
1435
1436 ret = pp_check(pp_handle);
ae97988f 1437 if (ret)
d0187727
EH
1438 return ret;
1439
1440 if (!clock)
1441 return -EINVAL;
1442
1443 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1444
1445 mutex_lock(&pp_handle->pp_lock);
1446 ret = phm_display_clock_voltage_request(hwmgr, clock);
1447 mutex_unlock(&pp_handle->pp_lock);
1448
1449 return ret;
1450}
1451
f685d714 1452static int pp_get_display_mode_validation_clocks(void *handle,
155f1127 1453 struct amd_pp_simple_clock_info *clocks)
e273b041 1454{
e273b041 1455 struct pp_hwmgr *hwmgr;
1c863802
RZ
1456 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1457 int ret = 0;
e273b041 1458
1c863802 1459 ret = pp_check(pp_handle);
fa9e6991 1460
ae97988f 1461 if (ret)
1c863802
RZ
1462 return ret;
1463
1464 hwmgr = pp_handle->hwmgr;
e273b041 1465
1c863802
RZ
1466 if (clocks == NULL)
1467 return -EINVAL;
ba5f884c 1468
2a507105
RZ
1469 mutex_lock(&pp_handle->pp_lock);
1470
e273b041 1471 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1c863802 1472 ret = phm_get_max_high_clocks(hwmgr, clocks);
e273b041 1473
2a507105 1474 mutex_unlock(&pp_handle->pp_lock);
1c863802 1475 return ret;
e273b041
RZ
1476}
1477
f685d714 1478const struct amd_pm_funcs pp_dpm_funcs = {
f685d714
RZ
1479 .load_firmware = pp_dpm_load_fw,
1480 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1481 .force_performance_level = pp_dpm_force_performance_level,
1482 .get_performance_level = pp_dpm_get_performance_level,
1483 .get_current_power_state = pp_dpm_get_current_power_state,
1484 .powergate_vce = pp_dpm_powergate_vce,
1485 .powergate_uvd = pp_dpm_powergate_uvd,
1486 .dispatch_tasks = pp_dpm_dispatch_tasks,
1487 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1488 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1489 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1490 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
1491 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1492 .get_pp_num_states = pp_dpm_get_pp_num_states,
1493 .get_pp_table = pp_dpm_get_pp_table,
1494 .set_pp_table = pp_dpm_set_pp_table,
1495 .force_clock_level = pp_dpm_force_clock_level,
1496 .print_clock_levels = pp_dpm_print_clock_levels,
1497 .get_sclk_od = pp_dpm_get_sclk_od,
1498 .set_sclk_od = pp_dpm_set_sclk_od,
1499 .get_mclk_od = pp_dpm_get_mclk_od,
1500 .set_mclk_od = pp_dpm_set_mclk_od,
1501 .read_sensor = pp_dpm_read_sensor,
1502 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
1503 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1504 .get_power_profile_state = pp_dpm_get_power_profile_state,
1505 .set_power_profile_state = pp_dpm_set_power_profile_state,
1506 .switch_power_profile = pp_dpm_switch_power_profile,
1507 .set_clockgating_by_smu = pp_set_clockgating_by_smu,
4c7c8bbb 1508 .notify_smu_memory_info = pp_dpm_notify_smu_memory_info,
6390258a
RZ
1509 .get_power_profile_mode = pp_get_power_profile_mode,
1510 .set_power_profile_mode = pp_set_power_profile_mode,
e3933f26 1511 .odn_edit_dpm_table = pp_odn_edit_dpm_table,
f685d714
RZ
1512/* export to DC */
1513 .get_sclk = pp_dpm_get_sclk,
1514 .get_mclk = pp_dpm_get_mclk,
1515 .display_configuration_change = pp_display_configuration_change,
1516 .get_display_power_level = pp_get_display_power_level,
1517 .get_current_clocks = pp_get_current_clocks,
1518 .get_clock_by_type = pp_get_clock_by_type,
1519 .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
1520 .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
1521 .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
1522 .display_clock_voltage_request = pp_display_clock_voltage_request,
1523 .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
1524};