Line data Source code
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 : */
23 : #include "pp_debug.h"
24 : #include <linux/types.h>
25 : #include <linux/kernel.h>
26 : #include <linux/gfp.h>
27 : #include <linux/slab.h>
28 : #include <linux/firmware.h>
29 : #include "amd_shared.h"
30 : #include "amd_powerplay.h"
31 : #include "power_state.h"
32 : #include "amdgpu.h"
33 : #include "hwmgr.h"
34 : #include "amdgpu_dpm_internal.h"
35 : #include "amdgpu_display.h"
36 :
37 : static const struct amd_pm_funcs pp_dpm_funcs;
38 :
39 0 : static int amd_powerplay_create(struct amdgpu_device *adev)
40 : {
41 : struct pp_hwmgr *hwmgr;
42 :
43 0 : if (adev == NULL)
44 : return -EINVAL;
45 :
46 0 : hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
47 0 : if (hwmgr == NULL)
48 : return -ENOMEM;
49 :
50 0 : hwmgr->adev = adev;
51 0 : hwmgr->not_vf = !amdgpu_sriov_vf(adev);
52 0 : hwmgr->device = amdgpu_cgs_create_device(adev);
53 0 : mutex_init(&hwmgr->msg_lock);
54 0 : hwmgr->chip_family = adev->family;
55 0 : hwmgr->chip_id = adev->asic_type;
56 0 : hwmgr->feature_mask = adev->pm.pp_feature;
57 0 : hwmgr->display_config = &adev->pm.pm_display_cfg;
58 0 : adev->powerplay.pp_handle = hwmgr;
59 0 : adev->powerplay.pp_funcs = &pp_dpm_funcs;
60 0 : return 0;
61 : }
62 :
63 :
64 : static void amd_powerplay_destroy(struct amdgpu_device *adev)
65 : {
66 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
67 :
68 0 : mutex_destroy(&hwmgr->msg_lock);
69 :
70 0 : kfree(hwmgr->hardcode_pp_table);
71 0 : hwmgr->hardcode_pp_table = NULL;
72 :
73 0 : kfree(hwmgr);
74 0 : hwmgr = NULL;
75 : }
76 :
77 0 : static int pp_early_init(void *handle)
78 : {
79 : int ret;
80 0 : struct amdgpu_device *adev = handle;
81 :
82 0 : ret = amd_powerplay_create(adev);
83 :
84 0 : if (ret != 0)
85 : return ret;
86 :
87 0 : ret = hwmgr_early_init(adev->powerplay.pp_handle);
88 0 : if (ret)
89 : return -EINVAL;
90 :
91 0 : return 0;
92 : }
93 :
94 0 : static int pp_sw_init(void *handle)
95 : {
96 0 : struct amdgpu_device *adev = handle;
97 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
98 0 : int ret = 0;
99 :
100 0 : ret = hwmgr_sw_init(hwmgr);
101 :
102 : pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");
103 :
104 0 : return ret;
105 : }
106 :
107 0 : static int pp_sw_fini(void *handle)
108 : {
109 0 : struct amdgpu_device *adev = handle;
110 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
111 :
112 0 : hwmgr_sw_fini(hwmgr);
113 :
114 0 : release_firmware(adev->pm.fw);
115 0 : adev->pm.fw = NULL;
116 :
117 0 : return 0;
118 : }
119 :
120 0 : static int pp_hw_init(void *handle)
121 : {
122 0 : int ret = 0;
123 0 : struct amdgpu_device *adev = handle;
124 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
125 :
126 0 : ret = hwmgr_hw_init(hwmgr);
127 :
128 0 : if (ret)
129 0 : pr_err("powerplay hw init failed\n");
130 :
131 0 : return ret;
132 : }
133 :
134 0 : static int pp_hw_fini(void *handle)
135 : {
136 0 : struct amdgpu_device *adev = handle;
137 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
138 :
139 0 : hwmgr_hw_fini(hwmgr);
140 :
141 0 : return 0;
142 : }
143 :
144 0 : static void pp_reserve_vram_for_smu(struct amdgpu_device *adev)
145 : {
146 0 : int r = -EINVAL;
147 0 : void *cpu_ptr = NULL;
148 : uint64_t gpu_addr;
149 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
150 :
151 0 : if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size,
152 : PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
153 : &adev->pm.smu_prv_buffer,
154 : &gpu_addr,
155 : &cpu_ptr)) {
156 0 : DRM_ERROR("amdgpu: failed to create smu prv buffer\n");
157 0 : return;
158 : }
159 :
160 0 : if (hwmgr->hwmgr_func->notify_cac_buffer_info)
161 0 : r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr,
162 : lower_32_bits((unsigned long)cpu_ptr),
163 0 : upper_32_bits((unsigned long)cpu_ptr),
164 : lower_32_bits(gpu_addr),
165 0 : upper_32_bits(gpu_addr),
166 : adev->pm.smu_prv_buffer_size);
167 :
168 0 : if (r) {
169 0 : amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
170 0 : adev->pm.smu_prv_buffer = NULL;
171 0 : DRM_ERROR("amdgpu: failed to notify SMU buffer address\n");
172 : }
173 : }
174 :
175 0 : static int pp_late_init(void *handle)
176 : {
177 0 : struct amdgpu_device *adev = handle;
178 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
179 :
180 0 : if (hwmgr && hwmgr->pm_en)
181 0 : hwmgr_handle_task(hwmgr,
182 : AMD_PP_TASK_COMPLETE_INIT, NULL);
183 0 : if (adev->pm.smu_prv_buffer_size != 0)
184 0 : pp_reserve_vram_for_smu(adev);
185 :
186 0 : return 0;
187 : }
188 :
189 0 : static void pp_late_fini(void *handle)
190 : {
191 0 : struct amdgpu_device *adev = handle;
192 :
193 0 : if (adev->pm.smu_prv_buffer)
194 0 : amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
195 0 : amd_powerplay_destroy(adev);
196 0 : }
197 :
198 :
199 0 : static bool pp_is_idle(void *handle)
200 : {
201 0 : return false;
202 : }
203 :
204 0 : static int pp_wait_for_idle(void *handle)
205 : {
206 0 : return 0;
207 : }
208 :
209 0 : static int pp_sw_reset(void *handle)
210 : {
211 0 : return 0;
212 : }
213 :
214 0 : static int pp_set_powergating_state(void *handle,
215 : enum amd_powergating_state state)
216 : {
217 0 : return 0;
218 : }
219 :
220 0 : static int pp_suspend(void *handle)
221 : {
222 0 : struct amdgpu_device *adev = handle;
223 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
224 :
225 0 : return hwmgr_suspend(hwmgr);
226 : }
227 :
228 0 : static int pp_resume(void *handle)
229 : {
230 0 : struct amdgpu_device *adev = handle;
231 0 : struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
232 :
233 0 : return hwmgr_resume(hwmgr);
234 : }
235 :
236 0 : static int pp_set_clockgating_state(void *handle,
237 : enum amd_clockgating_state state)
238 : {
239 0 : return 0;
240 : }
241 :
242 : static const struct amd_ip_funcs pp_ip_funcs = {
243 : .name = "powerplay",
244 : .early_init = pp_early_init,
245 : .late_init = pp_late_init,
246 : .sw_init = pp_sw_init,
247 : .sw_fini = pp_sw_fini,
248 : .hw_init = pp_hw_init,
249 : .hw_fini = pp_hw_fini,
250 : .late_fini = pp_late_fini,
251 : .suspend = pp_suspend,
252 : .resume = pp_resume,
253 : .is_idle = pp_is_idle,
254 : .wait_for_idle = pp_wait_for_idle,
255 : .soft_reset = pp_sw_reset,
256 : .set_clockgating_state = pp_set_clockgating_state,
257 : .set_powergating_state = pp_set_powergating_state,
258 : };
259 :
260 : const struct amdgpu_ip_block_version pp_smu_ip_block =
261 : {
262 : .type = AMD_IP_BLOCK_TYPE_SMC,
263 : .major = 1,
264 : .minor = 0,
265 : .rev = 0,
266 : .funcs = &pp_ip_funcs,
267 : };
268 :
269 : /* This interface only be supported On Vi,
270 : * because only smu7/8 can help to load gfx/sdma fw,
271 : * smu need to be enabled before load other ip's fw.
272 : * so call start smu to load smu7 fw and other ip's fw
273 : */
274 0 : static int pp_dpm_load_fw(void *handle)
275 : {
276 0 : struct pp_hwmgr *hwmgr = handle;
277 :
278 0 : if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu)
279 : return -EINVAL;
280 :
281 0 : if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {
282 0 : pr_err("fw load failed\n");
283 0 : return -EINVAL;
284 : }
285 :
286 : return 0;
287 : }
288 :
289 0 : static int pp_dpm_fw_loading_complete(void *handle)
290 : {
291 0 : return 0;
292 : }
293 :
294 0 : static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
295 : {
296 0 : struct pp_hwmgr *hwmgr = handle;
297 :
298 0 : if (!hwmgr || !hwmgr->pm_en)
299 : return -EINVAL;
300 :
301 0 : if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
302 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
303 : return 0;
304 : }
305 :
306 0 : return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
307 : }
308 :
309 : static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
310 : enum amd_dpm_forced_level *level)
311 : {
312 0 : uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
313 : AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
314 : AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
315 : AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
316 :
317 0 : if (!(hwmgr->dpm_level & profile_mode_mask)) {
318 : /* enter umd pstate, save current level, disable gfx cg*/
319 0 : if (*level & profile_mode_mask) {
320 0 : hwmgr->saved_dpm_level = hwmgr->dpm_level;
321 0 : hwmgr->en_umd_pstate = true;
322 : }
323 : } else {
324 : /* exit umd pstate, restore level, enable gfx cg*/
325 0 : if (!(*level & profile_mode_mask)) {
326 0 : if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
327 0 : *level = hwmgr->saved_dpm_level;
328 0 : hwmgr->en_umd_pstate = false;
329 : }
330 : }
331 : }
332 :
333 0 : static int pp_dpm_force_performance_level(void *handle,
334 : enum amd_dpm_forced_level level)
335 : {
336 0 : struct pp_hwmgr *hwmgr = handle;
337 :
338 0 : if (!hwmgr || !hwmgr->pm_en)
339 : return -EINVAL;
340 :
341 0 : if (level == hwmgr->dpm_level)
342 : return 0;
343 :
344 0 : pp_dpm_en_umd_pstate(hwmgr, &level);
345 0 : hwmgr->request_dpm_level = level;
346 0 : hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
347 :
348 0 : return 0;
349 : }
350 :
351 0 : static enum amd_dpm_forced_level pp_dpm_get_performance_level(
352 : void *handle)
353 : {
354 0 : struct pp_hwmgr *hwmgr = handle;
355 :
356 0 : if (!hwmgr || !hwmgr->pm_en)
357 : return -EINVAL;
358 :
359 0 : return hwmgr->dpm_level;
360 : }
361 :
362 0 : static uint32_t pp_dpm_get_sclk(void *handle, bool low)
363 : {
364 0 : struct pp_hwmgr *hwmgr = handle;
365 :
366 0 : if (!hwmgr || !hwmgr->pm_en)
367 : return 0;
368 :
369 0 : if (hwmgr->hwmgr_func->get_sclk == NULL) {
370 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
371 : return 0;
372 : }
373 0 : return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
374 : }
375 :
376 0 : static uint32_t pp_dpm_get_mclk(void *handle, bool low)
377 : {
378 0 : struct pp_hwmgr *hwmgr = handle;
379 :
380 0 : if (!hwmgr || !hwmgr->pm_en)
381 : return 0;
382 :
383 0 : if (hwmgr->hwmgr_func->get_mclk == NULL) {
384 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
385 : return 0;
386 : }
387 0 : return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
388 : }
389 :
390 0 : static void pp_dpm_powergate_vce(void *handle, bool gate)
391 : {
392 0 : struct pp_hwmgr *hwmgr = handle;
393 :
394 0 : if (!hwmgr || !hwmgr->pm_en)
395 : return;
396 :
397 0 : if (hwmgr->hwmgr_func->powergate_vce == NULL) {
398 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
399 : return;
400 : }
401 0 : hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
402 : }
403 :
404 0 : static void pp_dpm_powergate_uvd(void *handle, bool gate)
405 : {
406 0 : struct pp_hwmgr *hwmgr = handle;
407 :
408 0 : if (!hwmgr || !hwmgr->pm_en)
409 : return;
410 :
411 0 : if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
412 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
413 : return;
414 : }
415 0 : hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
416 : }
417 :
418 0 : static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
419 : enum amd_pm_state_type *user_state)
420 : {
421 0 : struct pp_hwmgr *hwmgr = handle;
422 :
423 0 : if (!hwmgr || !hwmgr->pm_en)
424 : return -EINVAL;
425 :
426 0 : return hwmgr_handle_task(hwmgr, task_id, user_state);
427 : }
428 :
429 0 : static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
430 : {
431 0 : struct pp_hwmgr *hwmgr = handle;
432 : struct pp_power_state *state;
433 : enum amd_pm_state_type pm_type;
434 :
435 0 : if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)
436 : return -EINVAL;
437 :
438 0 : state = hwmgr->current_ps;
439 :
440 0 : switch (state->classification.ui_label) {
441 : case PP_StateUILabel_Battery:
442 : pm_type = POWER_STATE_TYPE_BATTERY;
443 : break;
444 : case PP_StateUILabel_Balanced:
445 0 : pm_type = POWER_STATE_TYPE_BALANCED;
446 0 : break;
447 : case PP_StateUILabel_Performance:
448 0 : pm_type = POWER_STATE_TYPE_PERFORMANCE;
449 0 : break;
450 : default:
451 0 : if (state->classification.flags & PP_StateClassificationFlag_Boot)
452 : pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
453 : else
454 0 : pm_type = POWER_STATE_TYPE_DEFAULT;
455 : break;
456 : }
457 :
458 : return pm_type;
459 : }
460 :
461 0 : static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
462 : {
463 0 : struct pp_hwmgr *hwmgr = handle;
464 :
465 0 : if (!hwmgr || !hwmgr->pm_en)
466 : return -EOPNOTSUPP;
467 :
468 0 : if (hwmgr->hwmgr_func->set_fan_control_mode == NULL)
469 : return -EOPNOTSUPP;
470 :
471 0 : if (mode == U32_MAX)
472 : return -EINVAL;
473 :
474 0 : hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
475 :
476 0 : return 0;
477 : }
478 :
479 0 : static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode)
480 : {
481 0 : struct pp_hwmgr *hwmgr = handle;
482 :
483 0 : if (!hwmgr || !hwmgr->pm_en)
484 : return -EOPNOTSUPP;
485 :
486 0 : if (hwmgr->hwmgr_func->get_fan_control_mode == NULL)
487 : return -EOPNOTSUPP;
488 :
489 0 : if (!fan_mode)
490 : return -EINVAL;
491 :
492 0 : *fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
493 0 : return 0;
494 : }
495 :
496 0 : static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed)
497 : {
498 0 : struct pp_hwmgr *hwmgr = handle;
499 :
500 0 : if (!hwmgr || !hwmgr->pm_en)
501 : return -EOPNOTSUPP;
502 :
503 0 : if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL)
504 : return -EOPNOTSUPP;
505 :
506 0 : if (speed == U32_MAX)
507 : return -EINVAL;
508 :
509 0 : return hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed);
510 : }
511 :
512 0 : static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed)
513 : {
514 0 : struct pp_hwmgr *hwmgr = handle;
515 :
516 0 : if (!hwmgr || !hwmgr->pm_en)
517 : return -EOPNOTSUPP;
518 :
519 0 : if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL)
520 : return -EOPNOTSUPP;
521 :
522 0 : if (!speed)
523 : return -EINVAL;
524 :
525 0 : return hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed);
526 : }
527 :
528 0 : static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
529 : {
530 0 : struct pp_hwmgr *hwmgr = handle;
531 :
532 0 : if (!hwmgr || !hwmgr->pm_en)
533 : return -EOPNOTSUPP;
534 :
535 0 : if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
536 : return -EOPNOTSUPP;
537 :
538 0 : if (!rpm)
539 : return -EINVAL;
540 :
541 0 : return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
542 : }
543 :
544 0 : static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm)
545 : {
546 0 : struct pp_hwmgr *hwmgr = handle;
547 :
548 0 : if (!hwmgr || !hwmgr->pm_en)
549 : return -EOPNOTSUPP;
550 :
551 0 : if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL)
552 : return -EOPNOTSUPP;
553 :
554 0 : if (rpm == U32_MAX)
555 : return -EINVAL;
556 :
557 0 : return hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm);
558 : }
559 :
560 0 : static int pp_dpm_get_pp_num_states(void *handle,
561 : struct pp_states_info *data)
562 : {
563 0 : struct pp_hwmgr *hwmgr = handle;
564 : int i;
565 :
566 0 : memset(data, 0, sizeof(*data));
567 :
568 0 : if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps)
569 : return -EINVAL;
570 :
571 0 : data->nums = hwmgr->num_ps;
572 :
573 0 : for (i = 0; i < hwmgr->num_ps; i++) {
574 0 : struct pp_power_state *state = (struct pp_power_state *)
575 0 : ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
576 0 : switch (state->classification.ui_label) {
577 : case PP_StateUILabel_Battery:
578 0 : data->states[i] = POWER_STATE_TYPE_BATTERY;
579 0 : break;
580 : case PP_StateUILabel_Balanced:
581 0 : data->states[i] = POWER_STATE_TYPE_BALANCED;
582 0 : break;
583 : case PP_StateUILabel_Performance:
584 0 : data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
585 0 : break;
586 : default:
587 0 : if (state->classification.flags & PP_StateClassificationFlag_Boot)
588 0 : data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
589 : else
590 0 : data->states[i] = POWER_STATE_TYPE_DEFAULT;
591 : }
592 : }
593 : return 0;
594 : }
595 :
596 0 : static int pp_dpm_get_pp_table(void *handle, char **table)
597 : {
598 0 : struct pp_hwmgr *hwmgr = handle;
599 :
600 0 : if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table)
601 : return -EINVAL;
602 :
603 0 : *table = (char *)hwmgr->soft_pp_table;
604 0 : return hwmgr->soft_pp_table_size;
605 : }
606 :
607 0 : static int amd_powerplay_reset(void *handle)
608 : {
609 0 : struct pp_hwmgr *hwmgr = handle;
610 : int ret;
611 :
612 0 : ret = hwmgr_hw_fini(hwmgr);
613 0 : if (ret)
614 : return ret;
615 :
616 0 : ret = hwmgr_hw_init(hwmgr);
617 0 : if (ret)
618 : return ret;
619 :
620 0 : return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL);
621 : }
622 :
623 0 : static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
624 : {
625 0 : struct pp_hwmgr *hwmgr = handle;
626 0 : int ret = -ENOMEM;
627 :
628 0 : if (!hwmgr || !hwmgr->pm_en)
629 : return -EINVAL;
630 :
631 0 : if (!hwmgr->hardcode_pp_table) {
632 0 : hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
633 0 : hwmgr->soft_pp_table_size,
634 : GFP_KERNEL);
635 0 : if (!hwmgr->hardcode_pp_table)
636 : return ret;
637 : }
638 :
639 0 : memcpy(hwmgr->hardcode_pp_table, buf, size);
640 :
641 0 : hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
642 :
643 0 : ret = amd_powerplay_reset(handle);
644 0 : if (ret)
645 : return ret;
646 :
647 0 : if (hwmgr->hwmgr_func->avfs_control)
648 0 : ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
649 :
650 : return ret;
651 : }
652 :
653 0 : static int pp_dpm_force_clock_level(void *handle,
654 : enum pp_clock_type type, uint32_t mask)
655 : {
656 0 : struct pp_hwmgr *hwmgr = handle;
657 :
658 0 : if (!hwmgr || !hwmgr->pm_en)
659 : return -EINVAL;
660 :
661 0 : if (hwmgr->hwmgr_func->force_clock_level == NULL) {
662 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
663 : return 0;
664 : }
665 :
666 0 : if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
667 : pr_debug("force clock level is for dpm manual mode only.\n");
668 : return -EINVAL;
669 : }
670 :
671 0 : return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
672 : }
673 :
674 0 : static int pp_dpm_emit_clock_levels(void *handle,
675 : enum pp_clock_type type,
676 : char *buf,
677 : int *offset)
678 : {
679 0 : struct pp_hwmgr *hwmgr = handle;
680 :
681 0 : if (!hwmgr || !hwmgr->pm_en)
682 : return -EOPNOTSUPP;
683 :
684 0 : if (!hwmgr->hwmgr_func->emit_clock_levels)
685 : return -ENOENT;
686 :
687 0 : return hwmgr->hwmgr_func->emit_clock_levels(hwmgr, type, buf, offset);
688 : }
689 :
690 0 : static int pp_dpm_print_clock_levels(void *handle,
691 : enum pp_clock_type type, char *buf)
692 : {
693 0 : struct pp_hwmgr *hwmgr = handle;
694 :
695 0 : if (!hwmgr || !hwmgr->pm_en)
696 : return -EINVAL;
697 :
698 0 : if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
699 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
700 : return 0;
701 : }
702 0 : return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
703 : }
704 :
705 0 : static int pp_dpm_get_sclk_od(void *handle)
706 : {
707 0 : struct pp_hwmgr *hwmgr = handle;
708 :
709 0 : if (!hwmgr || !hwmgr->pm_en)
710 : return -EINVAL;
711 :
712 0 : if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
713 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
714 : return 0;
715 : }
716 0 : return hwmgr->hwmgr_func->get_sclk_od(hwmgr);
717 : }
718 :
719 0 : static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
720 : {
721 0 : struct pp_hwmgr *hwmgr = handle;
722 :
723 0 : if (!hwmgr || !hwmgr->pm_en)
724 : return -EINVAL;
725 :
726 0 : if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
727 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
728 : return 0;
729 : }
730 :
731 0 : return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
732 : }
733 :
734 0 : static int pp_dpm_get_mclk_od(void *handle)
735 : {
736 0 : struct pp_hwmgr *hwmgr = handle;
737 :
738 0 : if (!hwmgr || !hwmgr->pm_en)
739 : return -EINVAL;
740 :
741 0 : if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
742 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
743 : return 0;
744 : }
745 0 : return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
746 : }
747 :
748 0 : static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
749 : {
750 0 : struct pp_hwmgr *hwmgr = handle;
751 :
752 0 : if (!hwmgr || !hwmgr->pm_en)
753 : return -EINVAL;
754 :
755 0 : if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
756 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
757 : return 0;
758 : }
759 0 : return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
760 : }
761 :
762 0 : static int pp_dpm_read_sensor(void *handle, int idx,
763 : void *value, int *size)
764 : {
765 0 : struct pp_hwmgr *hwmgr = handle;
766 :
767 0 : if (!hwmgr || !hwmgr->pm_en || !value)
768 : return -EINVAL;
769 :
770 0 : switch (idx) {
771 : case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
772 0 : *((uint32_t *)value) = hwmgr->pstate_sclk;
773 0 : return 0;
774 : case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
775 0 : *((uint32_t *)value) = hwmgr->pstate_mclk;
776 0 : return 0;
777 : case AMDGPU_PP_SENSOR_MIN_FAN_RPM:
778 0 : *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM;
779 0 : return 0;
780 : case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
781 0 : *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
782 0 : return 0;
783 : default:
784 0 : return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
785 : }
786 : }
787 :
788 : static struct amd_vce_state*
789 0 : pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
790 : {
791 0 : struct pp_hwmgr *hwmgr = handle;
792 :
793 0 : if (!hwmgr || !hwmgr->pm_en)
794 : return NULL;
795 :
796 0 : if (idx < hwmgr->num_vce_state_tables)
797 0 : return &hwmgr->vce_states[idx];
798 : return NULL;
799 : }
800 :
801 0 : static int pp_get_power_profile_mode(void *handle, char *buf)
802 : {
803 0 : struct pp_hwmgr *hwmgr = handle;
804 :
805 0 : if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->get_power_profile_mode)
806 : return -EOPNOTSUPP;
807 0 : if (!buf)
808 : return -EINVAL;
809 :
810 0 : return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
811 : }
812 :
813 0 : static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
814 : {
815 0 : struct pp_hwmgr *hwmgr = handle;
816 :
817 0 : if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->set_power_profile_mode)
818 : return -EOPNOTSUPP;
819 :
820 0 : if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
821 : pr_debug("power profile setting is for manual dpm mode only.\n");
822 : return -EINVAL;
823 : }
824 :
825 0 : return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
826 : }
827 :
828 0 : static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size)
829 : {
830 0 : struct pp_hwmgr *hwmgr = handle;
831 :
832 0 : if (!hwmgr || !hwmgr->pm_en)
833 : return -EINVAL;
834 :
835 0 : if (hwmgr->hwmgr_func->set_fine_grain_clk_vol == NULL)
836 : return 0;
837 :
838 0 : return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size);
839 : }
840 :
841 0 : static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
842 : {
843 0 : struct pp_hwmgr *hwmgr = handle;
844 :
845 0 : if (!hwmgr || !hwmgr->pm_en)
846 : return -EINVAL;
847 :
848 0 : if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {
849 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
850 : return 0;
851 : }
852 :
853 0 : return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
854 : }
855 :
856 0 : static int pp_dpm_set_mp1_state(void *handle, enum pp_mp1_state mp1_state)
857 : {
858 0 : struct pp_hwmgr *hwmgr = handle;
859 :
860 0 : if (!hwmgr)
861 : return -EINVAL;
862 :
863 0 : if (!hwmgr->pm_en)
864 : return 0;
865 :
866 0 : if (hwmgr->hwmgr_func->set_mp1_state)
867 0 : return hwmgr->hwmgr_func->set_mp1_state(hwmgr, mp1_state);
868 :
869 : return 0;
870 : }
871 :
872 0 : static int pp_dpm_switch_power_profile(void *handle,
873 : enum PP_SMC_POWER_PROFILE type, bool en)
874 : {
875 0 : struct pp_hwmgr *hwmgr = handle;
876 : long workload;
877 : uint32_t index;
878 :
879 0 : if (!hwmgr || !hwmgr->pm_en)
880 : return -EINVAL;
881 :
882 0 : if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
883 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
884 : return -EINVAL;
885 : }
886 :
887 0 : if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
888 : return -EINVAL;
889 :
890 0 : if (!en) {
891 0 : hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
892 0 : index = fls(hwmgr->workload_mask);
893 0 : index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
894 0 : workload = hwmgr->workload_setting[index];
895 : } else {
896 0 : hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
897 0 : index = fls(hwmgr->workload_mask);
898 0 : index = index <= Workload_Policy_Max ? index - 1 : 0;
899 0 : workload = hwmgr->workload_setting[index];
900 : }
901 :
902 0 : if (type == PP_SMC_POWER_PROFILE_COMPUTE &&
903 0 : hwmgr->hwmgr_func->disable_power_features_for_compute_performance) {
904 0 : if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en))
905 : return -EINVAL;
906 : }
907 :
908 0 : if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
909 0 : hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
910 :
911 : return 0;
912 : }
913 :
914 0 : static int pp_set_power_limit(void *handle, uint32_t limit)
915 : {
916 0 : struct pp_hwmgr *hwmgr = handle;
917 : uint32_t max_power_limit;
918 :
919 0 : if (!hwmgr || !hwmgr->pm_en)
920 : return -EINVAL;
921 :
922 0 : if (hwmgr->hwmgr_func->set_power_limit == NULL) {
923 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
924 : return -EINVAL;
925 : }
926 :
927 0 : if (limit == 0)
928 0 : limit = hwmgr->default_power_limit;
929 :
930 0 : max_power_limit = hwmgr->default_power_limit;
931 0 : if (hwmgr->od_enabled) {
932 0 : max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
933 0 : max_power_limit /= 100;
934 : }
935 :
936 0 : if (limit > max_power_limit)
937 : return -EINVAL;
938 :
939 0 : hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
940 0 : hwmgr->power_limit = limit;
941 0 : return 0;
942 : }
943 :
944 0 : static int pp_get_power_limit(void *handle, uint32_t *limit,
945 : enum pp_power_limit_level pp_limit_level,
946 : enum pp_power_type power_type)
947 : {
948 0 : struct pp_hwmgr *hwmgr = handle;
949 0 : int ret = 0;
950 :
951 0 : if (!hwmgr || !hwmgr->pm_en ||!limit)
952 : return -EINVAL;
953 :
954 0 : if (power_type != PP_PWR_TYPE_SUSTAINED)
955 : return -EOPNOTSUPP;
956 :
957 0 : switch (pp_limit_level) {
958 : case PP_PWR_LIMIT_CURRENT:
959 0 : *limit = hwmgr->power_limit;
960 0 : break;
961 : case PP_PWR_LIMIT_DEFAULT:
962 0 : *limit = hwmgr->default_power_limit;
963 0 : break;
964 : case PP_PWR_LIMIT_MAX:
965 0 : *limit = hwmgr->default_power_limit;
966 0 : if (hwmgr->od_enabled) {
967 0 : *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
968 0 : *limit /= 100;
969 : }
970 : break;
971 : default:
972 : ret = -EOPNOTSUPP;
973 : break;
974 : }
975 :
976 : return ret;
977 : }
978 :
979 0 : static int pp_display_configuration_change(void *handle,
980 : const struct amd_pp_display_configuration *display_config)
981 : {
982 0 : struct pp_hwmgr *hwmgr = handle;
983 :
984 0 : if (!hwmgr || !hwmgr->pm_en)
985 : return -EINVAL;
986 :
987 0 : phm_store_dal_configuration_data(hwmgr, display_config);
988 0 : return 0;
989 : }
990 :
991 0 : static int pp_get_display_power_level(void *handle,
992 : struct amd_pp_simple_clock_info *output)
993 : {
994 0 : struct pp_hwmgr *hwmgr = handle;
995 :
996 0 : if (!hwmgr || !hwmgr->pm_en ||!output)
997 : return -EINVAL;
998 :
999 0 : return phm_get_dal_power_level(hwmgr, output);
1000 : }
1001 :
1002 0 : static int pp_get_current_clocks(void *handle,
1003 : struct amd_pp_clock_info *clocks)
1004 : {
1005 0 : struct amd_pp_simple_clock_info simple_clocks = { 0 };
1006 : struct pp_clock_info hw_clocks;
1007 0 : struct pp_hwmgr *hwmgr = handle;
1008 0 : int ret = 0;
1009 :
1010 0 : if (!hwmgr || !hwmgr->pm_en)
1011 : return -EINVAL;
1012 :
1013 0 : phm_get_dal_power_level(hwmgr, &simple_clocks);
1014 :
1015 0 : if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1016 : PHM_PlatformCaps_PowerContainment))
1017 0 : ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1018 : &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1019 : else
1020 0 : ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1021 : &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1022 :
1023 0 : if (ret) {
1024 : pr_debug("Error in phm_get_clock_info \n");
1025 : return -EINVAL;
1026 : }
1027 :
1028 0 : clocks->min_engine_clock = hw_clocks.min_eng_clk;
1029 0 : clocks->max_engine_clock = hw_clocks.max_eng_clk;
1030 0 : clocks->min_memory_clock = hw_clocks.min_mem_clk;
1031 0 : clocks->max_memory_clock = hw_clocks.max_mem_clk;
1032 0 : clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1033 0 : clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1034 :
1035 0 : clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1036 0 : clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1037 :
1038 0 : if (simple_clocks.level == 0)
1039 0 : clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;
1040 : else
1041 0 : clocks->max_clocks_state = simple_clocks.level;
1042 :
1043 0 : if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1044 0 : clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1045 0 : clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1046 : }
1047 : return 0;
1048 : }
1049 :
1050 0 : static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1051 : {
1052 0 : struct pp_hwmgr *hwmgr = handle;
1053 :
1054 0 : if (!hwmgr || !hwmgr->pm_en)
1055 : return -EINVAL;
1056 :
1057 0 : if (clocks == NULL)
1058 : return -EINVAL;
1059 :
1060 0 : return phm_get_clock_by_type(hwmgr, type, clocks);
1061 : }
1062 :
1063 0 : static int pp_get_clock_by_type_with_latency(void *handle,
1064 : enum amd_pp_clock_type type,
1065 : struct pp_clock_levels_with_latency *clocks)
1066 : {
1067 0 : struct pp_hwmgr *hwmgr = handle;
1068 :
1069 0 : if (!hwmgr || !hwmgr->pm_en ||!clocks)
1070 : return -EINVAL;
1071 :
1072 0 : return phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1073 : }
1074 :
1075 0 : static int pp_get_clock_by_type_with_voltage(void *handle,
1076 : enum amd_pp_clock_type type,
1077 : struct pp_clock_levels_with_voltage *clocks)
1078 : {
1079 0 : struct pp_hwmgr *hwmgr = handle;
1080 :
1081 0 : if (!hwmgr || !hwmgr->pm_en ||!clocks)
1082 : return -EINVAL;
1083 :
1084 0 : return phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1085 : }
1086 :
1087 0 : static int pp_set_watermarks_for_clocks_ranges(void *handle,
1088 : void *clock_ranges)
1089 : {
1090 0 : struct pp_hwmgr *hwmgr = handle;
1091 :
1092 0 : if (!hwmgr || !hwmgr->pm_en || !clock_ranges)
1093 : return -EINVAL;
1094 :
1095 0 : return phm_set_watermarks_for_clocks_ranges(hwmgr,
1096 : clock_ranges);
1097 : }
1098 :
1099 0 : static int pp_display_clock_voltage_request(void *handle,
1100 : struct pp_display_clock_request *clock)
1101 : {
1102 0 : struct pp_hwmgr *hwmgr = handle;
1103 :
1104 0 : if (!hwmgr || !hwmgr->pm_en ||!clock)
1105 : return -EINVAL;
1106 :
1107 0 : return phm_display_clock_voltage_request(hwmgr, clock);
1108 : }
1109 :
1110 0 : static int pp_get_display_mode_validation_clocks(void *handle,
1111 : struct amd_pp_simple_clock_info *clocks)
1112 : {
1113 0 : struct pp_hwmgr *hwmgr = handle;
1114 0 : int ret = 0;
1115 :
1116 0 : if (!hwmgr || !hwmgr->pm_en ||!clocks)
1117 : return -EINVAL;
1118 :
1119 0 : clocks->level = PP_DAL_POWERLEVEL_7;
1120 :
1121 0 : if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1122 0 : ret = phm_get_max_high_clocks(hwmgr, clocks);
1123 :
1124 : return ret;
1125 : }
1126 :
1127 0 : static int pp_dpm_powergate_mmhub(void *handle)
1128 : {
1129 0 : struct pp_hwmgr *hwmgr = handle;
1130 :
1131 0 : if (!hwmgr || !hwmgr->pm_en)
1132 : return -EINVAL;
1133 :
1134 0 : if (hwmgr->hwmgr_func->powergate_mmhub == NULL) {
1135 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1136 : return 0;
1137 : }
1138 :
1139 0 : return hwmgr->hwmgr_func->powergate_mmhub(hwmgr);
1140 : }
1141 :
1142 0 : static int pp_dpm_powergate_gfx(void *handle, bool gate)
1143 : {
1144 0 : struct pp_hwmgr *hwmgr = handle;
1145 :
1146 0 : if (!hwmgr || !hwmgr->pm_en)
1147 : return 0;
1148 :
1149 0 : if (hwmgr->hwmgr_func->powergate_gfx == NULL) {
1150 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1151 : return 0;
1152 : }
1153 :
1154 0 : return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate);
1155 : }
1156 :
1157 0 : static void pp_dpm_powergate_acp(void *handle, bool gate)
1158 : {
1159 0 : struct pp_hwmgr *hwmgr = handle;
1160 :
1161 0 : if (!hwmgr || !hwmgr->pm_en)
1162 : return;
1163 :
1164 0 : if (hwmgr->hwmgr_func->powergate_acp == NULL) {
1165 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1166 : return;
1167 : }
1168 :
1169 0 : hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);
1170 : }
1171 :
1172 0 : static void pp_dpm_powergate_sdma(void *handle, bool gate)
1173 : {
1174 0 : struct pp_hwmgr *hwmgr = handle;
1175 :
1176 0 : if (!hwmgr)
1177 : return;
1178 :
1179 0 : if (hwmgr->hwmgr_func->powergate_sdma == NULL) {
1180 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1181 : return;
1182 : }
1183 :
1184 0 : hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);
1185 : }
1186 :
1187 0 : static int pp_set_powergating_by_smu(void *handle,
1188 : uint32_t block_type, bool gate)
1189 : {
1190 0 : int ret = 0;
1191 :
1192 0 : switch (block_type) {
1193 : case AMD_IP_BLOCK_TYPE_UVD:
1194 : case AMD_IP_BLOCK_TYPE_VCN:
1195 0 : pp_dpm_powergate_uvd(handle, gate);
1196 0 : break;
1197 : case AMD_IP_BLOCK_TYPE_VCE:
1198 0 : pp_dpm_powergate_vce(handle, gate);
1199 0 : break;
1200 : case AMD_IP_BLOCK_TYPE_GMC:
1201 : /*
1202 : * For now, this is only used on PICASSO.
1203 : * And only "gate" operation is supported.
1204 : */
1205 0 : if (gate)
1206 0 : pp_dpm_powergate_mmhub(handle);
1207 : break;
1208 : case AMD_IP_BLOCK_TYPE_GFX:
1209 0 : ret = pp_dpm_powergate_gfx(handle, gate);
1210 0 : break;
1211 : case AMD_IP_BLOCK_TYPE_ACP:
1212 0 : pp_dpm_powergate_acp(handle, gate);
1213 0 : break;
1214 : case AMD_IP_BLOCK_TYPE_SDMA:
1215 0 : pp_dpm_powergate_sdma(handle, gate);
1216 0 : break;
1217 : default:
1218 : break;
1219 : }
1220 0 : return ret;
1221 : }
1222 :
1223 0 : static int pp_notify_smu_enable_pwe(void *handle)
1224 : {
1225 0 : struct pp_hwmgr *hwmgr = handle;
1226 :
1227 0 : if (!hwmgr || !hwmgr->pm_en)
1228 : return -EINVAL;
1229 :
1230 0 : if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) {
1231 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1232 : return -EINVAL;
1233 : }
1234 :
1235 0 : hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);
1236 :
1237 0 : return 0;
1238 : }
1239 :
1240 0 : static int pp_enable_mgpu_fan_boost(void *handle)
1241 : {
1242 0 : struct pp_hwmgr *hwmgr = handle;
1243 :
1244 0 : if (!hwmgr)
1245 : return -EINVAL;
1246 :
1247 0 : if (!hwmgr->pm_en ||
1248 0 : hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL)
1249 : return 0;
1250 :
1251 0 : hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);
1252 :
1253 0 : return 0;
1254 : }
1255 :
1256 0 : static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock)
1257 : {
1258 0 : struct pp_hwmgr *hwmgr = handle;
1259 :
1260 0 : if (!hwmgr || !hwmgr->pm_en)
1261 : return -EINVAL;
1262 :
1263 0 : if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) {
1264 : pr_debug("%s was not implemented.\n", __func__);
1265 : return -EINVAL;
1266 : }
1267 :
1268 0 : hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock);
1269 :
1270 0 : return 0;
1271 : }
1272 :
1273 0 : static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock)
1274 : {
1275 0 : struct pp_hwmgr *hwmgr = handle;
1276 :
1277 0 : if (!hwmgr || !hwmgr->pm_en)
1278 : return -EINVAL;
1279 :
1280 0 : if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) {
1281 : pr_debug("%s was not implemented.\n", __func__);
1282 : return -EINVAL;
1283 : }
1284 :
1285 0 : hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock);
1286 :
1287 0 : return 0;
1288 : }
1289 :
1290 0 : static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock)
1291 : {
1292 0 : struct pp_hwmgr *hwmgr = handle;
1293 :
1294 0 : if (!hwmgr || !hwmgr->pm_en)
1295 : return -EINVAL;
1296 :
1297 0 : if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) {
1298 : pr_debug("%s was not implemented.\n", __func__);
1299 : return -EINVAL;
1300 : }
1301 :
1302 0 : hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock);
1303 :
1304 0 : return 0;
1305 : }
1306 :
1307 0 : static int pp_set_active_display_count(void *handle, uint32_t count)
1308 : {
1309 0 : struct pp_hwmgr *hwmgr = handle;
1310 :
1311 0 : if (!hwmgr || !hwmgr->pm_en)
1312 : return -EINVAL;
1313 :
1314 0 : return phm_set_active_display_count(hwmgr, count);
1315 : }
1316 :
1317 0 : static int pp_get_asic_baco_capability(void *handle, bool *cap)
1318 : {
1319 0 : struct pp_hwmgr *hwmgr = handle;
1320 :
1321 0 : *cap = false;
1322 0 : if (!hwmgr)
1323 : return -EINVAL;
1324 :
1325 0 : if (!(hwmgr->not_vf && amdgpu_dpm) ||
1326 0 : !hwmgr->hwmgr_func->get_asic_baco_capability)
1327 : return 0;
1328 :
1329 0 : hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap);
1330 :
1331 0 : return 0;
1332 : }
1333 :
1334 0 : static int pp_get_asic_baco_state(void *handle, int *state)
1335 : {
1336 0 : struct pp_hwmgr *hwmgr = handle;
1337 :
1338 0 : if (!hwmgr)
1339 : return -EINVAL;
1340 :
1341 0 : if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)
1342 : return 0;
1343 :
1344 0 : hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state);
1345 :
1346 0 : return 0;
1347 : }
1348 :
1349 0 : static int pp_set_asic_baco_state(void *handle, int state)
1350 : {
1351 0 : struct pp_hwmgr *hwmgr = handle;
1352 :
1353 0 : if (!hwmgr)
1354 : return -EINVAL;
1355 :
1356 0 : if (!(hwmgr->not_vf && amdgpu_dpm) ||
1357 0 : !hwmgr->hwmgr_func->set_asic_baco_state)
1358 : return 0;
1359 :
1360 0 : hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state);
1361 :
1362 0 : return 0;
1363 : }
1364 :
1365 0 : static int pp_get_ppfeature_status(void *handle, char *buf)
1366 : {
1367 0 : struct pp_hwmgr *hwmgr = handle;
1368 :
1369 0 : if (!hwmgr || !hwmgr->pm_en || !buf)
1370 : return -EINVAL;
1371 :
1372 0 : if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {
1373 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1374 : return -EINVAL;
1375 : }
1376 :
1377 0 : return hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);
1378 : }
1379 :
1380 0 : static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)
1381 : {
1382 0 : struct pp_hwmgr *hwmgr = handle;
1383 :
1384 0 : if (!hwmgr || !hwmgr->pm_en)
1385 : return -EINVAL;
1386 :
1387 0 : if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {
1388 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1389 : return -EINVAL;
1390 : }
1391 :
1392 0 : return hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);
1393 : }
1394 :
1395 0 : static int pp_asic_reset_mode_2(void *handle)
1396 : {
1397 0 : struct pp_hwmgr *hwmgr = handle;
1398 :
1399 0 : if (!hwmgr || !hwmgr->pm_en)
1400 : return -EINVAL;
1401 :
1402 0 : if (hwmgr->hwmgr_func->asic_reset == NULL) {
1403 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1404 : return -EINVAL;
1405 : }
1406 :
1407 0 : return hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2);
1408 : }
1409 :
1410 0 : static int pp_smu_i2c_bus_access(void *handle, bool acquire)
1411 : {
1412 0 : struct pp_hwmgr *hwmgr = handle;
1413 :
1414 0 : if (!hwmgr || !hwmgr->pm_en)
1415 : return -EINVAL;
1416 :
1417 0 : if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) {
1418 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1419 : return -EINVAL;
1420 : }
1421 :
1422 0 : return hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire);
1423 : }
1424 :
1425 0 : static int pp_set_df_cstate(void *handle, enum pp_df_cstate state)
1426 : {
1427 0 : struct pp_hwmgr *hwmgr = handle;
1428 :
1429 0 : if (!hwmgr)
1430 : return -EINVAL;
1431 :
1432 0 : if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate)
1433 : return 0;
1434 :
1435 0 : hwmgr->hwmgr_func->set_df_cstate(hwmgr, state);
1436 :
1437 0 : return 0;
1438 : }
1439 :
1440 0 : static int pp_set_xgmi_pstate(void *handle, uint32_t pstate)
1441 : {
1442 0 : struct pp_hwmgr *hwmgr = handle;
1443 :
1444 0 : if (!hwmgr)
1445 : return -EINVAL;
1446 :
1447 0 : if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate)
1448 : return 0;
1449 :
1450 0 : hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate);
1451 :
1452 0 : return 0;
1453 : }
1454 :
1455 0 : static ssize_t pp_get_gpu_metrics(void *handle, void **table)
1456 : {
1457 0 : struct pp_hwmgr *hwmgr = handle;
1458 :
1459 0 : if (!hwmgr)
1460 : return -EINVAL;
1461 :
1462 0 : if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics)
1463 : return -EOPNOTSUPP;
1464 :
1465 0 : return hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table);
1466 : }
1467 :
1468 0 : static int pp_gfx_state_change_set(void *handle, uint32_t state)
1469 : {
1470 0 : struct pp_hwmgr *hwmgr = handle;
1471 :
1472 0 : if (!hwmgr || !hwmgr->pm_en)
1473 : return -EINVAL;
1474 :
1475 0 : if (hwmgr->hwmgr_func->gfx_state_change == NULL) {
1476 0 : pr_info_ratelimited("%s was not implemented.\n", __func__);
1477 : return -EINVAL;
1478 : }
1479 :
1480 0 : hwmgr->hwmgr_func->gfx_state_change(hwmgr, state);
1481 0 : return 0;
1482 : }
1483 :
1484 0 : static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size)
1485 : {
1486 0 : struct pp_hwmgr *hwmgr = handle;
1487 0 : struct amdgpu_device *adev = hwmgr->adev;
1488 :
1489 0 : if (!addr || !size)
1490 : return -EINVAL;
1491 :
1492 0 : *addr = NULL;
1493 0 : *size = 0;
1494 0 : if (adev->pm.smu_prv_buffer) {
1495 0 : amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr);
1496 0 : *size = adev->pm.smu_prv_buffer_size;
1497 : }
1498 :
1499 : return 0;
1500 : }
1501 :
1502 0 : static void pp_pm_compute_clocks(void *handle)
1503 : {
1504 0 : struct pp_hwmgr *hwmgr = handle;
1505 0 : struct amdgpu_device *adev = hwmgr->adev;
1506 :
1507 0 : if (!amdgpu_device_has_dc_support(adev)) {
1508 0 : amdgpu_dpm_get_active_displays(adev);
1509 0 : adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;
1510 0 : adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);
1511 0 : adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev);
1512 : /* we have issues with mclk switching with
1513 : * refresh rates over 120 hz on the non-DC code.
1514 : */
1515 0 : if (adev->pm.pm_display_cfg.vrefresh > 120)
1516 0 : adev->pm.pm_display_cfg.min_vblank_time = 0;
1517 :
1518 : pp_display_configuration_change(handle,
1519 0 : &adev->pm.pm_display_cfg);
1520 : }
1521 :
1522 0 : pp_dpm_dispatch_tasks(handle,
1523 : AMD_PP_TASK_DISPLAY_CONFIG_CHANGE,
1524 : NULL);
1525 0 : }
1526 :
1527 : static const struct amd_pm_funcs pp_dpm_funcs = {
1528 : .load_firmware = pp_dpm_load_fw,
1529 : .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1530 : .force_performance_level = pp_dpm_force_performance_level,
1531 : .get_performance_level = pp_dpm_get_performance_level,
1532 : .get_current_power_state = pp_dpm_get_current_power_state,
1533 : .dispatch_tasks = pp_dpm_dispatch_tasks,
1534 : .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1535 : .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1536 : .set_fan_speed_pwm = pp_dpm_set_fan_speed_pwm,
1537 : .get_fan_speed_pwm = pp_dpm_get_fan_speed_pwm,
1538 : .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1539 : .set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,
1540 : .get_pp_num_states = pp_dpm_get_pp_num_states,
1541 : .get_pp_table = pp_dpm_get_pp_table,
1542 : .set_pp_table = pp_dpm_set_pp_table,
1543 : .force_clock_level = pp_dpm_force_clock_level,
1544 : .emit_clock_levels = pp_dpm_emit_clock_levels,
1545 : .print_clock_levels = pp_dpm_print_clock_levels,
1546 : .get_sclk_od = pp_dpm_get_sclk_od,
1547 : .set_sclk_od = pp_dpm_set_sclk_od,
1548 : .get_mclk_od = pp_dpm_get_mclk_od,
1549 : .set_mclk_od = pp_dpm_set_mclk_od,
1550 : .read_sensor = pp_dpm_read_sensor,
1551 : .get_vce_clock_state = pp_dpm_get_vce_clock_state,
1552 : .switch_power_profile = pp_dpm_switch_power_profile,
1553 : .set_clockgating_by_smu = pp_set_clockgating_by_smu,
1554 : .set_powergating_by_smu = pp_set_powergating_by_smu,
1555 : .get_power_profile_mode = pp_get_power_profile_mode,
1556 : .set_power_profile_mode = pp_set_power_profile_mode,
1557 : .set_fine_grain_clk_vol = pp_set_fine_grain_clk_vol,
1558 : .odn_edit_dpm_table = pp_odn_edit_dpm_table,
1559 : .set_mp1_state = pp_dpm_set_mp1_state,
1560 : .set_power_limit = pp_set_power_limit,
1561 : .get_power_limit = pp_get_power_limit,
1562 : /* export to DC */
1563 : .get_sclk = pp_dpm_get_sclk,
1564 : .get_mclk = pp_dpm_get_mclk,
1565 : .display_configuration_change = pp_display_configuration_change,
1566 : .get_display_power_level = pp_get_display_power_level,
1567 : .get_current_clocks = pp_get_current_clocks,
1568 : .get_clock_by_type = pp_get_clock_by_type,
1569 : .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
1570 : .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
1571 : .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
1572 : .display_clock_voltage_request = pp_display_clock_voltage_request,
1573 : .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
1574 : .notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
1575 : .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,
1576 : .set_active_display_count = pp_set_active_display_count,
1577 : .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk,
1578 : .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq,
1579 : .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq,
1580 : .get_asic_baco_capability = pp_get_asic_baco_capability,
1581 : .get_asic_baco_state = pp_get_asic_baco_state,
1582 : .set_asic_baco_state = pp_set_asic_baco_state,
1583 : .get_ppfeature_status = pp_get_ppfeature_status,
1584 : .set_ppfeature_status = pp_set_ppfeature_status,
1585 : .asic_reset_mode_2 = pp_asic_reset_mode_2,
1586 : .smu_i2c_bus_access = pp_smu_i2c_bus_access,
1587 : .set_df_cstate = pp_set_df_cstate,
1588 : .set_xgmi_pstate = pp_set_xgmi_pstate,
1589 : .get_gpu_metrics = pp_get_gpu_metrics,
1590 : .gfx_state_change_set = pp_gfx_state_change_set,
1591 : .get_smu_prv_buf_details = pp_get_prv_buffer_details,
1592 : .pm_compute_clocks = pp_pm_compute_clocks,
1593 : };
|