1e098bc96SEvan Quan /*
2e098bc96SEvan Quan * Copyright 2015 Advanced Micro Devices, Inc.
3e098bc96SEvan Quan *
4e098bc96SEvan Quan * Permission is hereby granted, free of charge, to any person obtaining a
5e098bc96SEvan Quan * copy of this software and associated documentation files (the "Software"),
6e098bc96SEvan Quan * to deal in the Software without restriction, including without limitation
7e098bc96SEvan Quan * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e098bc96SEvan Quan * and/or sell copies of the Software, and to permit persons to whom the
9e098bc96SEvan Quan * Software is furnished to do so, subject to the following conditions:
10e098bc96SEvan Quan *
11e098bc96SEvan Quan * The above copyright notice and this permission notice shall be included in
12e098bc96SEvan Quan * all copies or substantial portions of the Software.
13e098bc96SEvan Quan *
14e098bc96SEvan Quan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e098bc96SEvan Quan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e098bc96SEvan Quan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17e098bc96SEvan Quan * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18e098bc96SEvan Quan * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19e098bc96SEvan Quan * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20e098bc96SEvan Quan * OTHER DEALINGS IN THE SOFTWARE.
21e098bc96SEvan Quan *
22e098bc96SEvan Quan */
23e098bc96SEvan Quan #include "pp_debug.h"
24e098bc96SEvan Quan #include <linux/types.h>
25e098bc96SEvan Quan #include <linux/kernel.h>
26e098bc96SEvan Quan #include <linux/gfp.h>
27e098bc96SEvan Quan #include <linux/slab.h>
28e098bc96SEvan Quan #include <linux/firmware.h>
29b75efe88SEvan Quan #include <linux/reboot.h>
30e098bc96SEvan Quan #include "amd_shared.h"
31e098bc96SEvan Quan #include "amd_powerplay.h"
32e098bc96SEvan Quan #include "power_state.h"
33e098bc96SEvan Quan #include "amdgpu.h"
34e098bc96SEvan Quan #include "hwmgr.h"
356ddbd37fSEvan Quan #include "amdgpu_dpm_internal.h"
366ddbd37fSEvan Quan #include "amdgpu_display.h"
37e098bc96SEvan Quan
38e098bc96SEvan Quan static const struct amd_pm_funcs pp_dpm_funcs;
39e098bc96SEvan Quan
amd_powerplay_create(struct amdgpu_device * adev)40e098bc96SEvan Quan static int amd_powerplay_create(struct amdgpu_device *adev)
41e098bc96SEvan Quan {
42e098bc96SEvan Quan struct pp_hwmgr *hwmgr;
43e098bc96SEvan Quan
44e098bc96SEvan Quan if (adev == NULL)
45e098bc96SEvan Quan return -EINVAL;
46e098bc96SEvan Quan
47e098bc96SEvan Quan hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL);
48e098bc96SEvan Quan if (hwmgr == NULL)
49e098bc96SEvan Quan return -ENOMEM;
50e098bc96SEvan Quan
51e098bc96SEvan Quan hwmgr->adev = adev;
52e098bc96SEvan Quan hwmgr->not_vf = !amdgpu_sriov_vf(adev);
53e098bc96SEvan Quan hwmgr->device = amdgpu_cgs_create_device(adev);
54e098bc96SEvan Quan mutex_init(&hwmgr->msg_lock);
55e098bc96SEvan Quan hwmgr->chip_family = adev->family;
56e098bc96SEvan Quan hwmgr->chip_id = adev->asic_type;
57e098bc96SEvan Quan hwmgr->feature_mask = adev->pm.pp_feature;
58e098bc96SEvan Quan hwmgr->display_config = &adev->pm.pm_display_cfg;
59e098bc96SEvan Quan adev->powerplay.pp_handle = hwmgr;
60e098bc96SEvan Quan adev->powerplay.pp_funcs = &pp_dpm_funcs;
61e098bc96SEvan Quan return 0;
62e098bc96SEvan Quan }
63e098bc96SEvan Quan
64e098bc96SEvan Quan
amd_powerplay_destroy(struct amdgpu_device * adev)65e098bc96SEvan Quan static void amd_powerplay_destroy(struct amdgpu_device *adev)
66e098bc96SEvan Quan {
67e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
68e098bc96SEvan Quan
69e098bc96SEvan Quan mutex_destroy(&hwmgr->msg_lock);
70e098bc96SEvan Quan
71e098bc96SEvan Quan kfree(hwmgr->hardcode_pp_table);
72e098bc96SEvan Quan hwmgr->hardcode_pp_table = NULL;
73e098bc96SEvan Quan
74e098bc96SEvan Quan kfree(hwmgr);
75e098bc96SEvan Quan hwmgr = NULL;
76e098bc96SEvan Quan }
77e098bc96SEvan Quan
pp_early_init(void * handle)78e098bc96SEvan Quan static int pp_early_init(void *handle)
79e098bc96SEvan Quan {
80e098bc96SEvan Quan int ret;
81e098bc96SEvan Quan struct amdgpu_device *adev = handle;
82e098bc96SEvan Quan
83e098bc96SEvan Quan ret = amd_powerplay_create(adev);
84e098bc96SEvan Quan
85e098bc96SEvan Quan if (ret != 0)
86e098bc96SEvan Quan return ret;
87e098bc96SEvan Quan
88e098bc96SEvan Quan ret = hwmgr_early_init(adev->powerplay.pp_handle);
89e098bc96SEvan Quan if (ret)
90e098bc96SEvan Quan return -EINVAL;
91e098bc96SEvan Quan
92e098bc96SEvan Quan return 0;
93e098bc96SEvan Quan }
94e098bc96SEvan Quan
pp_swctf_delayed_work_handler(struct work_struct * work)95b75efe88SEvan Quan static void pp_swctf_delayed_work_handler(struct work_struct *work)
96b75efe88SEvan Quan {
97b75efe88SEvan Quan struct pp_hwmgr *hwmgr =
98b75efe88SEvan Quan container_of(work, struct pp_hwmgr, swctf_delayed_work.work);
99b75efe88SEvan Quan struct amdgpu_device *adev = hwmgr->adev;
100b75efe88SEvan Quan struct amdgpu_dpm_thermal *range =
101b75efe88SEvan Quan &adev->pm.dpm.thermal;
102*fc0cb02eSJesse Zhang uint32_t gpu_temperature, size = sizeof(gpu_temperature);
103b75efe88SEvan Quan int ret;
104b75efe88SEvan Quan
105b75efe88SEvan Quan /*
106b75efe88SEvan Quan * If the hotspot/edge temperature is confirmed as below SW CTF setting point
107b75efe88SEvan Quan * after the delay enforced, nothing will be done.
108b75efe88SEvan Quan * Otherwise, a graceful shutdown will be performed to prevent further damage.
109b75efe88SEvan Quan */
110b75efe88SEvan Quan if (range->sw_ctf_threshold &&
111b75efe88SEvan Quan hwmgr->hwmgr_func->read_sensor) {
112b75efe88SEvan Quan ret = hwmgr->hwmgr_func->read_sensor(hwmgr,
113b75efe88SEvan Quan AMDGPU_PP_SENSOR_HOTSPOT_TEMP,
114b75efe88SEvan Quan &gpu_temperature,
115b75efe88SEvan Quan &size);
116b75efe88SEvan Quan /*
117b75efe88SEvan Quan * For some legacy ASICs, hotspot temperature retrieving might be not
118b75efe88SEvan Quan * supported. Check the edge temperature instead then.
119b75efe88SEvan Quan */
120b75efe88SEvan Quan if (ret == -EOPNOTSUPP)
121b75efe88SEvan Quan ret = hwmgr->hwmgr_func->read_sensor(hwmgr,
122b75efe88SEvan Quan AMDGPU_PP_SENSOR_EDGE_TEMP,
123b75efe88SEvan Quan &gpu_temperature,
124b75efe88SEvan Quan &size);
125b75efe88SEvan Quan if (!ret && gpu_temperature / 1000 < range->sw_ctf_threshold)
126b75efe88SEvan Quan return;
127b75efe88SEvan Quan }
128b75efe88SEvan Quan
129b75efe88SEvan Quan dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
130b75efe88SEvan Quan dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
131b75efe88SEvan Quan orderly_poweroff(true);
132b75efe88SEvan Quan }
133b75efe88SEvan Quan
pp_sw_init(void * handle)134e098bc96SEvan Quan static int pp_sw_init(void *handle)
135e098bc96SEvan Quan {
136e098bc96SEvan Quan struct amdgpu_device *adev = handle;
137e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
138e098bc96SEvan Quan int ret = 0;
139e098bc96SEvan Quan
140e098bc96SEvan Quan ret = hwmgr_sw_init(hwmgr);
141e098bc96SEvan Quan
142e098bc96SEvan Quan pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully");
143e098bc96SEvan Quan
144b75efe88SEvan Quan if (!ret)
145b75efe88SEvan Quan INIT_DELAYED_WORK(&hwmgr->swctf_delayed_work,
146b75efe88SEvan Quan pp_swctf_delayed_work_handler);
147b75efe88SEvan Quan
148e098bc96SEvan Quan return ret;
149e098bc96SEvan Quan }
150e098bc96SEvan Quan
pp_sw_fini(void * handle)151e098bc96SEvan Quan static int pp_sw_fini(void *handle)
152e098bc96SEvan Quan {
153e098bc96SEvan Quan struct amdgpu_device *adev = handle;
154e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
155e098bc96SEvan Quan
156e098bc96SEvan Quan hwmgr_sw_fini(hwmgr);
157e098bc96SEvan Quan
158778af666SMario Limonciello amdgpu_ucode_release(&adev->pm.fw);
159e098bc96SEvan Quan
160e098bc96SEvan Quan return 0;
161e098bc96SEvan Quan }
162e098bc96SEvan Quan
pp_hw_init(void * handle)163e098bc96SEvan Quan static int pp_hw_init(void *handle)
164e098bc96SEvan Quan {
165e098bc96SEvan Quan int ret = 0;
166e098bc96SEvan Quan struct amdgpu_device *adev = handle;
167e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
168e098bc96SEvan Quan
169e098bc96SEvan Quan ret = hwmgr_hw_init(hwmgr);
170e098bc96SEvan Quan
171e098bc96SEvan Quan if (ret)
172e098bc96SEvan Quan pr_err("powerplay hw init failed\n");
173e098bc96SEvan Quan
174e098bc96SEvan Quan return ret;
175e098bc96SEvan Quan }
176e098bc96SEvan Quan
pp_hw_fini(void * handle)177e098bc96SEvan Quan static int pp_hw_fini(void *handle)
178e098bc96SEvan Quan {
179e098bc96SEvan Quan struct amdgpu_device *adev = handle;
180e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
181e098bc96SEvan Quan
182b75efe88SEvan Quan cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);
183b75efe88SEvan Quan
184e098bc96SEvan Quan hwmgr_hw_fini(hwmgr);
185e098bc96SEvan Quan
186e098bc96SEvan Quan return 0;
187e098bc96SEvan Quan }
188e098bc96SEvan Quan
pp_reserve_vram_for_smu(struct amdgpu_device * adev)189e098bc96SEvan Quan static void pp_reserve_vram_for_smu(struct amdgpu_device *adev)
190e098bc96SEvan Quan {
191e098bc96SEvan Quan int r = -EINVAL;
192e098bc96SEvan Quan void *cpu_ptr = NULL;
193e098bc96SEvan Quan uint64_t gpu_addr;
194e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
195e098bc96SEvan Quan
196e098bc96SEvan Quan if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size,
197e098bc96SEvan Quan PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
198e098bc96SEvan Quan &adev->pm.smu_prv_buffer,
199e098bc96SEvan Quan &gpu_addr,
200e098bc96SEvan Quan &cpu_ptr)) {
201e098bc96SEvan Quan DRM_ERROR("amdgpu: failed to create smu prv buffer\n");
202e098bc96SEvan Quan return;
203e098bc96SEvan Quan }
204e098bc96SEvan Quan
205e098bc96SEvan Quan if (hwmgr->hwmgr_func->notify_cac_buffer_info)
206e098bc96SEvan Quan r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr,
207e098bc96SEvan Quan lower_32_bits((unsigned long)cpu_ptr),
208e098bc96SEvan Quan upper_32_bits((unsigned long)cpu_ptr),
209e098bc96SEvan Quan lower_32_bits(gpu_addr),
210e098bc96SEvan Quan upper_32_bits(gpu_addr),
211e098bc96SEvan Quan adev->pm.smu_prv_buffer_size);
212e098bc96SEvan Quan
213e098bc96SEvan Quan if (r) {
214e098bc96SEvan Quan amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
215e098bc96SEvan Quan adev->pm.smu_prv_buffer = NULL;
216e098bc96SEvan Quan DRM_ERROR("amdgpu: failed to notify SMU buffer address\n");
217e098bc96SEvan Quan }
218e098bc96SEvan Quan }
219e098bc96SEvan Quan
pp_late_init(void * handle)220e098bc96SEvan Quan static int pp_late_init(void *handle)
221e098bc96SEvan Quan {
222e098bc96SEvan Quan struct amdgpu_device *adev = handle;
223e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
224e098bc96SEvan Quan
225a746c77eSEvan Quan if (hwmgr && hwmgr->pm_en)
226e098bc96SEvan Quan hwmgr_handle_task(hwmgr,
227e098bc96SEvan Quan AMD_PP_TASK_COMPLETE_INIT, NULL);
228e098bc96SEvan Quan if (adev->pm.smu_prv_buffer_size != 0)
229e098bc96SEvan Quan pp_reserve_vram_for_smu(adev);
230e098bc96SEvan Quan
231e098bc96SEvan Quan return 0;
232e098bc96SEvan Quan }
233e098bc96SEvan Quan
pp_late_fini(void * handle)234e098bc96SEvan Quan static void pp_late_fini(void *handle)
235e098bc96SEvan Quan {
236e098bc96SEvan Quan struct amdgpu_device *adev = handle;
237e098bc96SEvan Quan
238e098bc96SEvan Quan if (adev->pm.smu_prv_buffer)
239e098bc96SEvan Quan amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL);
240e098bc96SEvan Quan amd_powerplay_destroy(adev);
241e098bc96SEvan Quan }
242e098bc96SEvan Quan
243e098bc96SEvan Quan
pp_is_idle(void * handle)244e098bc96SEvan Quan static bool pp_is_idle(void *handle)
245e098bc96SEvan Quan {
246e098bc96SEvan Quan return false;
247e098bc96SEvan Quan }
248e098bc96SEvan Quan
pp_wait_for_idle(void * handle)249e098bc96SEvan Quan static int pp_wait_for_idle(void *handle)
250e098bc96SEvan Quan {
251e098bc96SEvan Quan return 0;
252e098bc96SEvan Quan }
253e098bc96SEvan Quan
pp_sw_reset(void * handle)254e098bc96SEvan Quan static int pp_sw_reset(void *handle)
255e098bc96SEvan Quan {
256e098bc96SEvan Quan return 0;
257e098bc96SEvan Quan }
258e098bc96SEvan Quan
pp_set_powergating_state(void * handle,enum amd_powergating_state state)259e098bc96SEvan Quan static int pp_set_powergating_state(void *handle,
260e098bc96SEvan Quan enum amd_powergating_state state)
261e098bc96SEvan Quan {
262e098bc96SEvan Quan return 0;
263e098bc96SEvan Quan }
264e098bc96SEvan Quan
pp_suspend(void * handle)265e098bc96SEvan Quan static int pp_suspend(void *handle)
266e098bc96SEvan Quan {
267e098bc96SEvan Quan struct amdgpu_device *adev = handle;
268e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
269e098bc96SEvan Quan
270b75efe88SEvan Quan cancel_delayed_work_sync(&hwmgr->swctf_delayed_work);
271b75efe88SEvan Quan
272e098bc96SEvan Quan return hwmgr_suspend(hwmgr);
273e098bc96SEvan Quan }
274e098bc96SEvan Quan
pp_resume(void * handle)275e098bc96SEvan Quan static int pp_resume(void *handle)
276e098bc96SEvan Quan {
277e098bc96SEvan Quan struct amdgpu_device *adev = handle;
278e098bc96SEvan Quan struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
279e098bc96SEvan Quan
280e098bc96SEvan Quan return hwmgr_resume(hwmgr);
281e098bc96SEvan Quan }
282e098bc96SEvan Quan
pp_set_clockgating_state(void * handle,enum amd_clockgating_state state)283e098bc96SEvan Quan static int pp_set_clockgating_state(void *handle,
284e098bc96SEvan Quan enum amd_clockgating_state state)
285e098bc96SEvan Quan {
286e098bc96SEvan Quan return 0;
287e098bc96SEvan Quan }
288e098bc96SEvan Quan
289e098bc96SEvan Quan static const struct amd_ip_funcs pp_ip_funcs = {
290e098bc96SEvan Quan .name = "powerplay",
291e098bc96SEvan Quan .early_init = pp_early_init,
292e098bc96SEvan Quan .late_init = pp_late_init,
293e098bc96SEvan Quan .sw_init = pp_sw_init,
294e098bc96SEvan Quan .sw_fini = pp_sw_fini,
295e098bc96SEvan Quan .hw_init = pp_hw_init,
296e098bc96SEvan Quan .hw_fini = pp_hw_fini,
297e098bc96SEvan Quan .late_fini = pp_late_fini,
298e098bc96SEvan Quan .suspend = pp_suspend,
299e098bc96SEvan Quan .resume = pp_resume,
300e098bc96SEvan Quan .is_idle = pp_is_idle,
301e098bc96SEvan Quan .wait_for_idle = pp_wait_for_idle,
302e098bc96SEvan Quan .soft_reset = pp_sw_reset,
303e098bc96SEvan Quan .set_clockgating_state = pp_set_clockgating_state,
304e098bc96SEvan Quan .set_powergating_state = pp_set_powergating_state,
305e098bc96SEvan Quan };
306e098bc96SEvan Quan
307e098bc96SEvan Quan const struct amdgpu_ip_block_version pp_smu_ip_block =
308e098bc96SEvan Quan {
309e098bc96SEvan Quan .type = AMD_IP_BLOCK_TYPE_SMC,
310e098bc96SEvan Quan .major = 1,
311e098bc96SEvan Quan .minor = 0,
312e098bc96SEvan Quan .rev = 0,
313e098bc96SEvan Quan .funcs = &pp_ip_funcs,
314e098bc96SEvan Quan };
315e098bc96SEvan Quan
316e098bc96SEvan Quan /* This interface only be supported On Vi,
317e098bc96SEvan Quan * because only smu7/8 can help to load gfx/sdma fw,
318e098bc96SEvan Quan * smu need to be enabled before load other ip's fw.
319e098bc96SEvan Quan * so call start smu to load smu7 fw and other ip's fw
320e098bc96SEvan Quan */
pp_dpm_load_fw(void * handle)321e098bc96SEvan Quan static int pp_dpm_load_fw(void *handle)
322e098bc96SEvan Quan {
323e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
324e098bc96SEvan Quan
325e098bc96SEvan Quan if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu)
326e098bc96SEvan Quan return -EINVAL;
327e098bc96SEvan Quan
328e098bc96SEvan Quan if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {
329e098bc96SEvan Quan pr_err("fw load failed\n");
330e098bc96SEvan Quan return -EINVAL;
331e098bc96SEvan Quan }
332e098bc96SEvan Quan
333e098bc96SEvan Quan return 0;
334e098bc96SEvan Quan }
335e098bc96SEvan Quan
pp_dpm_fw_loading_complete(void * handle)336e098bc96SEvan Quan static int pp_dpm_fw_loading_complete(void *handle)
337e098bc96SEvan Quan {
338e098bc96SEvan Quan return 0;
339e098bc96SEvan Quan }
340e098bc96SEvan Quan
pp_set_clockgating_by_smu(void * handle,uint32_t msg_id)341e098bc96SEvan Quan static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
342e098bc96SEvan Quan {
343e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
344e098bc96SEvan Quan
345e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
346e098bc96SEvan Quan return -EINVAL;
347e098bc96SEvan Quan
348e098bc96SEvan Quan if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
349e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
350e098bc96SEvan Quan return 0;
351e098bc96SEvan Quan }
352e098bc96SEvan Quan
353e098bc96SEvan Quan return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
354e098bc96SEvan Quan }
355e098bc96SEvan Quan
pp_dpm_en_umd_pstate(struct pp_hwmgr * hwmgr,enum amd_dpm_forced_level * level)356e098bc96SEvan Quan static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
357e098bc96SEvan Quan enum amd_dpm_forced_level *level)
358e098bc96SEvan Quan {
359e098bc96SEvan Quan uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
360e098bc96SEvan Quan AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
361e098bc96SEvan Quan AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
362e098bc96SEvan Quan AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
363e098bc96SEvan Quan
364e098bc96SEvan Quan if (!(hwmgr->dpm_level & profile_mode_mask)) {
365e098bc96SEvan Quan /* enter umd pstate, save current level, disable gfx cg*/
366e098bc96SEvan Quan if (*level & profile_mode_mask) {
367e098bc96SEvan Quan hwmgr->saved_dpm_level = hwmgr->dpm_level;
368e098bc96SEvan Quan hwmgr->en_umd_pstate = true;
369e098bc96SEvan Quan }
370e098bc96SEvan Quan } else {
371e098bc96SEvan Quan /* exit umd pstate, restore level, enable gfx cg*/
372e098bc96SEvan Quan if (!(*level & profile_mode_mask)) {
373e098bc96SEvan Quan if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
374e098bc96SEvan Quan *level = hwmgr->saved_dpm_level;
375e098bc96SEvan Quan hwmgr->en_umd_pstate = false;
376e098bc96SEvan Quan }
377e098bc96SEvan Quan }
378e098bc96SEvan Quan }
379e098bc96SEvan Quan
pp_dpm_force_performance_level(void * handle,enum amd_dpm_forced_level level)380e098bc96SEvan Quan static int pp_dpm_force_performance_level(void *handle,
381e098bc96SEvan Quan enum amd_dpm_forced_level level)
382e098bc96SEvan Quan {
383e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
384e098bc96SEvan Quan
385e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
386e098bc96SEvan Quan return -EINVAL;
387e098bc96SEvan Quan
388e098bc96SEvan Quan if (level == hwmgr->dpm_level)
389e098bc96SEvan Quan return 0;
390e098bc96SEvan Quan
391e098bc96SEvan Quan pp_dpm_en_umd_pstate(hwmgr, &level);
392e098bc96SEvan Quan hwmgr->request_dpm_level = level;
393e098bc96SEvan Quan hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL);
394e098bc96SEvan Quan
395e098bc96SEvan Quan return 0;
396e098bc96SEvan Quan }
397e098bc96SEvan Quan
pp_dpm_get_performance_level(void * handle)398e098bc96SEvan Quan static enum amd_dpm_forced_level pp_dpm_get_performance_level(
399e098bc96SEvan Quan void *handle)
400e098bc96SEvan Quan {
401e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
402e098bc96SEvan Quan
403e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
404e098bc96SEvan Quan return -EINVAL;
405e098bc96SEvan Quan
406a746c77eSEvan Quan return hwmgr->dpm_level;
407e098bc96SEvan Quan }
408e098bc96SEvan Quan
pp_dpm_get_sclk(void * handle,bool low)409e098bc96SEvan Quan static uint32_t pp_dpm_get_sclk(void *handle, bool low)
410e098bc96SEvan Quan {
411e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
412e098bc96SEvan Quan
413e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
414e098bc96SEvan Quan return 0;
415e098bc96SEvan Quan
416e098bc96SEvan Quan if (hwmgr->hwmgr_func->get_sclk == NULL) {
417e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
418e098bc96SEvan Quan return 0;
419e098bc96SEvan Quan }
420a746c77eSEvan Quan return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
421e098bc96SEvan Quan }
422e098bc96SEvan Quan
pp_dpm_get_mclk(void * handle,bool low)423e098bc96SEvan Quan static uint32_t pp_dpm_get_mclk(void *handle, bool low)
424e098bc96SEvan Quan {
425e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
426e098bc96SEvan Quan
427e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
428e098bc96SEvan Quan return 0;
429e098bc96SEvan Quan
430e098bc96SEvan Quan if (hwmgr->hwmgr_func->get_mclk == NULL) {
431e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
432e098bc96SEvan Quan return 0;
433e098bc96SEvan Quan }
434a746c77eSEvan Quan return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
435e098bc96SEvan Quan }
436e098bc96SEvan Quan
pp_dpm_powergate_vce(void * handle,bool gate)437e098bc96SEvan Quan static void pp_dpm_powergate_vce(void *handle, bool gate)
438e098bc96SEvan Quan {
439e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
440e098bc96SEvan Quan
441e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
442e098bc96SEvan Quan return;
443e098bc96SEvan Quan
444e098bc96SEvan Quan if (hwmgr->hwmgr_func->powergate_vce == NULL) {
445e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
446e098bc96SEvan Quan return;
447e098bc96SEvan Quan }
448e098bc96SEvan Quan hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
449e098bc96SEvan Quan }
450e098bc96SEvan Quan
pp_dpm_powergate_uvd(void * handle,bool gate)451e098bc96SEvan Quan static void pp_dpm_powergate_uvd(void *handle, bool gate)
452e098bc96SEvan Quan {
453e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
454e098bc96SEvan Quan
455e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
456e098bc96SEvan Quan return;
457e098bc96SEvan Quan
458e098bc96SEvan Quan if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
459e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
460e098bc96SEvan Quan return;
461e098bc96SEvan Quan }
462e098bc96SEvan Quan hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
463e098bc96SEvan Quan }
464e098bc96SEvan Quan
pp_dpm_dispatch_tasks(void * handle,enum amd_pp_task task_id,enum amd_pm_state_type * user_state)465e098bc96SEvan Quan static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
466e098bc96SEvan Quan enum amd_pm_state_type *user_state)
467e098bc96SEvan Quan {
468e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
469e098bc96SEvan Quan
470e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
471e098bc96SEvan Quan return -EINVAL;
472e098bc96SEvan Quan
473a746c77eSEvan Quan return hwmgr_handle_task(hwmgr, task_id, user_state);
474e098bc96SEvan Quan }
475e098bc96SEvan Quan
pp_dpm_get_current_power_state(void * handle)476e098bc96SEvan Quan static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
477e098bc96SEvan Quan {
478e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
479e098bc96SEvan Quan struct pp_power_state *state;
480e098bc96SEvan Quan enum amd_pm_state_type pm_type;
481e098bc96SEvan Quan
482e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps)
483e098bc96SEvan Quan return -EINVAL;
484e098bc96SEvan Quan
485e098bc96SEvan Quan state = hwmgr->current_ps;
486e098bc96SEvan Quan
487e098bc96SEvan Quan switch (state->classification.ui_label) {
488e098bc96SEvan Quan case PP_StateUILabel_Battery:
489e098bc96SEvan Quan pm_type = POWER_STATE_TYPE_BATTERY;
490e098bc96SEvan Quan break;
491e098bc96SEvan Quan case PP_StateUILabel_Balanced:
492e098bc96SEvan Quan pm_type = POWER_STATE_TYPE_BALANCED;
493e098bc96SEvan Quan break;
494e098bc96SEvan Quan case PP_StateUILabel_Performance:
495e098bc96SEvan Quan pm_type = POWER_STATE_TYPE_PERFORMANCE;
496e098bc96SEvan Quan break;
497e098bc96SEvan Quan default:
498e098bc96SEvan Quan if (state->classification.flags & PP_StateClassificationFlag_Boot)
499e098bc96SEvan Quan pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
500e098bc96SEvan Quan else
501e098bc96SEvan Quan pm_type = POWER_STATE_TYPE_DEFAULT;
502e098bc96SEvan Quan break;
503e098bc96SEvan Quan }
504e098bc96SEvan Quan
505e098bc96SEvan Quan return pm_type;
506e098bc96SEvan Quan }
507e098bc96SEvan Quan
pp_dpm_set_fan_control_mode(void * handle,uint32_t mode)508685fae24SEvan Quan static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
509e098bc96SEvan Quan {
510e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
511e098bc96SEvan Quan
512e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
513685fae24SEvan Quan return -EOPNOTSUPP;
514e098bc96SEvan Quan
515685fae24SEvan Quan if (hwmgr->hwmgr_func->set_fan_control_mode == NULL)
516685fae24SEvan Quan return -EOPNOTSUPP;
517685fae24SEvan Quan
518685fae24SEvan Quan if (mode == U32_MAX)
519685fae24SEvan Quan return -EINVAL;
520685fae24SEvan Quan
521e098bc96SEvan Quan hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
522685fae24SEvan Quan
523685fae24SEvan Quan return 0;
524e098bc96SEvan Quan }
525e098bc96SEvan Quan
pp_dpm_get_fan_control_mode(void * handle,uint32_t * fan_mode)526685fae24SEvan Quan static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode)
527e098bc96SEvan Quan {
528e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
529e098bc96SEvan Quan
530e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
531685fae24SEvan Quan return -EOPNOTSUPP;
532e098bc96SEvan Quan
533685fae24SEvan Quan if (hwmgr->hwmgr_func->get_fan_control_mode == NULL)
534685fae24SEvan Quan return -EOPNOTSUPP;
535685fae24SEvan Quan
536685fae24SEvan Quan if (!fan_mode)
537685fae24SEvan Quan return -EINVAL;
538685fae24SEvan Quan
539685fae24SEvan Quan *fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
540685fae24SEvan Quan return 0;
541e098bc96SEvan Quan }
542e098bc96SEvan Quan
pp_dpm_set_fan_speed_pwm(void * handle,uint32_t speed)5430d8318e1SEvan Quan static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed)
544e098bc96SEvan Quan {
545e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
546e098bc96SEvan Quan
547e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
548685fae24SEvan Quan return -EOPNOTSUPP;
549685fae24SEvan Quan
550685fae24SEvan Quan if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL)
551685fae24SEvan Quan return -EOPNOTSUPP;
552685fae24SEvan Quan
553685fae24SEvan Quan if (speed == U32_MAX)
554e098bc96SEvan Quan return -EINVAL;
555e098bc96SEvan Quan
556a746c77eSEvan Quan return hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed);
557e098bc96SEvan Quan }
558e098bc96SEvan Quan
pp_dpm_get_fan_speed_pwm(void * handle,uint32_t * speed)5590d8318e1SEvan Quan static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed)
560e098bc96SEvan Quan {
561e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
562e098bc96SEvan Quan
563e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
564685fae24SEvan Quan return -EOPNOTSUPP;
565e098bc96SEvan Quan
566685fae24SEvan Quan if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL)
567685fae24SEvan Quan return -EOPNOTSUPP;
568685fae24SEvan Quan
569685fae24SEvan Quan if (!speed)
570685fae24SEvan Quan return -EINVAL;
571e098bc96SEvan Quan
572a746c77eSEvan Quan return hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed);
573e098bc96SEvan Quan }
574e098bc96SEvan Quan
pp_dpm_get_fan_speed_rpm(void * handle,uint32_t * rpm)575e098bc96SEvan Quan static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
576e098bc96SEvan Quan {
577e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
578e098bc96SEvan Quan
579e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
580685fae24SEvan Quan return -EOPNOTSUPP;
581e098bc96SEvan Quan
582e098bc96SEvan Quan if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
583685fae24SEvan Quan return -EOPNOTSUPP;
584685fae24SEvan Quan
585685fae24SEvan Quan if (!rpm)
586e098bc96SEvan Quan return -EINVAL;
587e098bc96SEvan Quan
588a746c77eSEvan Quan return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
589e098bc96SEvan Quan }
590e098bc96SEvan Quan
pp_dpm_set_fan_speed_rpm(void * handle,uint32_t rpm)591e098bc96SEvan Quan static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm)
592e098bc96SEvan Quan {
593e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
594e098bc96SEvan Quan
595e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
596685fae24SEvan Quan return -EOPNOTSUPP;
597685fae24SEvan Quan
598685fae24SEvan Quan if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL)
599685fae24SEvan Quan return -EOPNOTSUPP;
600685fae24SEvan Quan
601685fae24SEvan Quan if (rpm == U32_MAX)
602e098bc96SEvan Quan return -EINVAL;
603e098bc96SEvan Quan
604a746c77eSEvan Quan return hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm);
605e098bc96SEvan Quan }
606e098bc96SEvan Quan
pp_dpm_get_pp_num_states(void * handle,struct pp_states_info * data)607e098bc96SEvan Quan static int pp_dpm_get_pp_num_states(void *handle,
608e098bc96SEvan Quan struct pp_states_info *data)
609e098bc96SEvan Quan {
610e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
611e098bc96SEvan Quan int i;
612e098bc96SEvan Quan
613e098bc96SEvan Quan memset(data, 0, sizeof(*data));
614e098bc96SEvan Quan
615e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !hwmgr->ps)
616e098bc96SEvan Quan return -EINVAL;
617e098bc96SEvan Quan
618e098bc96SEvan Quan data->nums = hwmgr->num_ps;
619e098bc96SEvan Quan
620e098bc96SEvan Quan for (i = 0; i < hwmgr->num_ps; i++) {
621e098bc96SEvan Quan struct pp_power_state *state = (struct pp_power_state *)
622e098bc96SEvan Quan ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
623e098bc96SEvan Quan switch (state->classification.ui_label) {
624e098bc96SEvan Quan case PP_StateUILabel_Battery:
625e098bc96SEvan Quan data->states[i] = POWER_STATE_TYPE_BATTERY;
626e098bc96SEvan Quan break;
627e098bc96SEvan Quan case PP_StateUILabel_Balanced:
628e098bc96SEvan Quan data->states[i] = POWER_STATE_TYPE_BALANCED;
629e098bc96SEvan Quan break;
630e098bc96SEvan Quan case PP_StateUILabel_Performance:
631e098bc96SEvan Quan data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
632e098bc96SEvan Quan break;
633e098bc96SEvan Quan default:
634e098bc96SEvan Quan if (state->classification.flags & PP_StateClassificationFlag_Boot)
635e098bc96SEvan Quan data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
636e098bc96SEvan Quan else
637e098bc96SEvan Quan data->states[i] = POWER_STATE_TYPE_DEFAULT;
638e098bc96SEvan Quan }
639e098bc96SEvan Quan }
640e098bc96SEvan Quan return 0;
641e098bc96SEvan Quan }
642e098bc96SEvan Quan
pp_dpm_get_pp_table(void * handle,char ** table)643e098bc96SEvan Quan static int pp_dpm_get_pp_table(void *handle, char **table)
644e098bc96SEvan Quan {
645e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
646e098bc96SEvan Quan
647e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !hwmgr->soft_pp_table)
648e098bc96SEvan Quan return -EINVAL;
649e098bc96SEvan Quan
650e098bc96SEvan Quan *table = (char *)hwmgr->soft_pp_table;
651a746c77eSEvan Quan return hwmgr->soft_pp_table_size;
652e098bc96SEvan Quan }
653e098bc96SEvan Quan
amd_powerplay_reset(void * handle)654e098bc96SEvan Quan static int amd_powerplay_reset(void *handle)
655e098bc96SEvan Quan {
656e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
657e098bc96SEvan Quan int ret;
658e098bc96SEvan Quan
659e098bc96SEvan Quan ret = hwmgr_hw_fini(hwmgr);
660e098bc96SEvan Quan if (ret)
661e098bc96SEvan Quan return ret;
662e098bc96SEvan Quan
663e098bc96SEvan Quan ret = hwmgr_hw_init(hwmgr);
664e098bc96SEvan Quan if (ret)
665e098bc96SEvan Quan return ret;
666e098bc96SEvan Quan
667e098bc96SEvan Quan return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL);
668e098bc96SEvan Quan }
669e098bc96SEvan Quan
pp_dpm_set_pp_table(void * handle,const char * buf,size_t size)670e098bc96SEvan Quan static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
671e098bc96SEvan Quan {
672e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
673e098bc96SEvan Quan int ret = -ENOMEM;
674e098bc96SEvan Quan
675e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
676e098bc96SEvan Quan return -EINVAL;
677e098bc96SEvan Quan
678e098bc96SEvan Quan if (!hwmgr->hardcode_pp_table) {
679e098bc96SEvan Quan hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
680e098bc96SEvan Quan hwmgr->soft_pp_table_size,
681e098bc96SEvan Quan GFP_KERNEL);
682e098bc96SEvan Quan if (!hwmgr->hardcode_pp_table)
683a746c77eSEvan Quan return ret;
684e098bc96SEvan Quan }
685e098bc96SEvan Quan
686e098bc96SEvan Quan memcpy(hwmgr->hardcode_pp_table, buf, size);
687e098bc96SEvan Quan
688e098bc96SEvan Quan hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
689e098bc96SEvan Quan
690e098bc96SEvan Quan ret = amd_powerplay_reset(handle);
691e098bc96SEvan Quan if (ret)
692a746c77eSEvan Quan return ret;
693e098bc96SEvan Quan
694a746c77eSEvan Quan if (hwmgr->hwmgr_func->avfs_control)
695e098bc96SEvan Quan ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
696a746c77eSEvan Quan
697e098bc96SEvan Quan return ret;
698e098bc96SEvan Quan }
699e098bc96SEvan Quan
pp_dpm_force_clock_level(void * handle,enum pp_clock_type type,uint32_t mask)700e098bc96SEvan Quan static int pp_dpm_force_clock_level(void *handle,
701e098bc96SEvan Quan enum pp_clock_type type, uint32_t mask)
702e098bc96SEvan Quan {
703e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
704e098bc96SEvan Quan
705e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
706e098bc96SEvan Quan return -EINVAL;
707e098bc96SEvan Quan
708e098bc96SEvan Quan if (hwmgr->hwmgr_func->force_clock_level == NULL) {
709e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
710e098bc96SEvan Quan return 0;
711e098bc96SEvan Quan }
712e098bc96SEvan Quan
713e098bc96SEvan Quan if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
714e098bc96SEvan Quan pr_debug("force clock level is for dpm manual mode only.\n");
715e098bc96SEvan Quan return -EINVAL;
716e098bc96SEvan Quan }
717e098bc96SEvan Quan
718a746c77eSEvan Quan return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
719e098bc96SEvan Quan }
720e098bc96SEvan Quan
pp_dpm_emit_clock_levels(void * handle,enum pp_clock_type type,char * buf,int * offset)7215d8539d2SDarren Powell static int pp_dpm_emit_clock_levels(void *handle,
7225d8539d2SDarren Powell enum pp_clock_type type,
7235d8539d2SDarren Powell char *buf,
7245d8539d2SDarren Powell int *offset)
7255d8539d2SDarren Powell {
7265d8539d2SDarren Powell struct pp_hwmgr *hwmgr = handle;
7275d8539d2SDarren Powell
7285d8539d2SDarren Powell if (!hwmgr || !hwmgr->pm_en)
7295d8539d2SDarren Powell return -EOPNOTSUPP;
7305d8539d2SDarren Powell
7315d8539d2SDarren Powell if (!hwmgr->hwmgr_func->emit_clock_levels)
7325d8539d2SDarren Powell return -ENOENT;
7335d8539d2SDarren Powell
7345d8539d2SDarren Powell return hwmgr->hwmgr_func->emit_clock_levels(hwmgr, type, buf, offset);
7355d8539d2SDarren Powell }
7365d8539d2SDarren Powell
pp_dpm_print_clock_levels(void * handle,enum pp_clock_type type,char * buf)737e098bc96SEvan Quan static int pp_dpm_print_clock_levels(void *handle,
738e098bc96SEvan Quan enum pp_clock_type type, char *buf)
739e098bc96SEvan Quan {
740e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
741e098bc96SEvan Quan
742e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
743e098bc96SEvan Quan return -EINVAL;
744e098bc96SEvan Quan
745e098bc96SEvan Quan if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
746e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
747e098bc96SEvan Quan return 0;
748e098bc96SEvan Quan }
749a746c77eSEvan Quan return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
750e098bc96SEvan Quan }
751e098bc96SEvan Quan
pp_dpm_get_sclk_od(void * handle)752e098bc96SEvan Quan static int pp_dpm_get_sclk_od(void *handle)
753e098bc96SEvan Quan {
754e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
755e098bc96SEvan Quan
756e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
757e098bc96SEvan Quan return -EINVAL;
758e098bc96SEvan Quan
759e098bc96SEvan Quan if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
760e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
761e098bc96SEvan Quan return 0;
762e098bc96SEvan Quan }
763a746c77eSEvan Quan return hwmgr->hwmgr_func->get_sclk_od(hwmgr);
764e098bc96SEvan Quan }
765e098bc96SEvan Quan
pp_dpm_set_sclk_od(void * handle,uint32_t value)766e098bc96SEvan Quan static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
767e098bc96SEvan Quan {
768e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
769e098bc96SEvan Quan
770e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
771e098bc96SEvan Quan return -EINVAL;
772e098bc96SEvan Quan
773e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
774e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
775e098bc96SEvan Quan return 0;
776e098bc96SEvan Quan }
777e098bc96SEvan Quan
778a746c77eSEvan Quan return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
779e098bc96SEvan Quan }
780e098bc96SEvan Quan
pp_dpm_get_mclk_od(void * handle)781e098bc96SEvan Quan static int pp_dpm_get_mclk_od(void *handle)
782e098bc96SEvan Quan {
783e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
784e098bc96SEvan Quan
785e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
786e098bc96SEvan Quan return -EINVAL;
787e098bc96SEvan Quan
788e098bc96SEvan Quan if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
789e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
790e098bc96SEvan Quan return 0;
791e098bc96SEvan Quan }
792a746c77eSEvan Quan return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
793e098bc96SEvan Quan }
794e098bc96SEvan Quan
pp_dpm_set_mclk_od(void * handle,uint32_t value)795e098bc96SEvan Quan static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
796e098bc96SEvan Quan {
797e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
798e098bc96SEvan Quan
799e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
800e098bc96SEvan Quan return -EINVAL;
801e098bc96SEvan Quan
802e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
803e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
804e098bc96SEvan Quan return 0;
805e098bc96SEvan Quan }
806a746c77eSEvan Quan return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
807e098bc96SEvan Quan }
808e098bc96SEvan Quan
pp_dpm_read_sensor(void * handle,int idx,void * value,int * size)809e098bc96SEvan Quan static int pp_dpm_read_sensor(void *handle, int idx,
810e098bc96SEvan Quan void *value, int *size)
811e098bc96SEvan Quan {
812e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
813e098bc96SEvan Quan
814e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !value)
815e098bc96SEvan Quan return -EINVAL;
816e098bc96SEvan Quan
817e098bc96SEvan Quan switch (idx) {
818e098bc96SEvan Quan case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
819b1a9557aSEvan Quan *((uint32_t *)value) = hwmgr->pstate_sclk * 100;
820e098bc96SEvan Quan return 0;
821e098bc96SEvan Quan case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
822b1a9557aSEvan Quan *((uint32_t *)value) = hwmgr->pstate_mclk * 100;
823b1a9557aSEvan Quan return 0;
824b1a9557aSEvan Quan case AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK:
825b1a9557aSEvan Quan *((uint32_t *)value) = hwmgr->pstate_sclk_peak * 100;
826b1a9557aSEvan Quan return 0;
827b1a9557aSEvan Quan case AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK:
828b1a9557aSEvan Quan *((uint32_t *)value) = hwmgr->pstate_mclk_peak * 100;
829e098bc96SEvan Quan return 0;
830e098bc96SEvan Quan case AMDGPU_PP_SENSOR_MIN_FAN_RPM:
831e098bc96SEvan Quan *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM;
832e098bc96SEvan Quan return 0;
833e098bc96SEvan Quan case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
834e098bc96SEvan Quan *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
835e098bc96SEvan Quan return 0;
836e098bc96SEvan Quan default:
837a746c77eSEvan Quan return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
838e098bc96SEvan Quan }
839e098bc96SEvan Quan }
840e098bc96SEvan Quan
841e098bc96SEvan Quan static struct amd_vce_state*
pp_dpm_get_vce_clock_state(void * handle,unsigned idx)842e098bc96SEvan Quan pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
843e098bc96SEvan Quan {
844e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
845e098bc96SEvan Quan
846e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
847e098bc96SEvan Quan return NULL;
848e098bc96SEvan Quan
849e098bc96SEvan Quan if (idx < hwmgr->num_vce_state_tables)
850e098bc96SEvan Quan return &hwmgr->vce_states[idx];
851e098bc96SEvan Quan return NULL;
852e098bc96SEvan Quan }
853e098bc96SEvan Quan
pp_get_power_profile_mode(void * handle,char * buf)854e098bc96SEvan Quan static int pp_get_power_profile_mode(void *handle, char *buf)
855e098bc96SEvan Quan {
856e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
857e098bc96SEvan Quan
858a7505591SMario Limonciello if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->get_power_profile_mode)
859a035be8aSMario Limonciello return -EOPNOTSUPP;
860a035be8aSMario Limonciello if (!buf)
861e098bc96SEvan Quan return -EINVAL;
862e098bc96SEvan Quan
863a746c77eSEvan Quan return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf);
864e098bc96SEvan Quan }
865e098bc96SEvan Quan
pp_set_power_profile_mode(void * handle,long * input,uint32_t size)866e098bc96SEvan Quan static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size)
867e098bc96SEvan Quan {
868e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
869e098bc96SEvan Quan
870a7505591SMario Limonciello if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->set_power_profile_mode)
871a746c77eSEvan Quan return -EOPNOTSUPP;
872e098bc96SEvan Quan
873e098bc96SEvan Quan if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
874e098bc96SEvan Quan pr_debug("power profile setting is for manual dpm mode only.\n");
875a035be8aSMario Limonciello return -EINVAL;
876e098bc96SEvan Quan }
877e098bc96SEvan Quan
878a746c77eSEvan Quan return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size);
879e098bc96SEvan Quan }
880e098bc96SEvan Quan
pp_set_fine_grain_clk_vol(void * handle,uint32_t type,long * input,uint32_t size)88112a6727dSXiaojian Du static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size)
88212a6727dSXiaojian Du {
88312a6727dSXiaojian Du struct pp_hwmgr *hwmgr = handle;
88412a6727dSXiaojian Du
88512a6727dSXiaojian Du if (!hwmgr || !hwmgr->pm_en)
88612a6727dSXiaojian Du return -EINVAL;
88712a6727dSXiaojian Du
88812a6727dSXiaojian Du if (hwmgr->hwmgr_func->set_fine_grain_clk_vol == NULL)
88912a6727dSXiaojian Du return 0;
89012a6727dSXiaojian Du
89112a6727dSXiaojian Du return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size);
89212a6727dSXiaojian Du }
89312a6727dSXiaojian Du
pp_odn_edit_dpm_table(void * handle,enum PP_OD_DPM_TABLE_COMMAND type,long * input,uint32_t size)894e4d0ef75SNathan Chancellor static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type,
895e4d0ef75SNathan Chancellor long *input, uint32_t size)
896e098bc96SEvan Quan {
897e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
898e098bc96SEvan Quan
899e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
900e098bc96SEvan Quan return -EINVAL;
901e098bc96SEvan Quan
902e098bc96SEvan Quan if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) {
903e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
90412a6727dSXiaojian Du return 0;
905e098bc96SEvan Quan }
906e098bc96SEvan Quan
907e098bc96SEvan Quan return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size);
908e098bc96SEvan Quan }
909e098bc96SEvan Quan
pp_dpm_set_mp1_state(void * handle,enum pp_mp1_state mp1_state)910e098bc96SEvan Quan static int pp_dpm_set_mp1_state(void *handle, enum pp_mp1_state mp1_state)
911e098bc96SEvan Quan {
912e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
913e098bc96SEvan Quan
914e098bc96SEvan Quan if (!hwmgr)
915e098bc96SEvan Quan return -EINVAL;
916e098bc96SEvan Quan
917e098bc96SEvan Quan if (!hwmgr->pm_en)
918e098bc96SEvan Quan return 0;
919e098bc96SEvan Quan
920e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_mp1_state)
921e098bc96SEvan Quan return hwmgr->hwmgr_func->set_mp1_state(hwmgr, mp1_state);
922e098bc96SEvan Quan
923e098bc96SEvan Quan return 0;
924e098bc96SEvan Quan }
925e098bc96SEvan Quan
pp_dpm_switch_power_profile(void * handle,enum PP_SMC_POWER_PROFILE type,bool en)926e098bc96SEvan Quan static int pp_dpm_switch_power_profile(void *handle,
927e098bc96SEvan Quan enum PP_SMC_POWER_PROFILE type, bool en)
928e098bc96SEvan Quan {
929e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
930837ab17cSMa Jun long workload[1];
931e098bc96SEvan Quan uint32_t index;
932e098bc96SEvan Quan
933e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
934e098bc96SEvan Quan return -EINVAL;
935e098bc96SEvan Quan
936e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
937e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
938e098bc96SEvan Quan return -EINVAL;
939e098bc96SEvan Quan }
940e098bc96SEvan Quan
941e098bc96SEvan Quan if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
942e098bc96SEvan Quan return -EINVAL;
943e098bc96SEvan Quan
944e098bc96SEvan Quan if (!en) {
945e098bc96SEvan Quan hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
946e098bc96SEvan Quan index = fls(hwmgr->workload_mask);
947e098bc96SEvan Quan index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
948837ab17cSMa Jun workload[0] = hwmgr->workload_setting[index];
949e098bc96SEvan Quan } else {
950e098bc96SEvan Quan hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
951e098bc96SEvan Quan index = fls(hwmgr->workload_mask);
952e098bc96SEvan Quan index = index <= Workload_Policy_Max ? index - 1 : 0;
953837ab17cSMa Jun workload[0] = hwmgr->workload_setting[index];
954e098bc96SEvan Quan }
955e098bc96SEvan Quan
956e098bc96SEvan Quan if (type == PP_SMC_POWER_PROFILE_COMPUTE &&
957e098bc96SEvan Quan hwmgr->hwmgr_func->disable_power_features_for_compute_performance) {
958a746c77eSEvan Quan if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en))
959e098bc96SEvan Quan return -EINVAL;
960e098bc96SEvan Quan }
961e098bc96SEvan Quan
962e098bc96SEvan Quan if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
963837ab17cSMa Jun hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, workload, 0);
964e098bc96SEvan Quan
965e098bc96SEvan Quan return 0;
966e098bc96SEvan Quan }
967e098bc96SEvan Quan
pp_set_power_limit(void * handle,uint32_t limit)968e098bc96SEvan Quan static int pp_set_power_limit(void *handle, uint32_t limit)
969e098bc96SEvan Quan {
970e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
971e098bc96SEvan Quan uint32_t max_power_limit;
972e098bc96SEvan Quan
973e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
974e098bc96SEvan Quan return -EINVAL;
975e098bc96SEvan Quan
976e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_power_limit == NULL) {
977e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
978e098bc96SEvan Quan return -EINVAL;
979e098bc96SEvan Quan }
980e098bc96SEvan Quan
981e098bc96SEvan Quan if (limit == 0)
982e098bc96SEvan Quan limit = hwmgr->default_power_limit;
983e098bc96SEvan Quan
984e098bc96SEvan Quan max_power_limit = hwmgr->default_power_limit;
985e098bc96SEvan Quan if (hwmgr->od_enabled) {
986e098bc96SEvan Quan max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
987e098bc96SEvan Quan max_power_limit /= 100;
988e098bc96SEvan Quan }
989e098bc96SEvan Quan
990e098bc96SEvan Quan if (limit > max_power_limit)
991e098bc96SEvan Quan return -EINVAL;
992e098bc96SEvan Quan
993e098bc96SEvan Quan hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
994e098bc96SEvan Quan hwmgr->power_limit = limit;
995e098bc96SEvan Quan return 0;
996e098bc96SEvan Quan }
997e098bc96SEvan Quan
pp_get_power_limit(void * handle,uint32_t * limit,enum pp_power_limit_level pp_limit_level,enum pp_power_type power_type)9986e58941cSEric Huang static int pp_get_power_limit(void *handle, uint32_t *limit,
99904bec521SDarren Powell enum pp_power_limit_level pp_limit_level,
100004bec521SDarren Powell enum pp_power_type power_type)
1001e098bc96SEvan Quan {
1002e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
100304bec521SDarren Powell int ret = 0;
1004e098bc96SEvan Quan
1005e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !limit)
1006e098bc96SEvan Quan return -EINVAL;
1007e098bc96SEvan Quan
100804bec521SDarren Powell if (power_type != PP_PWR_TYPE_SUSTAINED)
100904bec521SDarren Powell return -EOPNOTSUPP;
101004bec521SDarren Powell
101104bec521SDarren Powell switch (pp_limit_level) {
101204bec521SDarren Powell case PP_PWR_LIMIT_CURRENT:
1013e098bc96SEvan Quan *limit = hwmgr->power_limit;
101404bec521SDarren Powell break;
101504bec521SDarren Powell case PP_PWR_LIMIT_DEFAULT:
101604bec521SDarren Powell *limit = hwmgr->default_power_limit;
101704bec521SDarren Powell break;
101804bec521SDarren Powell case PP_PWR_LIMIT_MAX:
101904bec521SDarren Powell *limit = hwmgr->default_power_limit;
102004bec521SDarren Powell if (hwmgr->od_enabled) {
102104bec521SDarren Powell *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit);
102204bec521SDarren Powell *limit /= 100;
102304bec521SDarren Powell }
102404bec521SDarren Powell break;
102504bec521SDarren Powell default:
102604bec521SDarren Powell ret = -EOPNOTSUPP;
102704bec521SDarren Powell break;
102804bec521SDarren Powell }
1029e098bc96SEvan Quan
103004bec521SDarren Powell return ret;
1031e098bc96SEvan Quan }
1032e098bc96SEvan Quan
pp_display_configuration_change(void * handle,const struct amd_pp_display_configuration * display_config)1033e098bc96SEvan Quan static int pp_display_configuration_change(void *handle,
1034e098bc96SEvan Quan const struct amd_pp_display_configuration *display_config)
1035e098bc96SEvan Quan {
1036e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1037e098bc96SEvan Quan
1038e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1039e098bc96SEvan Quan return -EINVAL;
1040e098bc96SEvan Quan
1041e098bc96SEvan Quan phm_store_dal_configuration_data(hwmgr, display_config);
1042e098bc96SEvan Quan return 0;
1043e098bc96SEvan Quan }
1044e098bc96SEvan Quan
pp_get_display_power_level(void * handle,struct amd_pp_simple_clock_info * output)1045e098bc96SEvan Quan static int pp_get_display_power_level(void *handle,
1046e098bc96SEvan Quan struct amd_pp_simple_clock_info *output)
1047e098bc96SEvan Quan {
1048e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1049e098bc96SEvan Quan
1050e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !output)
1051e098bc96SEvan Quan return -EINVAL;
1052e098bc96SEvan Quan
1053a746c77eSEvan Quan return phm_get_dal_power_level(hwmgr, output);
1054e098bc96SEvan Quan }
1055e098bc96SEvan Quan
pp_get_current_clocks(void * handle,struct amd_pp_clock_info * clocks)1056e098bc96SEvan Quan static int pp_get_current_clocks(void *handle,
1057e098bc96SEvan Quan struct amd_pp_clock_info *clocks)
1058e098bc96SEvan Quan {
1059e098bc96SEvan Quan struct amd_pp_simple_clock_info simple_clocks = { 0 };
1060e098bc96SEvan Quan struct pp_clock_info hw_clocks;
1061e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1062e098bc96SEvan Quan int ret = 0;
1063e098bc96SEvan Quan
1064e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1065e098bc96SEvan Quan return -EINVAL;
1066e098bc96SEvan Quan
1067e098bc96SEvan Quan phm_get_dal_power_level(hwmgr, &simple_clocks);
1068e098bc96SEvan Quan
1069e098bc96SEvan Quan if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1070e098bc96SEvan Quan PHM_PlatformCaps_PowerContainment))
1071e098bc96SEvan Quan ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1072e098bc96SEvan Quan &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1073e098bc96SEvan Quan else
1074e098bc96SEvan Quan ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1075e098bc96SEvan Quan &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1076e098bc96SEvan Quan
1077e098bc96SEvan Quan if (ret) {
1078e098bc96SEvan Quan pr_debug("Error in phm_get_clock_info \n");
1079e098bc96SEvan Quan return -EINVAL;
1080e098bc96SEvan Quan }
1081e098bc96SEvan Quan
1082e098bc96SEvan Quan clocks->min_engine_clock = hw_clocks.min_eng_clk;
1083e098bc96SEvan Quan clocks->max_engine_clock = hw_clocks.max_eng_clk;
1084e098bc96SEvan Quan clocks->min_memory_clock = hw_clocks.min_mem_clk;
1085e098bc96SEvan Quan clocks->max_memory_clock = hw_clocks.max_mem_clk;
1086e098bc96SEvan Quan clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1087e098bc96SEvan Quan clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1088e098bc96SEvan Quan
1089e098bc96SEvan Quan clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1090e098bc96SEvan Quan clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1091e098bc96SEvan Quan
1092e098bc96SEvan Quan if (simple_clocks.level == 0)
1093e098bc96SEvan Quan clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;
1094e098bc96SEvan Quan else
1095e098bc96SEvan Quan clocks->max_clocks_state = simple_clocks.level;
1096e098bc96SEvan Quan
1097e098bc96SEvan Quan if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1098e098bc96SEvan Quan clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1099e098bc96SEvan Quan clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1100e098bc96SEvan Quan }
1101e098bc96SEvan Quan return 0;
1102e098bc96SEvan Quan }
1103e098bc96SEvan Quan
pp_get_clock_by_type(void * handle,enum amd_pp_clock_type type,struct amd_pp_clocks * clocks)1104e098bc96SEvan Quan static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1105e098bc96SEvan Quan {
1106e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1107e098bc96SEvan Quan
1108e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1109e098bc96SEvan Quan return -EINVAL;
1110e098bc96SEvan Quan
1111e098bc96SEvan Quan if (clocks == NULL)
1112e098bc96SEvan Quan return -EINVAL;
1113e098bc96SEvan Quan
1114a746c77eSEvan Quan return phm_get_clock_by_type(hwmgr, type, clocks);
1115e098bc96SEvan Quan }
1116e098bc96SEvan Quan
pp_get_clock_by_type_with_latency(void * handle,enum amd_pp_clock_type type,struct pp_clock_levels_with_latency * clocks)1117e098bc96SEvan Quan static int pp_get_clock_by_type_with_latency(void *handle,
1118e098bc96SEvan Quan enum amd_pp_clock_type type,
1119e098bc96SEvan Quan struct pp_clock_levels_with_latency *clocks)
1120e098bc96SEvan Quan {
1121e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1122e098bc96SEvan Quan
1123e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !clocks)
1124e098bc96SEvan Quan return -EINVAL;
1125e098bc96SEvan Quan
1126a746c77eSEvan Quan return phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1127e098bc96SEvan Quan }
1128e098bc96SEvan Quan
pp_get_clock_by_type_with_voltage(void * handle,enum amd_pp_clock_type type,struct pp_clock_levels_with_voltage * clocks)1129e098bc96SEvan Quan static int pp_get_clock_by_type_with_voltage(void *handle,
1130e098bc96SEvan Quan enum amd_pp_clock_type type,
1131e098bc96SEvan Quan struct pp_clock_levels_with_voltage *clocks)
1132e098bc96SEvan Quan {
1133e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1134e098bc96SEvan Quan
1135e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !clocks)
1136e098bc96SEvan Quan return -EINVAL;
1137e098bc96SEvan Quan
1138a746c77eSEvan Quan return phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1139e098bc96SEvan Quan }
1140e098bc96SEvan Quan
pp_set_watermarks_for_clocks_ranges(void * handle,void * clock_ranges)1141e098bc96SEvan Quan static int pp_set_watermarks_for_clocks_ranges(void *handle,
1142e098bc96SEvan Quan void *clock_ranges)
1143e098bc96SEvan Quan {
1144e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1145e098bc96SEvan Quan
1146e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !clock_ranges)
1147e098bc96SEvan Quan return -EINVAL;
1148e098bc96SEvan Quan
1149a746c77eSEvan Quan return phm_set_watermarks_for_clocks_ranges(hwmgr,
1150e098bc96SEvan Quan clock_ranges);
1151e098bc96SEvan Quan }
1152e098bc96SEvan Quan
pp_display_clock_voltage_request(void * handle,struct pp_display_clock_request * clock)1153e098bc96SEvan Quan static int pp_display_clock_voltage_request(void *handle,
1154e098bc96SEvan Quan struct pp_display_clock_request *clock)
1155e098bc96SEvan Quan {
1156e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1157e098bc96SEvan Quan
1158e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !clock)
1159e098bc96SEvan Quan return -EINVAL;
1160e098bc96SEvan Quan
1161a746c77eSEvan Quan return phm_display_clock_voltage_request(hwmgr, clock);
1162e098bc96SEvan Quan }
1163e098bc96SEvan Quan
pp_get_display_mode_validation_clocks(void * handle,struct amd_pp_simple_clock_info * clocks)1164e098bc96SEvan Quan static int pp_get_display_mode_validation_clocks(void *handle,
1165e098bc96SEvan Quan struct amd_pp_simple_clock_info *clocks)
1166e098bc96SEvan Quan {
1167e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1168e098bc96SEvan Quan int ret = 0;
1169e098bc96SEvan Quan
1170e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !clocks)
1171e098bc96SEvan Quan return -EINVAL;
1172e098bc96SEvan Quan
1173e098bc96SEvan Quan clocks->level = PP_DAL_POWERLEVEL_7;
1174e098bc96SEvan Quan
1175e098bc96SEvan Quan if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1176e098bc96SEvan Quan ret = phm_get_max_high_clocks(hwmgr, clocks);
1177e098bc96SEvan Quan
1178e098bc96SEvan Quan return ret;
1179e098bc96SEvan Quan }
1180e098bc96SEvan Quan
pp_dpm_powergate_mmhub(void * handle)1181e098bc96SEvan Quan static int pp_dpm_powergate_mmhub(void *handle)
1182e098bc96SEvan Quan {
1183e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1184e098bc96SEvan Quan
1185e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1186e098bc96SEvan Quan return -EINVAL;
1187e098bc96SEvan Quan
1188e098bc96SEvan Quan if (hwmgr->hwmgr_func->powergate_mmhub == NULL) {
1189e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1190e098bc96SEvan Quan return 0;
1191e098bc96SEvan Quan }
1192e098bc96SEvan Quan
1193e098bc96SEvan Quan return hwmgr->hwmgr_func->powergate_mmhub(hwmgr);
1194e098bc96SEvan Quan }
1195e098bc96SEvan Quan
pp_dpm_powergate_gfx(void * handle,bool gate)1196e098bc96SEvan Quan static int pp_dpm_powergate_gfx(void *handle, bool gate)
1197e098bc96SEvan Quan {
1198e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1199e098bc96SEvan Quan
1200e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1201e098bc96SEvan Quan return 0;
1202e098bc96SEvan Quan
1203e098bc96SEvan Quan if (hwmgr->hwmgr_func->powergate_gfx == NULL) {
1204e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1205e098bc96SEvan Quan return 0;
1206e098bc96SEvan Quan }
1207e098bc96SEvan Quan
1208e098bc96SEvan Quan return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate);
1209e098bc96SEvan Quan }
1210e098bc96SEvan Quan
pp_dpm_powergate_acp(void * handle,bool gate)1211e098bc96SEvan Quan static void pp_dpm_powergate_acp(void *handle, bool gate)
1212e098bc96SEvan Quan {
1213e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1214e098bc96SEvan Quan
1215e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1216e098bc96SEvan Quan return;
1217e098bc96SEvan Quan
1218e098bc96SEvan Quan if (hwmgr->hwmgr_func->powergate_acp == NULL) {
1219e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1220e098bc96SEvan Quan return;
1221e098bc96SEvan Quan }
1222e098bc96SEvan Quan
1223e098bc96SEvan Quan hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);
1224e098bc96SEvan Quan }
1225e098bc96SEvan Quan
pp_dpm_powergate_sdma(void * handle,bool gate)1226e098bc96SEvan Quan static void pp_dpm_powergate_sdma(void *handle, bool gate)
1227e098bc96SEvan Quan {
1228e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1229e098bc96SEvan Quan
1230e098bc96SEvan Quan if (!hwmgr)
1231e098bc96SEvan Quan return;
1232e098bc96SEvan Quan
1233e098bc96SEvan Quan if (hwmgr->hwmgr_func->powergate_sdma == NULL) {
1234e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1235e098bc96SEvan Quan return;
1236e098bc96SEvan Quan }
1237e098bc96SEvan Quan
1238e098bc96SEvan Quan hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);
1239e098bc96SEvan Quan }
1240e098bc96SEvan Quan
pp_set_powergating_by_smu(void * handle,uint32_t block_type,bool gate)1241e098bc96SEvan Quan static int pp_set_powergating_by_smu(void *handle,
1242e098bc96SEvan Quan uint32_t block_type, bool gate)
1243e098bc96SEvan Quan {
1244e098bc96SEvan Quan int ret = 0;
1245e098bc96SEvan Quan
1246e098bc96SEvan Quan switch (block_type) {
1247e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_UVD:
1248e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_VCN:
1249e098bc96SEvan Quan pp_dpm_powergate_uvd(handle, gate);
1250e098bc96SEvan Quan break;
1251e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_VCE:
1252e098bc96SEvan Quan pp_dpm_powergate_vce(handle, gate);
1253e098bc96SEvan Quan break;
1254e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_GMC:
125517252701SEvan Quan /*
125617252701SEvan Quan * For now, this is only used on PICASSO.
125717252701SEvan Quan * And only "gate" operation is supported.
125817252701SEvan Quan */
125917252701SEvan Quan if (gate)
1260e098bc96SEvan Quan pp_dpm_powergate_mmhub(handle);
1261e098bc96SEvan Quan break;
1262e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_GFX:
1263e098bc96SEvan Quan ret = pp_dpm_powergate_gfx(handle, gate);
1264e098bc96SEvan Quan break;
1265e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_ACP:
1266e098bc96SEvan Quan pp_dpm_powergate_acp(handle, gate);
1267e098bc96SEvan Quan break;
1268e098bc96SEvan Quan case AMD_IP_BLOCK_TYPE_SDMA:
1269e098bc96SEvan Quan pp_dpm_powergate_sdma(handle, gate);
1270e098bc96SEvan Quan break;
1271e098bc96SEvan Quan default:
1272e098bc96SEvan Quan break;
1273e098bc96SEvan Quan }
1274e098bc96SEvan Quan return ret;
1275e098bc96SEvan Quan }
1276e098bc96SEvan Quan
pp_notify_smu_enable_pwe(void * handle)1277e098bc96SEvan Quan static int pp_notify_smu_enable_pwe(void *handle)
1278e098bc96SEvan Quan {
1279e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1280e098bc96SEvan Quan
1281e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1282e098bc96SEvan Quan return -EINVAL;
1283e098bc96SEvan Quan
1284e098bc96SEvan Quan if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) {
1285e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1286e098bc96SEvan Quan return -EINVAL;
1287e098bc96SEvan Quan }
1288e098bc96SEvan Quan
1289e098bc96SEvan Quan hwmgr->hwmgr_func->smus_notify_pwe(hwmgr);
1290e098bc96SEvan Quan
1291e098bc96SEvan Quan return 0;
1292e098bc96SEvan Quan }
1293e098bc96SEvan Quan
pp_enable_mgpu_fan_boost(void * handle)1294e098bc96SEvan Quan static int pp_enable_mgpu_fan_boost(void *handle)
1295e098bc96SEvan Quan {
1296e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1297e098bc96SEvan Quan
1298e098bc96SEvan Quan if (!hwmgr)
1299e098bc96SEvan Quan return -EINVAL;
1300e098bc96SEvan Quan
1301e098bc96SEvan Quan if (!hwmgr->pm_en ||
1302e098bc96SEvan Quan hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL)
1303e098bc96SEvan Quan return 0;
1304e098bc96SEvan Quan
1305e098bc96SEvan Quan hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);
1306e098bc96SEvan Quan
1307e098bc96SEvan Quan return 0;
1308e098bc96SEvan Quan }
1309e098bc96SEvan Quan
pp_set_min_deep_sleep_dcefclk(void * handle,uint32_t clock)1310e098bc96SEvan Quan static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock)
1311e098bc96SEvan Quan {
1312e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1313e098bc96SEvan Quan
1314e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1315e098bc96SEvan Quan return -EINVAL;
1316e098bc96SEvan Quan
1317e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) {
1318e098bc96SEvan Quan pr_debug("%s was not implemented.\n", __func__);
1319e098bc96SEvan Quan return -EINVAL;
1320e098bc96SEvan Quan }
1321e098bc96SEvan Quan
1322e098bc96SEvan Quan hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock);
1323e098bc96SEvan Quan
1324e098bc96SEvan Quan return 0;
1325e098bc96SEvan Quan }
1326e098bc96SEvan Quan
pp_set_hard_min_dcefclk_by_freq(void * handle,uint32_t clock)1327e098bc96SEvan Quan static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock)
1328e098bc96SEvan Quan {
1329e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1330e098bc96SEvan Quan
1331e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1332e098bc96SEvan Quan return -EINVAL;
1333e098bc96SEvan Quan
1334e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) {
1335e098bc96SEvan Quan pr_debug("%s was not implemented.\n", __func__);
1336e098bc96SEvan Quan return -EINVAL;
1337e098bc96SEvan Quan }
1338e098bc96SEvan Quan
1339e098bc96SEvan Quan hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock);
1340e098bc96SEvan Quan
1341e098bc96SEvan Quan return 0;
1342e098bc96SEvan Quan }
1343e098bc96SEvan Quan
pp_set_hard_min_fclk_by_freq(void * handle,uint32_t clock)1344e098bc96SEvan Quan static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock)
1345e098bc96SEvan Quan {
1346e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1347e098bc96SEvan Quan
1348e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1349e098bc96SEvan Quan return -EINVAL;
1350e098bc96SEvan Quan
1351e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) {
1352e098bc96SEvan Quan pr_debug("%s was not implemented.\n", __func__);
1353e098bc96SEvan Quan return -EINVAL;
1354e098bc96SEvan Quan }
1355e098bc96SEvan Quan
1356e098bc96SEvan Quan hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock);
1357e098bc96SEvan Quan
1358e098bc96SEvan Quan return 0;
1359e098bc96SEvan Quan }
1360e098bc96SEvan Quan
pp_set_active_display_count(void * handle,uint32_t count)1361e098bc96SEvan Quan static int pp_set_active_display_count(void *handle, uint32_t count)
1362e098bc96SEvan Quan {
1363e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1364e098bc96SEvan Quan
1365e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1366e098bc96SEvan Quan return -EINVAL;
1367e098bc96SEvan Quan
1368a746c77eSEvan Quan return phm_set_active_display_count(hwmgr, count);
1369e098bc96SEvan Quan }
1370e098bc96SEvan Quan
pp_get_asic_baco_capability(void * handle,bool * cap)1371e098bc96SEvan Quan static int pp_get_asic_baco_capability(void *handle, bool *cap)
1372e098bc96SEvan Quan {
1373e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1374e098bc96SEvan Quan
1375e098bc96SEvan Quan *cap = false;
1376e098bc96SEvan Quan if (!hwmgr)
1377e098bc96SEvan Quan return -EINVAL;
1378e098bc96SEvan Quan
1379e098bc96SEvan Quan if (!(hwmgr->not_vf && amdgpu_dpm) ||
1380e098bc96SEvan Quan !hwmgr->hwmgr_func->get_asic_baco_capability)
1381e098bc96SEvan Quan return 0;
1382e098bc96SEvan Quan
1383e098bc96SEvan Quan hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap);
1384e098bc96SEvan Quan
1385e098bc96SEvan Quan return 0;
1386e098bc96SEvan Quan }
1387e098bc96SEvan Quan
pp_get_asic_baco_state(void * handle,int * state)1388e098bc96SEvan Quan static int pp_get_asic_baco_state(void *handle, int *state)
1389e098bc96SEvan Quan {
1390e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1391e098bc96SEvan Quan
1392e098bc96SEvan Quan if (!hwmgr)
1393e098bc96SEvan Quan return -EINVAL;
1394e098bc96SEvan Quan
1395e098bc96SEvan Quan if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state)
1396e098bc96SEvan Quan return 0;
1397e098bc96SEvan Quan
1398e098bc96SEvan Quan hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state);
1399e098bc96SEvan Quan
1400e098bc96SEvan Quan return 0;
1401e098bc96SEvan Quan }
1402e098bc96SEvan Quan
pp_set_asic_baco_state(void * handle,int state)1403e098bc96SEvan Quan static int pp_set_asic_baco_state(void *handle, int state)
1404e098bc96SEvan Quan {
1405e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1406e098bc96SEvan Quan
1407e098bc96SEvan Quan if (!hwmgr)
1408e098bc96SEvan Quan return -EINVAL;
1409e098bc96SEvan Quan
1410e098bc96SEvan Quan if (!(hwmgr->not_vf && amdgpu_dpm) ||
1411e098bc96SEvan Quan !hwmgr->hwmgr_func->set_asic_baco_state)
1412e098bc96SEvan Quan return 0;
1413e098bc96SEvan Quan
1414e098bc96SEvan Quan hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state);
1415e098bc96SEvan Quan
1416e098bc96SEvan Quan return 0;
1417e098bc96SEvan Quan }
1418e098bc96SEvan Quan
pp_get_ppfeature_status(void * handle,char * buf)1419e098bc96SEvan Quan static int pp_get_ppfeature_status(void *handle, char *buf)
1420e098bc96SEvan Quan {
1421e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1422e098bc96SEvan Quan
1423e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en || !buf)
1424e098bc96SEvan Quan return -EINVAL;
1425e098bc96SEvan Quan
1426e098bc96SEvan Quan if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) {
1427e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1428e098bc96SEvan Quan return -EINVAL;
1429e098bc96SEvan Quan }
1430e098bc96SEvan Quan
1431a746c77eSEvan Quan return hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf);
1432e098bc96SEvan Quan }
1433e098bc96SEvan Quan
pp_set_ppfeature_status(void * handle,uint64_t ppfeature_masks)1434e098bc96SEvan Quan static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks)
1435e098bc96SEvan Quan {
1436e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1437e098bc96SEvan Quan
1438e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1439e098bc96SEvan Quan return -EINVAL;
1440e098bc96SEvan Quan
1441e098bc96SEvan Quan if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) {
1442e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1443e098bc96SEvan Quan return -EINVAL;
1444e098bc96SEvan Quan }
1445e098bc96SEvan Quan
1446a746c77eSEvan Quan return hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks);
1447e098bc96SEvan Quan }
1448e098bc96SEvan Quan
pp_asic_reset_mode_2(void * handle)1449e098bc96SEvan Quan static int pp_asic_reset_mode_2(void *handle)
1450e098bc96SEvan Quan {
1451e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1452e098bc96SEvan Quan
1453e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1454e098bc96SEvan Quan return -EINVAL;
1455e098bc96SEvan Quan
1456e098bc96SEvan Quan if (hwmgr->hwmgr_func->asic_reset == NULL) {
1457e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1458e098bc96SEvan Quan return -EINVAL;
1459e098bc96SEvan Quan }
1460e098bc96SEvan Quan
1461a746c77eSEvan Quan return hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2);
1462e098bc96SEvan Quan }
1463e098bc96SEvan Quan
pp_smu_i2c_bus_access(void * handle,bool acquire)1464e098bc96SEvan Quan static int pp_smu_i2c_bus_access(void *handle, bool acquire)
1465e098bc96SEvan Quan {
1466e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1467e098bc96SEvan Quan
1468e098bc96SEvan Quan if (!hwmgr || !hwmgr->pm_en)
1469e098bc96SEvan Quan return -EINVAL;
1470e098bc96SEvan Quan
1471e098bc96SEvan Quan if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) {
1472e098bc96SEvan Quan pr_info_ratelimited("%s was not implemented.\n", __func__);
1473e098bc96SEvan Quan return -EINVAL;
1474e098bc96SEvan Quan }
1475e098bc96SEvan Quan
1476a746c77eSEvan Quan return hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire);
1477e098bc96SEvan Quan }
1478e098bc96SEvan Quan
pp_set_df_cstate(void * handle,enum pp_df_cstate state)1479e098bc96SEvan Quan static int pp_set_df_cstate(void *handle, enum pp_df_cstate state)
1480e098bc96SEvan Quan {
1481e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1482e098bc96SEvan Quan
1483e098bc96SEvan Quan if (!hwmgr)
1484e098bc96SEvan Quan return -EINVAL;
1485e098bc96SEvan Quan
1486e098bc96SEvan Quan if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate)
1487e098bc96SEvan Quan return 0;
1488e098bc96SEvan Quan
1489e098bc96SEvan Quan hwmgr->hwmgr_func->set_df_cstate(hwmgr, state);
1490e098bc96SEvan Quan
1491e098bc96SEvan Quan return 0;
1492e098bc96SEvan Quan }
1493e098bc96SEvan Quan
pp_set_xgmi_pstate(void * handle,uint32_t pstate)1494e098bc96SEvan Quan static int pp_set_xgmi_pstate(void *handle, uint32_t pstate)
1495e098bc96SEvan Quan {
1496e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1497e098bc96SEvan Quan
1498e098bc96SEvan Quan if (!hwmgr)
1499e098bc96SEvan Quan return -EINVAL;
1500e098bc96SEvan Quan
1501e098bc96SEvan Quan if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate)
1502e098bc96SEvan Quan return 0;
1503e098bc96SEvan Quan
1504e098bc96SEvan Quan hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate);
1505e098bc96SEvan Quan
1506e098bc96SEvan Quan return 0;
1507e098bc96SEvan Quan }
1508e098bc96SEvan Quan
pp_get_gpu_metrics(void * handle,void ** table)1509e098bc96SEvan Quan static ssize_t pp_get_gpu_metrics(void *handle, void **table)
1510e098bc96SEvan Quan {
1511e098bc96SEvan Quan struct pp_hwmgr *hwmgr = handle;
1512e098bc96SEvan Quan
1513e098bc96SEvan Quan if (!hwmgr)
1514e098bc96SEvan Quan return -EINVAL;
1515e098bc96SEvan Quan
1516e098bc96SEvan Quan if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics)
1517e098bc96SEvan Quan return -EOPNOTSUPP;
1518e098bc96SEvan Quan
1519a746c77eSEvan Quan return hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table);
1520e098bc96SEvan Quan }
1521e098bc96SEvan Quan
pp_gfx_state_change_set(void * handle,uint32_t state)1522d90a53d6SPrike Liang static int pp_gfx_state_change_set(void *handle, uint32_t state)
1523d90a53d6SPrike Liang {
1524d90a53d6SPrike Liang struct pp_hwmgr *hwmgr = handle;
1525d90a53d6SPrike Liang
1526d90a53d6SPrike Liang if (!hwmgr || !hwmgr->pm_en)
1527d90a53d6SPrike Liang return -EINVAL;
1528d90a53d6SPrike Liang
1529d90a53d6SPrike Liang if (hwmgr->hwmgr_func->gfx_state_change == NULL) {
1530d90a53d6SPrike Liang pr_info_ratelimited("%s was not implemented.\n", __func__);
1531d90a53d6SPrike Liang return -EINVAL;
1532d90a53d6SPrike Liang }
1533d90a53d6SPrike Liang
1534d90a53d6SPrike Liang hwmgr->hwmgr_func->gfx_state_change(hwmgr, state);
1535d90a53d6SPrike Liang return 0;
1536d90a53d6SPrike Liang }
1537d90a53d6SPrike Liang
pp_get_prv_buffer_details(void * handle,void ** addr,size_t * size)1538b8c78bdbSLijo Lazar static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size)
1539b8c78bdbSLijo Lazar {
1540b8c78bdbSLijo Lazar struct pp_hwmgr *hwmgr = handle;
1541b8c78bdbSLijo Lazar struct amdgpu_device *adev = hwmgr->adev;
1542629c30dbSLi Zhong int err;
1543b8c78bdbSLijo Lazar
1544b8c78bdbSLijo Lazar if (!addr || !size)
1545b8c78bdbSLijo Lazar return -EINVAL;
1546b8c78bdbSLijo Lazar
1547b8c78bdbSLijo Lazar *addr = NULL;
1548b8c78bdbSLijo Lazar *size = 0;
1549b8c78bdbSLijo Lazar if (adev->pm.smu_prv_buffer) {
1550629c30dbSLi Zhong err = amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr);
1551629c30dbSLi Zhong if (err)
1552629c30dbSLi Zhong return err;
1553b8c78bdbSLijo Lazar *size = adev->pm.smu_prv_buffer_size;
1554b8c78bdbSLijo Lazar }
1555b8c78bdbSLijo Lazar
1556b8c78bdbSLijo Lazar return 0;
1557b8c78bdbSLijo Lazar }
1558b8c78bdbSLijo Lazar
pp_pm_compute_clocks(void * handle)15596ddbd37fSEvan Quan static void pp_pm_compute_clocks(void *handle)
15606ddbd37fSEvan Quan {
15616ddbd37fSEvan Quan struct pp_hwmgr *hwmgr = handle;
15626ddbd37fSEvan Quan struct amdgpu_device *adev = hwmgr->adev;
15636ddbd37fSEvan Quan
1564d09ef243SAlex Deucher if (!adev->dc_enabled) {
15656ddbd37fSEvan Quan amdgpu_dpm_get_active_displays(adev);
15666ddbd37fSEvan Quan adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;
15676ddbd37fSEvan Quan adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);
15686ddbd37fSEvan Quan adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev);
15696ddbd37fSEvan Quan /* we have issues with mclk switching with
15706ddbd37fSEvan Quan * refresh rates over 120 hz on the non-DC code.
15716ddbd37fSEvan Quan */
15726ddbd37fSEvan Quan if (adev->pm.pm_display_cfg.vrefresh > 120)
15736ddbd37fSEvan Quan adev->pm.pm_display_cfg.min_vblank_time = 0;
15746ddbd37fSEvan Quan
15756ddbd37fSEvan Quan pp_display_configuration_change(handle,
15766ddbd37fSEvan Quan &adev->pm.pm_display_cfg);
15776ddbd37fSEvan Quan }
15786ddbd37fSEvan Quan
15796ddbd37fSEvan Quan pp_dpm_dispatch_tasks(handle,
15806ddbd37fSEvan Quan AMD_PP_TASK_DISPLAY_CONFIG_CHANGE,
15816ddbd37fSEvan Quan NULL);
15826ddbd37fSEvan Quan }
15836ddbd37fSEvan Quan
1584e098bc96SEvan Quan static const struct amd_pm_funcs pp_dpm_funcs = {
1585e098bc96SEvan Quan .load_firmware = pp_dpm_load_fw,
1586e098bc96SEvan Quan .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1587e098bc96SEvan Quan .force_performance_level = pp_dpm_force_performance_level,
1588e098bc96SEvan Quan .get_performance_level = pp_dpm_get_performance_level,
1589e098bc96SEvan Quan .get_current_power_state = pp_dpm_get_current_power_state,
1590e098bc96SEvan Quan .dispatch_tasks = pp_dpm_dispatch_tasks,
1591e098bc96SEvan Quan .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1592e098bc96SEvan Quan .get_fan_control_mode = pp_dpm_get_fan_control_mode,
15930d8318e1SEvan Quan .set_fan_speed_pwm = pp_dpm_set_fan_speed_pwm,
15940d8318e1SEvan Quan .get_fan_speed_pwm = pp_dpm_get_fan_speed_pwm,
1595e098bc96SEvan Quan .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
1596e098bc96SEvan Quan .set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,
1597e098bc96SEvan Quan .get_pp_num_states = pp_dpm_get_pp_num_states,
1598e098bc96SEvan Quan .get_pp_table = pp_dpm_get_pp_table,
1599e098bc96SEvan Quan .set_pp_table = pp_dpm_set_pp_table,
1600e098bc96SEvan Quan .force_clock_level = pp_dpm_force_clock_level,
16015d8539d2SDarren Powell .emit_clock_levels = pp_dpm_emit_clock_levels,
1602e098bc96SEvan Quan .print_clock_levels = pp_dpm_print_clock_levels,
1603e098bc96SEvan Quan .get_sclk_od = pp_dpm_get_sclk_od,
1604e098bc96SEvan Quan .set_sclk_od = pp_dpm_set_sclk_od,
1605e098bc96SEvan Quan .get_mclk_od = pp_dpm_get_mclk_od,
1606e098bc96SEvan Quan .set_mclk_od = pp_dpm_set_mclk_od,
1607e098bc96SEvan Quan .read_sensor = pp_dpm_read_sensor,
1608e098bc96SEvan Quan .get_vce_clock_state = pp_dpm_get_vce_clock_state,
1609e098bc96SEvan Quan .switch_power_profile = pp_dpm_switch_power_profile,
1610e098bc96SEvan Quan .set_clockgating_by_smu = pp_set_clockgating_by_smu,
1611e098bc96SEvan Quan .set_powergating_by_smu = pp_set_powergating_by_smu,
1612e098bc96SEvan Quan .get_power_profile_mode = pp_get_power_profile_mode,
1613e098bc96SEvan Quan .set_power_profile_mode = pp_set_power_profile_mode,
161412a6727dSXiaojian Du .set_fine_grain_clk_vol = pp_set_fine_grain_clk_vol,
1615e098bc96SEvan Quan .odn_edit_dpm_table = pp_odn_edit_dpm_table,
1616e098bc96SEvan Quan .set_mp1_state = pp_dpm_set_mp1_state,
1617e098bc96SEvan Quan .set_power_limit = pp_set_power_limit,
1618e098bc96SEvan Quan .get_power_limit = pp_get_power_limit,
1619e098bc96SEvan Quan /* export to DC */
1620e098bc96SEvan Quan .get_sclk = pp_dpm_get_sclk,
1621e098bc96SEvan Quan .get_mclk = pp_dpm_get_mclk,
1622e098bc96SEvan Quan .display_configuration_change = pp_display_configuration_change,
1623e098bc96SEvan Quan .get_display_power_level = pp_get_display_power_level,
1624e098bc96SEvan Quan .get_current_clocks = pp_get_current_clocks,
1625e098bc96SEvan Quan .get_clock_by_type = pp_get_clock_by_type,
1626e098bc96SEvan Quan .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency,
1627e098bc96SEvan Quan .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage,
1628e098bc96SEvan Quan .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges,
1629e098bc96SEvan Quan .display_clock_voltage_request = pp_display_clock_voltage_request,
1630e098bc96SEvan Quan .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
1631e098bc96SEvan Quan .notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
1632e098bc96SEvan Quan .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,
1633e098bc96SEvan Quan .set_active_display_count = pp_set_active_display_count,
1634e098bc96SEvan Quan .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk,
1635e098bc96SEvan Quan .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq,
1636e098bc96SEvan Quan .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq,
1637e098bc96SEvan Quan .get_asic_baco_capability = pp_get_asic_baco_capability,
1638e098bc96SEvan Quan .get_asic_baco_state = pp_get_asic_baco_state,
1639e098bc96SEvan Quan .set_asic_baco_state = pp_set_asic_baco_state,
1640e098bc96SEvan Quan .get_ppfeature_status = pp_get_ppfeature_status,
1641e098bc96SEvan Quan .set_ppfeature_status = pp_set_ppfeature_status,
1642e098bc96SEvan Quan .asic_reset_mode_2 = pp_asic_reset_mode_2,
1643e098bc96SEvan Quan .smu_i2c_bus_access = pp_smu_i2c_bus_access,
1644e098bc96SEvan Quan .set_df_cstate = pp_set_df_cstate,
1645e098bc96SEvan Quan .set_xgmi_pstate = pp_set_xgmi_pstate,
1646e098bc96SEvan Quan .get_gpu_metrics = pp_get_gpu_metrics,
1647d90a53d6SPrike Liang .gfx_state_change_set = pp_gfx_state_change_set,
1648b8c78bdbSLijo Lazar .get_smu_prv_buf_details = pp_get_prv_buffer_details,
16496ddbd37fSEvan Quan .pm_compute_clocks = pp_pm_compute_clocks,
1650e098bc96SEvan Quan };
1651