xref: /openbmc/linux/drivers/gpu/drm/amd/pm/amdgpu_dpm.c (revision 7101ab97)
1e098bc96SEvan Quan /*
2e098bc96SEvan Quan  * Copyright 2011 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  * Authors: Alex Deucher
23e098bc96SEvan Quan  */
24e098bc96SEvan Quan 
25e098bc96SEvan Quan #include "amdgpu.h"
26e098bc96SEvan Quan #include "amdgpu_atombios.h"
27e098bc96SEvan Quan #include "amdgpu_i2c.h"
28e098bc96SEvan Quan #include "amdgpu_dpm.h"
29e098bc96SEvan Quan #include "atom.h"
30e098bc96SEvan Quan #include "amd_pcie.h"
31e098bc96SEvan Quan #include "amdgpu_display.h"
32e098bc96SEvan Quan #include "hwmgr.h"
33e098bc96SEvan Quan #include <linux/power_supply.h>
34ebfc2533SEvan Quan #include "amdgpu_smu.h"
35e098bc96SEvan Quan 
36d4481576SEvan Quan #define amdgpu_dpm_enable_bapm(adev, e) \
37d4481576SEvan Quan 		((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e)))
38d4481576SEvan Quan 
39e098bc96SEvan Quan int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
40e098bc96SEvan Quan {
41bc7d6c12SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
423712e7a4SEvan Quan 	int ret = 0;
43e098bc96SEvan Quan 
443712e7a4SEvan Quan 	if (!pp_funcs->get_sclk)
453712e7a4SEvan Quan 		return 0;
463712e7a4SEvan Quan 
473712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
483712e7a4SEvan Quan 	ret = pp_funcs->get_sclk((adev)->powerplay.pp_handle,
493712e7a4SEvan Quan 				 low);
503712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
513712e7a4SEvan Quan 
523712e7a4SEvan Quan 	return ret;
53e098bc96SEvan Quan }
54e098bc96SEvan Quan 
55e098bc96SEvan Quan int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low)
56e098bc96SEvan Quan {
57bc7d6c12SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
583712e7a4SEvan Quan 	int ret = 0;
59e098bc96SEvan Quan 
603712e7a4SEvan Quan 	if (!pp_funcs->get_mclk)
613712e7a4SEvan Quan 		return 0;
623712e7a4SEvan Quan 
633712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
643712e7a4SEvan Quan 	ret = pp_funcs->get_mclk((adev)->powerplay.pp_handle,
653712e7a4SEvan Quan 				 low);
663712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
673712e7a4SEvan Quan 
683712e7a4SEvan Quan 	return ret;
69e098bc96SEvan Quan }
70e098bc96SEvan Quan 
71e098bc96SEvan Quan int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate)
72e098bc96SEvan Quan {
73e098bc96SEvan Quan 	int ret = 0;
74bc7d6c12SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
756ee27ee2SEvan Quan 	enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON;
766ee27ee2SEvan Quan 
776ee27ee2SEvan Quan 	if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) {
786ee27ee2SEvan Quan 		dev_dbg(adev->dev, "IP block%d already in the target %s state!",
796ee27ee2SEvan Quan 				block_type, gate ? "gate" : "ungate");
806ee27ee2SEvan Quan 		return 0;
816ee27ee2SEvan Quan 	}
82e098bc96SEvan Quan 
833712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
843712e7a4SEvan Quan 
85e098bc96SEvan Quan 	switch (block_type) {
86e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_UVD:
87e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_VCE:
88e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_GFX:
89e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_VCN:
90e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_SDMA:
91e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_JPEG:
92e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_GMC:
93e098bc96SEvan Quan 	case AMD_IP_BLOCK_TYPE_ACP:
943712e7a4SEvan Quan 		if (pp_funcs && pp_funcs->set_powergating_by_smu)
95bc7d6c12SDarren Powell 			ret = (pp_funcs->set_powergating_by_smu(
96e098bc96SEvan Quan 				(adev)->powerplay.pp_handle, block_type, gate));
97e098bc96SEvan Quan 		break;
98e098bc96SEvan Quan 	default:
99e098bc96SEvan Quan 		break;
100e098bc96SEvan Quan 	}
101e098bc96SEvan Quan 
1026ee27ee2SEvan Quan 	if (!ret)
1036ee27ee2SEvan Quan 		atomic_set(&adev->pm.pwr_state[block_type], pwr_state);
1046ee27ee2SEvan Quan 
1053712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
1063712e7a4SEvan Quan 
107e098bc96SEvan Quan 	return ret;
108e098bc96SEvan Quan }
109e098bc96SEvan Quan 
110*7101ab97SHuang Rui int amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev)
111*7101ab97SHuang Rui {
112*7101ab97SHuang Rui 	struct smu_context *smu = adev->powerplay.pp_handle;
113*7101ab97SHuang Rui 	int ret = -EOPNOTSUPP;
114*7101ab97SHuang Rui 
115*7101ab97SHuang Rui 	mutex_lock(&adev->pm.mutex);
116*7101ab97SHuang Rui 	ret = smu_set_gfx_power_up_by_imu(smu);
117*7101ab97SHuang Rui 	mutex_unlock(&adev->pm.mutex);
118*7101ab97SHuang Rui 
119*7101ab97SHuang Rui 	msleep(10);
120*7101ab97SHuang Rui 
121*7101ab97SHuang Rui 	return ret;
122*7101ab97SHuang Rui }
123*7101ab97SHuang Rui 
124e098bc96SEvan Quan int amdgpu_dpm_baco_enter(struct amdgpu_device *adev)
125e098bc96SEvan Quan {
126e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
127e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
128e098bc96SEvan Quan 	int ret = 0;
129e098bc96SEvan Quan 
130e098bc96SEvan Quan 	if (!pp_funcs || !pp_funcs->set_asic_baco_state)
131e098bc96SEvan Quan 		return -ENOENT;
132e098bc96SEvan Quan 
1333712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
1343712e7a4SEvan Quan 
135e098bc96SEvan Quan 	/* enter BACO state */
136e098bc96SEvan Quan 	ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
137e098bc96SEvan Quan 
1383712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
1393712e7a4SEvan Quan 
140e098bc96SEvan Quan 	return ret;
141e098bc96SEvan Quan }
142e098bc96SEvan Quan 
143e098bc96SEvan Quan int amdgpu_dpm_baco_exit(struct amdgpu_device *adev)
144e098bc96SEvan Quan {
145e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
146e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
147e098bc96SEvan Quan 	int ret = 0;
148e098bc96SEvan Quan 
149e098bc96SEvan Quan 	if (!pp_funcs || !pp_funcs->set_asic_baco_state)
150e098bc96SEvan Quan 		return -ENOENT;
151e098bc96SEvan Quan 
1523712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
1533712e7a4SEvan Quan 
154e098bc96SEvan Quan 	/* exit BACO state */
155e098bc96SEvan Quan 	ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
156e098bc96SEvan Quan 
1573712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
1583712e7a4SEvan Quan 
159e098bc96SEvan Quan 	return ret;
160e098bc96SEvan Quan }
161e098bc96SEvan Quan 
162e098bc96SEvan Quan int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
163e098bc96SEvan Quan 			     enum pp_mp1_state mp1_state)
164e098bc96SEvan Quan {
165e098bc96SEvan Quan 	int ret = 0;
166bab0f602SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
167e098bc96SEvan Quan 
168bab0f602SDarren Powell 	if (pp_funcs && pp_funcs->set_mp1_state) {
1693712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
1703712e7a4SEvan Quan 
171bab0f602SDarren Powell 		ret = pp_funcs->set_mp1_state(
172e098bc96SEvan Quan 				adev->powerplay.pp_handle,
173e098bc96SEvan Quan 				mp1_state);
1743712e7a4SEvan Quan 
1753712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
176e098bc96SEvan Quan 	}
177e098bc96SEvan Quan 
178e098bc96SEvan Quan 	return ret;
179e098bc96SEvan Quan }
180e098bc96SEvan Quan 
181e098bc96SEvan Quan bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev)
182e098bc96SEvan Quan {
183e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
184e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
185e098bc96SEvan Quan 	bool baco_cap;
1863712e7a4SEvan Quan 	int ret = 0;
187e098bc96SEvan Quan 
188e098bc96SEvan Quan 	if (!pp_funcs || !pp_funcs->get_asic_baco_capability)
189e098bc96SEvan Quan 		return false;
19034452ac3SAlex Deucher 	/* Don't use baco for reset in S3.
19134452ac3SAlex Deucher 	 * This is a workaround for some platforms
19234452ac3SAlex Deucher 	 * where entering BACO during suspend
19334452ac3SAlex Deucher 	 * seems to cause reboots or hangs.
19434452ac3SAlex Deucher 	 * This might be related to the fact that BACO controls
19534452ac3SAlex Deucher 	 * power to the whole GPU including devices like audio and USB.
19634452ac3SAlex Deucher 	 * Powering down/up everything may adversely affect these other
19734452ac3SAlex Deucher 	 * devices.  Needs more investigation.
19834452ac3SAlex Deucher 	 */
19934452ac3SAlex Deucher 	if (adev->in_s3)
20034452ac3SAlex Deucher 		return false;
201e098bc96SEvan Quan 
2023712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
203e098bc96SEvan Quan 
2043712e7a4SEvan Quan 	ret = pp_funcs->get_asic_baco_capability(pp_handle,
2053712e7a4SEvan Quan 						 &baco_cap);
2063712e7a4SEvan Quan 
2073712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
2083712e7a4SEvan Quan 
2093712e7a4SEvan Quan 	return ret ? false : baco_cap;
210e098bc96SEvan Quan }
211e098bc96SEvan Quan 
212e098bc96SEvan Quan int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev)
213e098bc96SEvan Quan {
214e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
215e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
2163712e7a4SEvan Quan 	int ret = 0;
217e098bc96SEvan Quan 
218e098bc96SEvan Quan 	if (!pp_funcs || !pp_funcs->asic_reset_mode_2)
219e098bc96SEvan Quan 		return -ENOENT;
220e098bc96SEvan Quan 
2213712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
2223712e7a4SEvan Quan 
2233712e7a4SEvan Quan 	ret = pp_funcs->asic_reset_mode_2(pp_handle);
2243712e7a4SEvan Quan 
2253712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
2263712e7a4SEvan Quan 
2273712e7a4SEvan Quan 	return ret;
228e098bc96SEvan Quan }
229e098bc96SEvan Quan 
230e098bc96SEvan Quan int amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
231e098bc96SEvan Quan {
232e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
233e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
234e098bc96SEvan Quan 	int ret = 0;
235e098bc96SEvan Quan 
2369ab5001aSDarren Powell 	if (!pp_funcs || !pp_funcs->set_asic_baco_state)
237e098bc96SEvan Quan 		return -ENOENT;
238e098bc96SEvan Quan 
2393712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
2403712e7a4SEvan Quan 
241e098bc96SEvan Quan 	/* enter BACO state */
242e098bc96SEvan Quan 	ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
243e098bc96SEvan Quan 	if (ret)
2443712e7a4SEvan Quan 		goto out;
245e098bc96SEvan Quan 
246e098bc96SEvan Quan 	/* exit BACO state */
247e098bc96SEvan Quan 	ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
248e098bc96SEvan Quan 
2493712e7a4SEvan Quan out:
2503712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
2513712e7a4SEvan Quan 	return ret;
252e098bc96SEvan Quan }
253e098bc96SEvan Quan 
254e098bc96SEvan Quan bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev)
255e098bc96SEvan Quan {
256ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
2573712e7a4SEvan Quan 	bool support_mode1_reset = false;
258e098bc96SEvan Quan 
2593712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
2603712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
2613712e7a4SEvan Quan 		support_mode1_reset = smu_mode1_reset_is_support(smu);
2623712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
2633712e7a4SEvan Quan 	}
264e098bc96SEvan Quan 
2653712e7a4SEvan Quan 	return support_mode1_reset;
266e098bc96SEvan Quan }
267e098bc96SEvan Quan 
268e098bc96SEvan Quan int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev)
269e098bc96SEvan Quan {
270ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
2713712e7a4SEvan Quan 	int ret = -EOPNOTSUPP;
272e098bc96SEvan Quan 
2733712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
2743712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
2753712e7a4SEvan Quan 		ret = smu_mode1_reset(smu);
2763712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
2773712e7a4SEvan Quan 	}
278e098bc96SEvan Quan 
2793712e7a4SEvan Quan 	return ret;
280e098bc96SEvan Quan }
281e098bc96SEvan Quan 
282e098bc96SEvan Quan int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
283e098bc96SEvan Quan 				    enum PP_SMC_POWER_PROFILE type,
284e098bc96SEvan Quan 				    bool en)
285e098bc96SEvan Quan {
286bab0f602SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
287e098bc96SEvan Quan 	int ret = 0;
288e098bc96SEvan Quan 
2897cf7a392SJingwen Chen 	if (amdgpu_sriov_vf(adev))
2907cf7a392SJingwen Chen 		return 0;
2917cf7a392SJingwen Chen 
2923712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->switch_power_profile) {
2933712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
294bab0f602SDarren Powell 		ret = pp_funcs->switch_power_profile(
295e098bc96SEvan Quan 			adev->powerplay.pp_handle, type, en);
2963712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
2973712e7a4SEvan Quan 	}
298e098bc96SEvan Quan 
299e098bc96SEvan Quan 	return ret;
300e098bc96SEvan Quan }
301e098bc96SEvan Quan 
302e098bc96SEvan Quan int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
303e098bc96SEvan Quan 			       uint32_t pstate)
304e098bc96SEvan Quan {
305bab0f602SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
306e098bc96SEvan Quan 	int ret = 0;
307e098bc96SEvan Quan 
3083712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->set_xgmi_pstate) {
3093712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
310bab0f602SDarren Powell 		ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle,
311e098bc96SEvan Quan 								pstate);
3123712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3133712e7a4SEvan Quan 	}
314e098bc96SEvan Quan 
315e098bc96SEvan Quan 	return ret;
316e098bc96SEvan Quan }
317e098bc96SEvan Quan 
318e098bc96SEvan Quan int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev,
319e098bc96SEvan Quan 			     uint32_t cstate)
320e098bc96SEvan Quan {
321e098bc96SEvan Quan 	int ret = 0;
322e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
323e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
324e098bc96SEvan Quan 
3253712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->set_df_cstate) {
3263712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
327e098bc96SEvan Quan 		ret = pp_funcs->set_df_cstate(pp_handle, cstate);
3283712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3293712e7a4SEvan Quan 	}
330e098bc96SEvan Quan 
331e098bc96SEvan Quan 	return ret;
332e098bc96SEvan Quan }
333e098bc96SEvan Quan 
334e098bc96SEvan Quan int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en)
335e098bc96SEvan Quan {
336ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
3373712e7a4SEvan Quan 	int ret = 0;
338e098bc96SEvan Quan 
3393712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
3403712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
3413712e7a4SEvan Quan 		ret = smu_allow_xgmi_power_down(smu, en);
3423712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3433712e7a4SEvan Quan 	}
344e098bc96SEvan Quan 
3453712e7a4SEvan Quan 	return ret;
346e098bc96SEvan Quan }
347e098bc96SEvan Quan 
348e098bc96SEvan Quan int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev)
349e098bc96SEvan Quan {
350e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
351e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs =
352e098bc96SEvan Quan 			adev->powerplay.pp_funcs;
353e098bc96SEvan Quan 	int ret = 0;
354e098bc96SEvan Quan 
3553712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) {
3563712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
357e098bc96SEvan Quan 		ret = pp_funcs->enable_mgpu_fan_boost(pp_handle);
3583712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3593712e7a4SEvan Quan 	}
360e098bc96SEvan Quan 
361e098bc96SEvan Quan 	return ret;
362e098bc96SEvan Quan }
363e098bc96SEvan Quan 
364e098bc96SEvan Quan int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev,
365e098bc96SEvan Quan 				      uint32_t msg_id)
366e098bc96SEvan Quan {
367e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
368e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs =
369e098bc96SEvan Quan 			adev->powerplay.pp_funcs;
370e098bc96SEvan Quan 	int ret = 0;
371e098bc96SEvan Quan 
3723712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->set_clockgating_by_smu) {
3733712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
374e098bc96SEvan Quan 		ret = pp_funcs->set_clockgating_by_smu(pp_handle,
375e098bc96SEvan Quan 						       msg_id);
3763712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3773712e7a4SEvan Quan 	}
378e098bc96SEvan Quan 
379e098bc96SEvan Quan 	return ret;
380e098bc96SEvan Quan }
381e098bc96SEvan Quan 
382e098bc96SEvan Quan int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev,
383e098bc96SEvan Quan 				  bool acquire)
384e098bc96SEvan Quan {
385e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
386e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs =
387e098bc96SEvan Quan 			adev->powerplay.pp_funcs;
388e098bc96SEvan Quan 	int ret = -EOPNOTSUPP;
389e098bc96SEvan Quan 
3903712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->smu_i2c_bus_access) {
3913712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
392e098bc96SEvan Quan 		ret = pp_funcs->smu_i2c_bus_access(pp_handle,
393e098bc96SEvan Quan 						   acquire);
3943712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3953712e7a4SEvan Quan 	}
396e098bc96SEvan Quan 
397e098bc96SEvan Quan 	return ret;
398e098bc96SEvan Quan }
399e098bc96SEvan Quan 
400e098bc96SEvan Quan void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
401e098bc96SEvan Quan {
402e098bc96SEvan Quan 	if (adev->pm.dpm_enabled) {
403e098bc96SEvan Quan 		mutex_lock(&adev->pm.mutex);
404e098bc96SEvan Quan 		if (power_supply_is_system_supplied() > 0)
405e098bc96SEvan Quan 			adev->pm.ac_power = true;
406e098bc96SEvan Quan 		else
407e098bc96SEvan Quan 			adev->pm.ac_power = false;
4083712e7a4SEvan Quan 
409e098bc96SEvan Quan 		if (adev->powerplay.pp_funcs &&
410e098bc96SEvan Quan 		    adev->powerplay.pp_funcs->enable_bapm)
411e098bc96SEvan Quan 			amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power);
412e098bc96SEvan Quan 
413e098bc96SEvan Quan 		if (is_support_sw_smu(adev))
414ebfc2533SEvan Quan 			smu_set_ac_dc(adev->powerplay.pp_handle);
4153712e7a4SEvan Quan 
4163712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
417e098bc96SEvan Quan 	}
418e098bc96SEvan Quan }
419e098bc96SEvan Quan 
420e098bc96SEvan Quan int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor,
421e098bc96SEvan Quan 			   void *data, uint32_t *size)
422e098bc96SEvan Quan {
4239ab5001aSDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
4243712e7a4SEvan Quan 	int ret = -EINVAL;
425e098bc96SEvan Quan 
426e098bc96SEvan Quan 	if (!data || !size)
427e098bc96SEvan Quan 		return -EINVAL;
428e098bc96SEvan Quan 
4293712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->read_sensor) {
4303712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
4313712e7a4SEvan Quan 		ret = pp_funcs->read_sensor(adev->powerplay.pp_handle,
4323712e7a4SEvan Quan 					    sensor,
4333712e7a4SEvan Quan 					    data,
4343712e7a4SEvan Quan 					    size);
4353712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
4363712e7a4SEvan Quan 	}
437e098bc96SEvan Quan 
438e098bc96SEvan Quan 	return ret;
439e098bc96SEvan Quan }
440e098bc96SEvan Quan 
44184176663SEvan Quan void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev)
442e098bc96SEvan Quan {
4436ddbd37fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
444a71849cdSEvan Quan 	int i;
445e098bc96SEvan Quan 
446e098bc96SEvan Quan 	if (!adev->pm.dpm_enabled)
447e098bc96SEvan Quan 		return;
448e098bc96SEvan Quan 
4496ddbd37fSEvan Quan 	if (!pp_funcs->pm_compute_clocks)
4506ddbd37fSEvan Quan 		return;
451e098bc96SEvan Quan 
452a71849cdSEvan Quan 	if (adev->mode_info.num_crtc)
453a71849cdSEvan Quan 		amdgpu_display_bandwidth_update(adev);
454a71849cdSEvan Quan 
455a71849cdSEvan Quan 	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
456a71849cdSEvan Quan 		struct amdgpu_ring *ring = adev->rings[i];
457a71849cdSEvan Quan 		if (ring && ring->sched.ready)
458a71849cdSEvan Quan 			amdgpu_fence_wait_empty(ring);
459a71849cdSEvan Quan 	}
460a71849cdSEvan Quan 
4613712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
4626ddbd37fSEvan Quan 	pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle);
4633712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
464e098bc96SEvan Quan }
465e098bc96SEvan Quan 
466e098bc96SEvan Quan void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
467e098bc96SEvan Quan {
468e098bc96SEvan Quan 	int ret = 0;
469e098bc96SEvan Quan 
470a71849cdSEvan Quan 	if (adev->family == AMDGPU_FAMILY_SI) {
471a71849cdSEvan Quan 		mutex_lock(&adev->pm.mutex);
472a71849cdSEvan Quan 		if (enable) {
473a71849cdSEvan Quan 			adev->pm.dpm.uvd_active = true;
474a71849cdSEvan Quan 			adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
475a71849cdSEvan Quan 		} else {
476a71849cdSEvan Quan 			adev->pm.dpm.uvd_active = false;
477a71849cdSEvan Quan 		}
478a71849cdSEvan Quan 		mutex_unlock(&adev->pm.mutex);
479a71849cdSEvan Quan 
480a71849cdSEvan Quan 		amdgpu_dpm_compute_clocks(adev);
481a71849cdSEvan Quan 		return;
482a71849cdSEvan Quan 	}
483a71849cdSEvan Quan 
484e098bc96SEvan Quan 	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable);
485e098bc96SEvan Quan 	if (ret)
486e098bc96SEvan Quan 		DRM_ERROR("Dpm %s uvd failed, ret = %d. \n",
487e098bc96SEvan Quan 			  enable ? "enable" : "disable", ret);
488e098bc96SEvan Quan }
489e098bc96SEvan Quan 
490e098bc96SEvan Quan void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
491e098bc96SEvan Quan {
492e098bc96SEvan Quan 	int ret = 0;
493e098bc96SEvan Quan 
494a71849cdSEvan Quan 	if (adev->family == AMDGPU_FAMILY_SI) {
495a71849cdSEvan Quan 		mutex_lock(&adev->pm.mutex);
496a71849cdSEvan Quan 		if (enable) {
497a71849cdSEvan Quan 			adev->pm.dpm.vce_active = true;
498a71849cdSEvan Quan 			/* XXX select vce level based on ring/task */
499a71849cdSEvan Quan 			adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
500a71849cdSEvan Quan 		} else {
501a71849cdSEvan Quan 			adev->pm.dpm.vce_active = false;
502a71849cdSEvan Quan 		}
503a71849cdSEvan Quan 		mutex_unlock(&adev->pm.mutex);
504a71849cdSEvan Quan 
505a71849cdSEvan Quan 		amdgpu_dpm_compute_clocks(adev);
506a71849cdSEvan Quan 		return;
507a71849cdSEvan Quan 	}
508a71849cdSEvan Quan 
509e098bc96SEvan Quan 	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable);
510e098bc96SEvan Quan 	if (ret)
511e098bc96SEvan Quan 		DRM_ERROR("Dpm %s vce failed, ret = %d. \n",
512e098bc96SEvan Quan 			  enable ? "enable" : "disable", ret);
513e098bc96SEvan Quan }
514e098bc96SEvan Quan 
515e098bc96SEvan Quan void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable)
516e098bc96SEvan Quan {
517e098bc96SEvan Quan 	int ret = 0;
518e098bc96SEvan Quan 
519e098bc96SEvan Quan 	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable);
520e098bc96SEvan Quan 	if (ret)
521e098bc96SEvan Quan 		DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n",
522e098bc96SEvan Quan 			  enable ? "enable" : "disable", ret);
523e098bc96SEvan Quan }
524e098bc96SEvan Quan 
525e098bc96SEvan Quan int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
526e098bc96SEvan Quan {
5273712e7a4SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
5283712e7a4SEvan Quan 	int r = 0;
529e098bc96SEvan Quan 
5301613f346SFlora Cui 	if (!pp_funcs || !pp_funcs->load_firmware)
5313712e7a4SEvan Quan 		return 0;
5323712e7a4SEvan Quan 
5333712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
5343712e7a4SEvan Quan 	r = pp_funcs->load_firmware(adev->powerplay.pp_handle);
535e098bc96SEvan Quan 	if (r) {
536e098bc96SEvan Quan 		pr_err("smu firmware loading failed\n");
5373712e7a4SEvan Quan 		goto out;
538e098bc96SEvan Quan 	}
5392e4b2f7bSEvan Quan 
5402e4b2f7bSEvan Quan 	if (smu_version)
541e098bc96SEvan Quan 		*smu_version = adev->pm.fw_version;
5422e4b2f7bSEvan Quan 
5433712e7a4SEvan Quan out:
5443712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
5453712e7a4SEvan Quan 	return r;
546e098bc96SEvan Quan }
547bc143d8bSEvan Quan 
548bc143d8bSEvan Quan int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable)
549bc143d8bSEvan Quan {
5503712e7a4SEvan Quan 	int ret = 0;
5513712e7a4SEvan Quan 
5523712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
5533712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
5543712e7a4SEvan Quan 		ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle,
5553712e7a4SEvan Quan 						 enable);
5563712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
5573712e7a4SEvan Quan 	}
5583712e7a4SEvan Quan 
5593712e7a4SEvan Quan 	return ret;
560bc143d8bSEvan Quan }
561bc143d8bSEvan Quan 
562bc143d8bSEvan Quan int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size)
563bc143d8bSEvan Quan {
564ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
5653712e7a4SEvan Quan 	int ret = 0;
566ebfc2533SEvan Quan 
56793dde6ccSStanley.Yang 	if (!is_support_sw_smu(adev))
56893dde6ccSStanley.Yang 		return -EOPNOTSUPP;
56993dde6ccSStanley.Yang 
5703712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
5713712e7a4SEvan Quan 	ret = smu_send_hbm_bad_pages_num(smu, size);
5723712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
5733712e7a4SEvan Quan 
5743712e7a4SEvan Quan 	return ret;
575bc143d8bSEvan Quan }
576bc143d8bSEvan Quan 
577d510eccfSStanley.Yang int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size)
578d510eccfSStanley.Yang {
579d510eccfSStanley.Yang 	struct smu_context *smu = adev->powerplay.pp_handle;
580d510eccfSStanley.Yang 	int ret = 0;
581d510eccfSStanley.Yang 
58293dde6ccSStanley.Yang 	if (!is_support_sw_smu(adev))
58393dde6ccSStanley.Yang 		return -EOPNOTSUPP;
58493dde6ccSStanley.Yang 
585d510eccfSStanley.Yang 	mutex_lock(&adev->pm.mutex);
586d510eccfSStanley.Yang 	ret = smu_send_hbm_bad_channel_flag(smu, size);
587d510eccfSStanley.Yang 	mutex_unlock(&adev->pm.mutex);
588d510eccfSStanley.Yang 
589d510eccfSStanley.Yang 	return ret;
590d510eccfSStanley.Yang }
591d510eccfSStanley.Yang 
592bc143d8bSEvan Quan int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev,
593bc143d8bSEvan Quan 				  enum pp_clock_type type,
594bc143d8bSEvan Quan 				  uint32_t *min,
595bc143d8bSEvan Quan 				  uint32_t *max)
596bc143d8bSEvan Quan {
5973712e7a4SEvan Quan 	int ret = 0;
5983712e7a4SEvan Quan 
5993712e7a4SEvan Quan 	if (type != PP_SCLK)
6003712e7a4SEvan Quan 		return -EINVAL;
6013712e7a4SEvan Quan 
602bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
603bc143d8bSEvan Quan 		return -EOPNOTSUPP;
604bc143d8bSEvan Quan 
6053712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6063712e7a4SEvan Quan 	ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle,
6073712e7a4SEvan Quan 				     SMU_SCLK,
6083712e7a4SEvan Quan 				     min,
6093712e7a4SEvan Quan 				     max);
6103712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6113712e7a4SEvan Quan 
6123712e7a4SEvan Quan 	return ret;
613bc143d8bSEvan Quan }
614bc143d8bSEvan Quan 
615bc143d8bSEvan Quan int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev,
616bc143d8bSEvan Quan 				   enum pp_clock_type type,
617bc143d8bSEvan Quan 				   uint32_t min,
618bc143d8bSEvan Quan 				   uint32_t max)
619bc143d8bSEvan Quan {
620ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6213712e7a4SEvan Quan 	int ret = 0;
6223712e7a4SEvan Quan 
6233712e7a4SEvan Quan 	if (type != PP_SCLK)
6243712e7a4SEvan Quan 		return -EINVAL;
625ebfc2533SEvan Quan 
626bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
627bc143d8bSEvan Quan 		return -EOPNOTSUPP;
628bc143d8bSEvan Quan 
6293712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6303712e7a4SEvan Quan 	ret = smu_set_soft_freq_range(smu,
6313712e7a4SEvan Quan 				      SMU_SCLK,
6323712e7a4SEvan Quan 				      min,
6333712e7a4SEvan Quan 				      max);
6343712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6353712e7a4SEvan Quan 
6363712e7a4SEvan Quan 	return ret;
637bc143d8bSEvan Quan }
638bc143d8bSEvan Quan 
63913f5dbd6SEvan Quan int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev)
64013f5dbd6SEvan Quan {
641ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6423712e7a4SEvan Quan 	int ret = 0;
643ebfc2533SEvan Quan 
64413f5dbd6SEvan Quan 	if (!is_support_sw_smu(adev))
64513f5dbd6SEvan Quan 		return 0;
64613f5dbd6SEvan Quan 
6473712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6483712e7a4SEvan Quan 	ret = smu_write_watermarks_table(smu);
6493712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6503712e7a4SEvan Quan 
6513712e7a4SEvan Quan 	return ret;
65213f5dbd6SEvan Quan }
65313f5dbd6SEvan Quan 
654bc143d8bSEvan Quan int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev,
655bc143d8bSEvan Quan 			      enum smu_event_type event,
656bc143d8bSEvan Quan 			      uint64_t event_arg)
657bc143d8bSEvan Quan {
658ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6593712e7a4SEvan Quan 	int ret = 0;
660ebfc2533SEvan Quan 
661bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
662bc143d8bSEvan Quan 		return -EOPNOTSUPP;
663bc143d8bSEvan Quan 
6643712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6653712e7a4SEvan Quan 	ret = smu_wait_for_event(smu, event, event_arg);
6663712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6673712e7a4SEvan Quan 
6683712e7a4SEvan Quan 	return ret;
669bc143d8bSEvan Quan }
670bc143d8bSEvan Quan 
671bc143d8bSEvan Quan int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value)
672bc143d8bSEvan Quan {
673ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6743712e7a4SEvan Quan 	int ret = 0;
675ebfc2533SEvan Quan 
676bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
677bc143d8bSEvan Quan 		return -EOPNOTSUPP;
678bc143d8bSEvan Quan 
6793712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6803712e7a4SEvan Quan 	ret = smu_get_status_gfxoff(smu, value);
6813712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6823712e7a4SEvan Quan 
6833712e7a4SEvan Quan 	return ret;
684bc143d8bSEvan Quan }
685bc143d8bSEvan Quan 
686bc143d8bSEvan Quan uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev)
687bc143d8bSEvan Quan {
688ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
689ebfc2533SEvan Quan 
6903712e7a4SEvan Quan 	if (!is_support_sw_smu(adev))
6913712e7a4SEvan Quan 		return 0;
6923712e7a4SEvan Quan 
693ebfc2533SEvan Quan 	return atomic64_read(&smu->throttle_int_counter);
694bc143d8bSEvan Quan }
695bc143d8bSEvan Quan 
696bc143d8bSEvan Quan /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set
697bc143d8bSEvan Quan  * @adev: amdgpu_device pointer
698bc143d8bSEvan Quan  * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry)
699bc143d8bSEvan Quan  *
700bc143d8bSEvan Quan  */
701bc143d8bSEvan Quan void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev,
702bc143d8bSEvan Quan 				 enum gfx_change_state state)
703bc143d8bSEvan Quan {
704bc143d8bSEvan Quan 	mutex_lock(&adev->pm.mutex);
705bc143d8bSEvan Quan 	if (adev->powerplay.pp_funcs &&
706bc143d8bSEvan Quan 	    adev->powerplay.pp_funcs->gfx_state_change_set)
707bc143d8bSEvan Quan 		((adev)->powerplay.pp_funcs->gfx_state_change_set(
708bc143d8bSEvan Quan 			(adev)->powerplay.pp_handle, state));
709bc143d8bSEvan Quan 	mutex_unlock(&adev->pm.mutex);
710bc143d8bSEvan Quan }
711bc143d8bSEvan Quan 
712bc143d8bSEvan Quan int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev,
713bc143d8bSEvan Quan 			    void *umc_ecc)
714bc143d8bSEvan Quan {
715ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
716a29d44aeSStanley.Yang 	int ret = 0;
717ebfc2533SEvan Quan 
718bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
719bc143d8bSEvan Quan 		return -EOPNOTSUPP;
720bc143d8bSEvan Quan 
721a29d44aeSStanley.Yang 	mutex_lock(&adev->pm.mutex);
722a29d44aeSStanley.Yang 	ret = smu_get_ecc_info(smu, umc_ecc);
723a29d44aeSStanley.Yang 	mutex_unlock(&adev->pm.mutex);
724a29d44aeSStanley.Yang 
725a29d44aeSStanley.Yang 	return ret;
726bc143d8bSEvan Quan }
72779c65f3fSEvan Quan 
72879c65f3fSEvan Quan struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev,
72979c65f3fSEvan Quan 						     uint32_t idx)
73079c65f3fSEvan Quan {
73179c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
7323712e7a4SEvan Quan 	struct amd_vce_state *vstate = NULL;
73379c65f3fSEvan Quan 
73479c65f3fSEvan Quan 	if (!pp_funcs->get_vce_clock_state)
73579c65f3fSEvan Quan 		return NULL;
73679c65f3fSEvan Quan 
7373712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
7383712e7a4SEvan Quan 	vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle,
73979c65f3fSEvan Quan 					       idx);
7403712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
7413712e7a4SEvan Quan 
7423712e7a4SEvan Quan 	return vstate;
74379c65f3fSEvan Quan }
74479c65f3fSEvan Quan 
74579c65f3fSEvan Quan void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev,
74679c65f3fSEvan Quan 					enum amd_pm_state_type *state)
74779c65f3fSEvan Quan {
74879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
74979c65f3fSEvan Quan 
7503712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
7513712e7a4SEvan Quan 
75279c65f3fSEvan Quan 	if (!pp_funcs->get_current_power_state) {
75379c65f3fSEvan Quan 		*state = adev->pm.dpm.user_state;
7543712e7a4SEvan Quan 		goto out;
75579c65f3fSEvan Quan 	}
75679c65f3fSEvan Quan 
75779c65f3fSEvan Quan 	*state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle);
75879c65f3fSEvan Quan 	if (*state < POWER_STATE_TYPE_DEFAULT ||
75979c65f3fSEvan Quan 	    *state > POWER_STATE_TYPE_INTERNAL_3DPERF)
76079c65f3fSEvan Quan 		*state = adev->pm.dpm.user_state;
7613712e7a4SEvan Quan 
7623712e7a4SEvan Quan out:
7633712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
76479c65f3fSEvan Quan }
76579c65f3fSEvan Quan 
76679c65f3fSEvan Quan void amdgpu_dpm_set_power_state(struct amdgpu_device *adev,
76779c65f3fSEvan Quan 				enum amd_pm_state_type state)
76879c65f3fSEvan Quan {
7693712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
77079c65f3fSEvan Quan 	adev->pm.dpm.user_state = state;
7713712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
77279c65f3fSEvan Quan 
77379c65f3fSEvan Quan 	if (is_support_sw_smu(adev))
77479c65f3fSEvan Quan 		return;
77579c65f3fSEvan Quan 
77679c65f3fSEvan Quan 	if (amdgpu_dpm_dispatch_task(adev,
77779c65f3fSEvan Quan 				     AMD_PP_TASK_ENABLE_USER_STATE,
77879c65f3fSEvan Quan 				     &state) == -EOPNOTSUPP)
77984176663SEvan Quan 		amdgpu_dpm_compute_clocks(adev);
78079c65f3fSEvan Quan }
78179c65f3fSEvan Quan 
78275513bf5SEvan Quan enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev)
78379c65f3fSEvan Quan {
78479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
78579c65f3fSEvan Quan 	enum amd_dpm_forced_level level;
78679c65f3fSEvan Quan 
78739dbde65SLijo Lazar 	if (!pp_funcs)
78839dbde65SLijo Lazar 		return AMD_DPM_FORCED_LEVEL_AUTO;
78939dbde65SLijo Lazar 
79075513bf5SEvan Quan 	mutex_lock(&adev->pm.mutex);
79179c65f3fSEvan Quan 	if (pp_funcs->get_performance_level)
79279c65f3fSEvan Quan 		level = pp_funcs->get_performance_level(adev->powerplay.pp_handle);
79379c65f3fSEvan Quan 	else
79479c65f3fSEvan Quan 		level = adev->pm.dpm.forced_level;
7953712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
79679c65f3fSEvan Quan 
79779c65f3fSEvan Quan 	return level;
79879c65f3fSEvan Quan }
79979c65f3fSEvan Quan 
80079c65f3fSEvan Quan int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
80179c65f3fSEvan Quan 				       enum amd_dpm_forced_level level)
80279c65f3fSEvan Quan {
80379c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
80454c73b51SAlex Deucher 	enum amd_dpm_forced_level current_level;
80554c73b51SAlex Deucher 	uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
80654c73b51SAlex Deucher 					AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
80754c73b51SAlex Deucher 					AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
80854c73b51SAlex Deucher 					AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
80979c65f3fSEvan Quan 
810eea5c7b3SHuang Rui 	if (!pp_funcs || !pp_funcs->force_performance_level)
8113712e7a4SEvan Quan 		return 0;
8123712e7a4SEvan Quan 
81375513bf5SEvan Quan 	if (adev->pm.dpm.thermal_active)
81475513bf5SEvan Quan 		return -EINVAL;
8153712e7a4SEvan Quan 
81675513bf5SEvan Quan 	current_level = amdgpu_dpm_get_performance_level(adev);
81775513bf5SEvan Quan 	if (current_level == level)
81875513bf5SEvan Quan 		return 0;
81954c73b51SAlex Deucher 
82054c73b51SAlex Deucher 	if (adev->asic_type == CHIP_RAVEN) {
82154c73b51SAlex Deucher 		if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) {
82254c73b51SAlex Deucher 			if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
82354c73b51SAlex Deucher 			    level == AMD_DPM_FORCED_LEVEL_MANUAL)
82454c73b51SAlex Deucher 				amdgpu_gfx_off_ctrl(adev, false);
82554c73b51SAlex Deucher 			else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL &&
82654c73b51SAlex Deucher 				 level != AMD_DPM_FORCED_LEVEL_MANUAL)
82754c73b51SAlex Deucher 				amdgpu_gfx_off_ctrl(adev, true);
82854c73b51SAlex Deucher 		}
82954c73b51SAlex Deucher 	}
83054c73b51SAlex Deucher 
83154c73b51SAlex Deucher 	if (!(current_level & profile_mode_mask) &&
83275513bf5SEvan Quan 	    (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT))
83375513bf5SEvan Quan 		return -EINVAL;
83454c73b51SAlex Deucher 
83554c73b51SAlex Deucher 	if (!(current_level & profile_mode_mask) &&
83654c73b51SAlex Deucher 	      (level & profile_mode_mask)) {
83754c73b51SAlex Deucher 		/* enter UMD Pstate */
83854c73b51SAlex Deucher 		amdgpu_device_ip_set_powergating_state(adev,
83954c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
84054c73b51SAlex Deucher 						       AMD_PG_STATE_UNGATE);
84154c73b51SAlex Deucher 		amdgpu_device_ip_set_clockgating_state(adev,
84254c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
84354c73b51SAlex Deucher 						       AMD_CG_STATE_UNGATE);
84454c73b51SAlex Deucher 	} else if ((current_level & profile_mode_mask) &&
84554c73b51SAlex Deucher 		    !(level & profile_mode_mask)) {
84654c73b51SAlex Deucher 		/* exit UMD Pstate */
84754c73b51SAlex Deucher 		amdgpu_device_ip_set_clockgating_state(adev,
84854c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
84954c73b51SAlex Deucher 						       AMD_CG_STATE_GATE);
85054c73b51SAlex Deucher 		amdgpu_device_ip_set_powergating_state(adev,
85154c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
85254c73b51SAlex Deucher 						       AMD_PG_STATE_GATE);
85354c73b51SAlex Deucher 	}
85454c73b51SAlex Deucher 
85575513bf5SEvan Quan 	mutex_lock(&adev->pm.mutex);
85679c65f3fSEvan Quan 
85775513bf5SEvan Quan 	if (pp_funcs->force_performance_level(adev->powerplay.pp_handle,
85875513bf5SEvan Quan 					      level)) {
85975513bf5SEvan Quan 		mutex_unlock(&adev->pm.mutex);
86075513bf5SEvan Quan 		return -EINVAL;
86175513bf5SEvan Quan 	}
86275513bf5SEvan Quan 
86379c65f3fSEvan Quan 	adev->pm.dpm.forced_level = level;
86479c65f3fSEvan Quan 
8653712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
8663712e7a4SEvan Quan 
86775513bf5SEvan Quan 	return 0;
86879c65f3fSEvan Quan }
86979c65f3fSEvan Quan 
87079c65f3fSEvan Quan int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev,
87179c65f3fSEvan Quan 				 struct pp_states_info *states)
87279c65f3fSEvan Quan {
87379c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
8743712e7a4SEvan Quan 	int ret = 0;
87579c65f3fSEvan Quan 
87679c65f3fSEvan Quan 	if (!pp_funcs->get_pp_num_states)
87779c65f3fSEvan Quan 		return -EOPNOTSUPP;
87879c65f3fSEvan Quan 
8793712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
8803712e7a4SEvan Quan 	ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle,
8813712e7a4SEvan Quan 					  states);
8823712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
8833712e7a4SEvan Quan 
8843712e7a4SEvan Quan 	return ret;
88579c65f3fSEvan Quan }
88679c65f3fSEvan Quan 
88779c65f3fSEvan Quan int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev,
88879c65f3fSEvan Quan 			      enum amd_pp_task task_id,
88979c65f3fSEvan Quan 			      enum amd_pm_state_type *user_state)
89079c65f3fSEvan Quan {
89179c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
8923712e7a4SEvan Quan 	int ret = 0;
89379c65f3fSEvan Quan 
89479c65f3fSEvan Quan 	if (!pp_funcs->dispatch_tasks)
89579c65f3fSEvan Quan 		return -EOPNOTSUPP;
89679c65f3fSEvan Quan 
8973712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
8983712e7a4SEvan Quan 	ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle,
8993712e7a4SEvan Quan 				       task_id,
9003712e7a4SEvan Quan 				       user_state);
9013712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9023712e7a4SEvan Quan 
9033712e7a4SEvan Quan 	return ret;
90479c65f3fSEvan Quan }
90579c65f3fSEvan Quan 
90679c65f3fSEvan Quan int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table)
90779c65f3fSEvan Quan {
90879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9093712e7a4SEvan Quan 	int ret = 0;
91079c65f3fSEvan Quan 
91179c65f3fSEvan Quan 	if (!pp_funcs->get_pp_table)
91279c65f3fSEvan Quan 		return 0;
91379c65f3fSEvan Quan 
9143712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
9153712e7a4SEvan Quan 	ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle,
9163712e7a4SEvan Quan 				     table);
9173712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9183712e7a4SEvan Quan 
9193712e7a4SEvan Quan 	return ret;
92079c65f3fSEvan Quan }
92179c65f3fSEvan Quan 
92279c65f3fSEvan Quan int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev,
92379c65f3fSEvan Quan 				      uint32_t type,
92479c65f3fSEvan Quan 				      long *input,
92579c65f3fSEvan Quan 				      uint32_t size)
92679c65f3fSEvan Quan {
92779c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9283712e7a4SEvan Quan 	int ret = 0;
92979c65f3fSEvan Quan 
93079c65f3fSEvan Quan 	if (!pp_funcs->set_fine_grain_clk_vol)
93179c65f3fSEvan Quan 		return 0;
93279c65f3fSEvan Quan 
9333712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
9343712e7a4SEvan Quan 	ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle,
93579c65f3fSEvan Quan 					       type,
93679c65f3fSEvan Quan 					       input,
93779c65f3fSEvan Quan 					       size);
9383712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9393712e7a4SEvan Quan 
9403712e7a4SEvan Quan 	return ret;
94179c65f3fSEvan Quan }
94279c65f3fSEvan Quan 
94379c65f3fSEvan Quan int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev,
94479c65f3fSEvan Quan 				  uint32_t type,
94579c65f3fSEvan Quan 				  long *input,
94679c65f3fSEvan Quan 				  uint32_t size)
94779c65f3fSEvan Quan {
94879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9493712e7a4SEvan Quan 	int ret = 0;
95079c65f3fSEvan Quan 
95179c65f3fSEvan Quan 	if (!pp_funcs->odn_edit_dpm_table)
95279c65f3fSEvan Quan 		return 0;
95379c65f3fSEvan Quan 
9543712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
9553712e7a4SEvan Quan 	ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle,
95679c65f3fSEvan Quan 					   type,
95779c65f3fSEvan Quan 					   input,
95879c65f3fSEvan Quan 					   size);
9593712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9603712e7a4SEvan Quan 
9613712e7a4SEvan Quan 	return ret;
96279c65f3fSEvan Quan }
96379c65f3fSEvan Quan 
96479c65f3fSEvan Quan int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
96579c65f3fSEvan Quan 				  enum pp_clock_type type,
96679c65f3fSEvan Quan 				  char *buf)
96779c65f3fSEvan Quan {
96879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9693712e7a4SEvan Quan 	int ret = 0;
97079c65f3fSEvan Quan 
97179c65f3fSEvan Quan 	if (!pp_funcs->print_clock_levels)
97279c65f3fSEvan Quan 		return 0;
97379c65f3fSEvan Quan 
9743712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
9753712e7a4SEvan Quan 	ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle,
97679c65f3fSEvan Quan 					   type,
97779c65f3fSEvan Quan 					   buf);
9783712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9793712e7a4SEvan Quan 
9803712e7a4SEvan Quan 	return ret;
98179c65f3fSEvan Quan }
98279c65f3fSEvan Quan 
9835d64f9bbSDarren Powell int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev,
9845d64f9bbSDarren Powell 				  enum pp_clock_type type,
9855d64f9bbSDarren Powell 				  char *buf,
9865d64f9bbSDarren Powell 				  int *offset)
9875d64f9bbSDarren Powell {
9885d64f9bbSDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9895d64f9bbSDarren Powell 	int ret = 0;
9905d64f9bbSDarren Powell 
9915d64f9bbSDarren Powell 	if (!pp_funcs->emit_clock_levels)
9925d64f9bbSDarren Powell 		return -ENOENT;
9935d64f9bbSDarren Powell 
9945d64f9bbSDarren Powell 	mutex_lock(&adev->pm.mutex);
9955d64f9bbSDarren Powell 	ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle,
9965d64f9bbSDarren Powell 					   type,
9975d64f9bbSDarren Powell 					   buf,
9985d64f9bbSDarren Powell 					   offset);
9995d64f9bbSDarren Powell 	mutex_unlock(&adev->pm.mutex);
10005d64f9bbSDarren Powell 
10015d64f9bbSDarren Powell 	return ret;
10025d64f9bbSDarren Powell }
10035d64f9bbSDarren Powell 
100479c65f3fSEvan Quan int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
100579c65f3fSEvan Quan 				    uint64_t ppfeature_masks)
100679c65f3fSEvan Quan {
100779c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10083712e7a4SEvan Quan 	int ret = 0;
100979c65f3fSEvan Quan 
101079c65f3fSEvan Quan 	if (!pp_funcs->set_ppfeature_status)
101179c65f3fSEvan Quan 		return 0;
101279c65f3fSEvan Quan 
10133712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10143712e7a4SEvan Quan 	ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle,
101579c65f3fSEvan Quan 					     ppfeature_masks);
10163712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10173712e7a4SEvan Quan 
10183712e7a4SEvan Quan 	return ret;
101979c65f3fSEvan Quan }
102079c65f3fSEvan Quan 
102179c65f3fSEvan Quan int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf)
102279c65f3fSEvan Quan {
102379c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10243712e7a4SEvan Quan 	int ret = 0;
102579c65f3fSEvan Quan 
102679c65f3fSEvan Quan 	if (!pp_funcs->get_ppfeature_status)
102779c65f3fSEvan Quan 		return 0;
102879c65f3fSEvan Quan 
10293712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10303712e7a4SEvan Quan 	ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle,
103179c65f3fSEvan Quan 					     buf);
10323712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10333712e7a4SEvan Quan 
10343712e7a4SEvan Quan 	return ret;
103579c65f3fSEvan Quan }
103679c65f3fSEvan Quan 
103779c65f3fSEvan Quan int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev,
103879c65f3fSEvan Quan 				 enum pp_clock_type type,
103979c65f3fSEvan Quan 				 uint32_t mask)
104079c65f3fSEvan Quan {
104179c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10423712e7a4SEvan Quan 	int ret = 0;
104379c65f3fSEvan Quan 
104479c65f3fSEvan Quan 	if (!pp_funcs->force_clock_level)
104579c65f3fSEvan Quan 		return 0;
104679c65f3fSEvan Quan 
10473712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10483712e7a4SEvan Quan 	ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle,
104979c65f3fSEvan Quan 					  type,
105079c65f3fSEvan Quan 					  mask);
10513712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10523712e7a4SEvan Quan 
10533712e7a4SEvan Quan 	return ret;
105479c65f3fSEvan Quan }
105579c65f3fSEvan Quan 
105679c65f3fSEvan Quan int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev)
105779c65f3fSEvan Quan {
105879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10593712e7a4SEvan Quan 	int ret = 0;
106079c65f3fSEvan Quan 
106179c65f3fSEvan Quan 	if (!pp_funcs->get_sclk_od)
106279c65f3fSEvan Quan 		return 0;
106379c65f3fSEvan Quan 
10643712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10653712e7a4SEvan Quan 	ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle);
10663712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10673712e7a4SEvan Quan 
10683712e7a4SEvan Quan 	return ret;
106979c65f3fSEvan Quan }
107079c65f3fSEvan Quan 
107179c65f3fSEvan Quan int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value)
107279c65f3fSEvan Quan {
107379c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
107479c65f3fSEvan Quan 
107579c65f3fSEvan Quan 	if (is_support_sw_smu(adev))
107679c65f3fSEvan Quan 		return 0;
107779c65f3fSEvan Quan 
10783712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
107979c65f3fSEvan Quan 	if (pp_funcs->set_sclk_od)
108079c65f3fSEvan Quan 		pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value);
10813712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
108279c65f3fSEvan Quan 
108379c65f3fSEvan Quan 	if (amdgpu_dpm_dispatch_task(adev,
108479c65f3fSEvan Quan 				     AMD_PP_TASK_READJUST_POWER_STATE,
108579c65f3fSEvan Quan 				     NULL) == -EOPNOTSUPP) {
108679c65f3fSEvan Quan 		adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
108784176663SEvan Quan 		amdgpu_dpm_compute_clocks(adev);
108879c65f3fSEvan Quan 	}
108979c65f3fSEvan Quan 
109079c65f3fSEvan Quan 	return 0;
109179c65f3fSEvan Quan }
109279c65f3fSEvan Quan 
109379c65f3fSEvan Quan int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev)
109479c65f3fSEvan Quan {
109579c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10963712e7a4SEvan Quan 	int ret = 0;
109779c65f3fSEvan Quan 
109879c65f3fSEvan Quan 	if (!pp_funcs->get_mclk_od)
109979c65f3fSEvan Quan 		return 0;
110079c65f3fSEvan Quan 
11013712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11023712e7a4SEvan Quan 	ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle);
11033712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11043712e7a4SEvan Quan 
11053712e7a4SEvan Quan 	return ret;
110679c65f3fSEvan Quan }
110779c65f3fSEvan Quan 
110879c65f3fSEvan Quan int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value)
110979c65f3fSEvan Quan {
111079c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
111179c65f3fSEvan Quan 
111279c65f3fSEvan Quan 	if (is_support_sw_smu(adev))
111379c65f3fSEvan Quan 		return 0;
111479c65f3fSEvan Quan 
11153712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
111679c65f3fSEvan Quan 	if (pp_funcs->set_mclk_od)
111779c65f3fSEvan Quan 		pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value);
11183712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
111979c65f3fSEvan Quan 
112079c65f3fSEvan Quan 	if (amdgpu_dpm_dispatch_task(adev,
112179c65f3fSEvan Quan 				     AMD_PP_TASK_READJUST_POWER_STATE,
112279c65f3fSEvan Quan 				     NULL) == -EOPNOTSUPP) {
112379c65f3fSEvan Quan 		adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
112484176663SEvan Quan 		amdgpu_dpm_compute_clocks(adev);
112579c65f3fSEvan Quan 	}
112679c65f3fSEvan Quan 
112779c65f3fSEvan Quan 	return 0;
112879c65f3fSEvan Quan }
112979c65f3fSEvan Quan 
113079c65f3fSEvan Quan int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev,
113179c65f3fSEvan Quan 				      char *buf)
113279c65f3fSEvan Quan {
113379c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11343712e7a4SEvan Quan 	int ret = 0;
113579c65f3fSEvan Quan 
113679c65f3fSEvan Quan 	if (!pp_funcs->get_power_profile_mode)
113779c65f3fSEvan Quan 		return -EOPNOTSUPP;
113879c65f3fSEvan Quan 
11393712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11403712e7a4SEvan Quan 	ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle,
114179c65f3fSEvan Quan 					       buf);
11423712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11433712e7a4SEvan Quan 
11443712e7a4SEvan Quan 	return ret;
114579c65f3fSEvan Quan }
114679c65f3fSEvan Quan 
114779c65f3fSEvan Quan int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev,
114879c65f3fSEvan Quan 				      long *input, uint32_t size)
114979c65f3fSEvan Quan {
115079c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11513712e7a4SEvan Quan 	int ret = 0;
115279c65f3fSEvan Quan 
115379c65f3fSEvan Quan 	if (!pp_funcs->set_power_profile_mode)
115479c65f3fSEvan Quan 		return 0;
115579c65f3fSEvan Quan 
11563712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11573712e7a4SEvan Quan 	ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle,
115879c65f3fSEvan Quan 					       input,
115979c65f3fSEvan Quan 					       size);
11603712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11613712e7a4SEvan Quan 
11623712e7a4SEvan Quan 	return ret;
116379c65f3fSEvan Quan }
116479c65f3fSEvan Quan 
116579c65f3fSEvan Quan int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table)
116679c65f3fSEvan Quan {
116779c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11683712e7a4SEvan Quan 	int ret = 0;
116979c65f3fSEvan Quan 
117079c65f3fSEvan Quan 	if (!pp_funcs->get_gpu_metrics)
117179c65f3fSEvan Quan 		return 0;
117279c65f3fSEvan Quan 
11733712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11743712e7a4SEvan Quan 	ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle,
11753712e7a4SEvan Quan 					table);
11763712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11773712e7a4SEvan Quan 
11783712e7a4SEvan Quan 	return ret;
117979c65f3fSEvan Quan }
118079c65f3fSEvan Quan 
118179c65f3fSEvan Quan int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev,
118279c65f3fSEvan Quan 				    uint32_t *fan_mode)
118379c65f3fSEvan Quan {
118479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1185685fae24SEvan Quan 	int ret = 0;
118679c65f3fSEvan Quan 
118779c65f3fSEvan Quan 	if (!pp_funcs->get_fan_control_mode)
118879c65f3fSEvan Quan 		return -EOPNOTSUPP;
118979c65f3fSEvan Quan 
11903712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
1191685fae24SEvan Quan 	ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle,
1192685fae24SEvan Quan 					     fan_mode);
11933712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
119479c65f3fSEvan Quan 
1195685fae24SEvan Quan 	return ret;
119679c65f3fSEvan Quan }
119779c65f3fSEvan Quan 
119879c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev,
119979c65f3fSEvan Quan 				 uint32_t speed)
120079c65f3fSEvan Quan {
120179c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12023712e7a4SEvan Quan 	int ret = 0;
120379c65f3fSEvan Quan 
120479c65f3fSEvan Quan 	if (!pp_funcs->set_fan_speed_pwm)
1205685fae24SEvan Quan 		return -EOPNOTSUPP;
120679c65f3fSEvan Quan 
12073712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12083712e7a4SEvan Quan 	ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle,
12093712e7a4SEvan Quan 					  speed);
12103712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12113712e7a4SEvan Quan 
12123712e7a4SEvan Quan 	return ret;
121379c65f3fSEvan Quan }
121479c65f3fSEvan Quan 
121579c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev,
121679c65f3fSEvan Quan 				 uint32_t *speed)
121779c65f3fSEvan Quan {
121879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12193712e7a4SEvan Quan 	int ret = 0;
122079c65f3fSEvan Quan 
122179c65f3fSEvan Quan 	if (!pp_funcs->get_fan_speed_pwm)
1222685fae24SEvan Quan 		return -EOPNOTSUPP;
122379c65f3fSEvan Quan 
12243712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12253712e7a4SEvan Quan 	ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle,
12263712e7a4SEvan Quan 					  speed);
12273712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12283712e7a4SEvan Quan 
12293712e7a4SEvan Quan 	return ret;
123079c65f3fSEvan Quan }
123179c65f3fSEvan Quan 
123279c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev,
123379c65f3fSEvan Quan 				 uint32_t *speed)
123479c65f3fSEvan Quan {
123579c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12363712e7a4SEvan Quan 	int ret = 0;
123779c65f3fSEvan Quan 
123879c65f3fSEvan Quan 	if (!pp_funcs->get_fan_speed_rpm)
1239685fae24SEvan Quan 		return -EOPNOTSUPP;
124079c65f3fSEvan Quan 
12413712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12423712e7a4SEvan Quan 	ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle,
12433712e7a4SEvan Quan 					  speed);
12443712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12453712e7a4SEvan Quan 
12463712e7a4SEvan Quan 	return ret;
124779c65f3fSEvan Quan }
124879c65f3fSEvan Quan 
124979c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev,
125079c65f3fSEvan Quan 				 uint32_t speed)
125179c65f3fSEvan Quan {
125279c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12533712e7a4SEvan Quan 	int ret = 0;
125479c65f3fSEvan Quan 
125579c65f3fSEvan Quan 	if (!pp_funcs->set_fan_speed_rpm)
1256685fae24SEvan Quan 		return -EOPNOTSUPP;
125779c65f3fSEvan Quan 
12583712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12593712e7a4SEvan Quan 	ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle,
12603712e7a4SEvan Quan 					  speed);
12613712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12623712e7a4SEvan Quan 
12633712e7a4SEvan Quan 	return ret;
126479c65f3fSEvan Quan }
126579c65f3fSEvan Quan 
126679c65f3fSEvan Quan int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev,
126779c65f3fSEvan Quan 				    uint32_t mode)
126879c65f3fSEvan Quan {
126979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1270685fae24SEvan Quan 	int ret = 0;
127179c65f3fSEvan Quan 
127279c65f3fSEvan Quan 	if (!pp_funcs->set_fan_control_mode)
127379c65f3fSEvan Quan 		return -EOPNOTSUPP;
127479c65f3fSEvan Quan 
12753712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
1276685fae24SEvan Quan 	ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle,
12773712e7a4SEvan Quan 					     mode);
12783712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
127979c65f3fSEvan Quan 
1280685fae24SEvan Quan 	return ret;
128179c65f3fSEvan Quan }
128279c65f3fSEvan Quan 
128379c65f3fSEvan Quan int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev,
128479c65f3fSEvan Quan 			       uint32_t *limit,
128579c65f3fSEvan Quan 			       enum pp_power_limit_level pp_limit_level,
128679c65f3fSEvan Quan 			       enum pp_power_type power_type)
128779c65f3fSEvan Quan {
128879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12893712e7a4SEvan Quan 	int ret = 0;
129079c65f3fSEvan Quan 
129179c65f3fSEvan Quan 	if (!pp_funcs->get_power_limit)
129279c65f3fSEvan Quan 		return -ENODATA;
129379c65f3fSEvan Quan 
12943712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12953712e7a4SEvan Quan 	ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle,
129679c65f3fSEvan Quan 					limit,
129779c65f3fSEvan Quan 					pp_limit_level,
129879c65f3fSEvan Quan 					power_type);
12993712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13003712e7a4SEvan Quan 
13013712e7a4SEvan Quan 	return ret;
130279c65f3fSEvan Quan }
130379c65f3fSEvan Quan 
130479c65f3fSEvan Quan int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev,
130579c65f3fSEvan Quan 			       uint32_t limit)
130679c65f3fSEvan Quan {
130779c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13083712e7a4SEvan Quan 	int ret = 0;
130979c65f3fSEvan Quan 
131079c65f3fSEvan Quan 	if (!pp_funcs->set_power_limit)
131179c65f3fSEvan Quan 		return -EINVAL;
131279c65f3fSEvan Quan 
13133712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13143712e7a4SEvan Quan 	ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle,
13153712e7a4SEvan Quan 					limit);
13163712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13173712e7a4SEvan Quan 
13183712e7a4SEvan Quan 	return ret;
131979c65f3fSEvan Quan }
132079c65f3fSEvan Quan 
132179c65f3fSEvan Quan int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev)
132279c65f3fSEvan Quan {
13233712e7a4SEvan Quan 	bool cclk_dpm_supported = false;
13243712e7a4SEvan Quan 
132579c65f3fSEvan Quan 	if (!is_support_sw_smu(adev))
132679c65f3fSEvan Quan 		return false;
132779c65f3fSEvan Quan 
13283712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13293712e7a4SEvan Quan 	cclk_dpm_supported = is_support_cclk_dpm(adev);
13303712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13313712e7a4SEvan Quan 
13323712e7a4SEvan Quan 	return (int)cclk_dpm_supported;
133379c65f3fSEvan Quan }
133479c65f3fSEvan Quan 
133579c65f3fSEvan Quan int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
133679c65f3fSEvan Quan 						       struct seq_file *m)
133779c65f3fSEvan Quan {
133879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
133979c65f3fSEvan Quan 
134079c65f3fSEvan Quan 	if (!pp_funcs->debugfs_print_current_performance_level)
134179c65f3fSEvan Quan 		return -EOPNOTSUPP;
134279c65f3fSEvan Quan 
13433712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
134479c65f3fSEvan Quan 	pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle,
134579c65f3fSEvan Quan 							  m);
13463712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
134779c65f3fSEvan Quan 
134879c65f3fSEvan Quan 	return 0;
134979c65f3fSEvan Quan }
135079c65f3fSEvan Quan 
135179c65f3fSEvan Quan int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev,
135279c65f3fSEvan Quan 				       void **addr,
135379c65f3fSEvan Quan 				       size_t *size)
135479c65f3fSEvan Quan {
135579c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13563712e7a4SEvan Quan 	int ret = 0;
135779c65f3fSEvan Quan 
135879c65f3fSEvan Quan 	if (!pp_funcs->get_smu_prv_buf_details)
135979c65f3fSEvan Quan 		return -ENOSYS;
136079c65f3fSEvan Quan 
13613712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13623712e7a4SEvan Quan 	ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle,
136379c65f3fSEvan Quan 						addr,
136479c65f3fSEvan Quan 						size);
13653712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13663712e7a4SEvan Quan 
13673712e7a4SEvan Quan 	return ret;
136879c65f3fSEvan Quan }
136979c65f3fSEvan Quan 
137079c65f3fSEvan Quan int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev)
137179c65f3fSEvan Quan {
137279c65f3fSEvan Quan 	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
1373ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
137479c65f3fSEvan Quan 
1375ebfc2533SEvan Quan 	if ((is_support_sw_smu(adev) && smu->od_enabled) ||
1376ebfc2533SEvan Quan 	    (is_support_sw_smu(adev) && smu->is_apu) ||
137779c65f3fSEvan Quan 		(!is_support_sw_smu(adev) && hwmgr->od_enabled))
137879c65f3fSEvan Quan 		return true;
137979c65f3fSEvan Quan 
138079c65f3fSEvan Quan 	return false;
138179c65f3fSEvan Quan }
138279c65f3fSEvan Quan 
138379c65f3fSEvan Quan int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev,
138479c65f3fSEvan Quan 			    const char *buf,
138579c65f3fSEvan Quan 			    size_t size)
138679c65f3fSEvan Quan {
138779c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13883712e7a4SEvan Quan 	int ret = 0;
138979c65f3fSEvan Quan 
139079c65f3fSEvan Quan 	if (!pp_funcs->set_pp_table)
139179c65f3fSEvan Quan 		return -EOPNOTSUPP;
139279c65f3fSEvan Quan 
13933712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13943712e7a4SEvan Quan 	ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle,
139579c65f3fSEvan Quan 				     buf,
139679c65f3fSEvan Quan 				     size);
13973712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13983712e7a4SEvan Quan 
13993712e7a4SEvan Quan 	return ret;
140079c65f3fSEvan Quan }
140179c65f3fSEvan Quan 
140279c65f3fSEvan Quan int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev)
140379c65f3fSEvan Quan {
1404ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
1405ebfc2533SEvan Quan 
14063712e7a4SEvan Quan 	if (!is_support_sw_smu(adev))
14073712e7a4SEvan Quan 		return INT_MAX;
14083712e7a4SEvan Quan 
1409ebfc2533SEvan Quan 	return smu->cpu_core_num;
141079c65f3fSEvan Quan }
141179c65f3fSEvan Quan 
141279c65f3fSEvan Quan void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev)
141379c65f3fSEvan Quan {
141479c65f3fSEvan Quan 	if (!is_support_sw_smu(adev))
141579c65f3fSEvan Quan 		return;
141679c65f3fSEvan Quan 
141779c65f3fSEvan Quan 	amdgpu_smu_stb_debug_fs_init(adev);
141879c65f3fSEvan Quan }
141913f5dbd6SEvan Quan 
142013f5dbd6SEvan Quan int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev,
142113f5dbd6SEvan Quan 					    const struct amd_pp_display_configuration *input)
142213f5dbd6SEvan Quan {
142313f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14243712e7a4SEvan Quan 	int ret = 0;
142513f5dbd6SEvan Quan 
142613f5dbd6SEvan Quan 	if (!pp_funcs->display_configuration_change)
142713f5dbd6SEvan Quan 		return 0;
142813f5dbd6SEvan Quan 
14293712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14303712e7a4SEvan Quan 	ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle,
143113f5dbd6SEvan Quan 						     input);
14323712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14333712e7a4SEvan Quan 
14343712e7a4SEvan Quan 	return ret;
143513f5dbd6SEvan Quan }
143613f5dbd6SEvan Quan 
143713f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev,
143813f5dbd6SEvan Quan 				 enum amd_pp_clock_type type,
143913f5dbd6SEvan Quan 				 struct amd_pp_clocks *clocks)
144013f5dbd6SEvan Quan {
144113f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14423712e7a4SEvan Quan 	int ret = 0;
144313f5dbd6SEvan Quan 
144413f5dbd6SEvan Quan 	if (!pp_funcs->get_clock_by_type)
144513f5dbd6SEvan Quan 		return 0;
144613f5dbd6SEvan Quan 
14473712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14483712e7a4SEvan Quan 	ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle,
144913f5dbd6SEvan Quan 					  type,
145013f5dbd6SEvan Quan 					  clocks);
14513712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14523712e7a4SEvan Quan 
14533712e7a4SEvan Quan 	return ret;
145413f5dbd6SEvan Quan }
145513f5dbd6SEvan Quan 
145613f5dbd6SEvan Quan int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev,
145713f5dbd6SEvan Quan 						struct amd_pp_simple_clock_info *clocks)
145813f5dbd6SEvan Quan {
145913f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14603712e7a4SEvan Quan 	int ret = 0;
146113f5dbd6SEvan Quan 
146213f5dbd6SEvan Quan 	if (!pp_funcs->get_display_mode_validation_clocks)
146313f5dbd6SEvan Quan 		return 0;
146413f5dbd6SEvan Quan 
14653712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14663712e7a4SEvan Quan 	ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle,
146713f5dbd6SEvan Quan 							   clocks);
14683712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14693712e7a4SEvan Quan 
14703712e7a4SEvan Quan 	return ret;
147113f5dbd6SEvan Quan }
147213f5dbd6SEvan Quan 
147313f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev,
147413f5dbd6SEvan Quan 					      enum amd_pp_clock_type type,
147513f5dbd6SEvan Quan 					      struct pp_clock_levels_with_latency *clocks)
147613f5dbd6SEvan Quan {
147713f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14783712e7a4SEvan Quan 	int ret = 0;
147913f5dbd6SEvan Quan 
148013f5dbd6SEvan Quan 	if (!pp_funcs->get_clock_by_type_with_latency)
148113f5dbd6SEvan Quan 		return 0;
148213f5dbd6SEvan Quan 
14833712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14843712e7a4SEvan Quan 	ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle,
148513f5dbd6SEvan Quan 						       type,
148613f5dbd6SEvan Quan 						       clocks);
14873712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14883712e7a4SEvan Quan 
14893712e7a4SEvan Quan 	return ret;
149013f5dbd6SEvan Quan }
149113f5dbd6SEvan Quan 
149213f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev,
149313f5dbd6SEvan Quan 					      enum amd_pp_clock_type type,
149413f5dbd6SEvan Quan 					      struct pp_clock_levels_with_voltage *clocks)
149513f5dbd6SEvan Quan {
149613f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14973712e7a4SEvan Quan 	int ret = 0;
149813f5dbd6SEvan Quan 
149913f5dbd6SEvan Quan 	if (!pp_funcs->get_clock_by_type_with_voltage)
150013f5dbd6SEvan Quan 		return 0;
150113f5dbd6SEvan Quan 
15023712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15033712e7a4SEvan Quan 	ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle,
150413f5dbd6SEvan Quan 						       type,
150513f5dbd6SEvan Quan 						       clocks);
15063712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15073712e7a4SEvan Quan 
15083712e7a4SEvan Quan 	return ret;
150913f5dbd6SEvan Quan }
151013f5dbd6SEvan Quan 
151113f5dbd6SEvan Quan int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev,
151213f5dbd6SEvan Quan 					       void *clock_ranges)
151313f5dbd6SEvan Quan {
151413f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15153712e7a4SEvan Quan 	int ret = 0;
151613f5dbd6SEvan Quan 
151713f5dbd6SEvan Quan 	if (!pp_funcs->set_watermarks_for_clocks_ranges)
151813f5dbd6SEvan Quan 		return -EOPNOTSUPP;
151913f5dbd6SEvan Quan 
15203712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15213712e7a4SEvan Quan 	ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle,
152213f5dbd6SEvan Quan 							 clock_ranges);
15233712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15243712e7a4SEvan Quan 
15253712e7a4SEvan Quan 	return ret;
152613f5dbd6SEvan Quan }
152713f5dbd6SEvan Quan 
152813f5dbd6SEvan Quan int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev,
152913f5dbd6SEvan Quan 					     struct pp_display_clock_request *clock)
153013f5dbd6SEvan Quan {
153113f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15323712e7a4SEvan Quan 	int ret = 0;
153313f5dbd6SEvan Quan 
153413f5dbd6SEvan Quan 	if (!pp_funcs->display_clock_voltage_request)
153513f5dbd6SEvan Quan 		return -EOPNOTSUPP;
153613f5dbd6SEvan Quan 
15373712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15383712e7a4SEvan Quan 	ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle,
153913f5dbd6SEvan Quan 						      clock);
15403712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15413712e7a4SEvan Quan 
15423712e7a4SEvan Quan 	return ret;
154313f5dbd6SEvan Quan }
154413f5dbd6SEvan Quan 
154513f5dbd6SEvan Quan int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev,
154613f5dbd6SEvan Quan 				  struct amd_pp_clock_info *clocks)
154713f5dbd6SEvan Quan {
154813f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15493712e7a4SEvan Quan 	int ret = 0;
155013f5dbd6SEvan Quan 
155113f5dbd6SEvan Quan 	if (!pp_funcs->get_current_clocks)
155213f5dbd6SEvan Quan 		return -EOPNOTSUPP;
155313f5dbd6SEvan Quan 
15543712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15553712e7a4SEvan Quan 	ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle,
155613f5dbd6SEvan Quan 					   clocks);
15573712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15583712e7a4SEvan Quan 
15593712e7a4SEvan Quan 	return ret;
156013f5dbd6SEvan Quan }
156113f5dbd6SEvan Quan 
156213f5dbd6SEvan Quan void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev)
156313f5dbd6SEvan Quan {
156413f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
156513f5dbd6SEvan Quan 
156613f5dbd6SEvan Quan 	if (!pp_funcs->notify_smu_enable_pwe)
156713f5dbd6SEvan Quan 		return;
156813f5dbd6SEvan Quan 
15693712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
157013f5dbd6SEvan Quan 	pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle);
15713712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
157213f5dbd6SEvan Quan }
157313f5dbd6SEvan Quan 
157413f5dbd6SEvan Quan int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev,
157513f5dbd6SEvan Quan 					uint32_t count)
157613f5dbd6SEvan Quan {
157713f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15783712e7a4SEvan Quan 	int ret = 0;
157913f5dbd6SEvan Quan 
158013f5dbd6SEvan Quan 	if (!pp_funcs->set_active_display_count)
158113f5dbd6SEvan Quan 		return -EOPNOTSUPP;
158213f5dbd6SEvan Quan 
15833712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15843712e7a4SEvan Quan 	ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle,
158513f5dbd6SEvan Quan 						 count);
15863712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15873712e7a4SEvan Quan 
15883712e7a4SEvan Quan 	return ret;
158913f5dbd6SEvan Quan }
159013f5dbd6SEvan Quan 
159113f5dbd6SEvan Quan int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev,
159213f5dbd6SEvan Quan 					  uint32_t clock)
159313f5dbd6SEvan Quan {
159413f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15953712e7a4SEvan Quan 	int ret = 0;
159613f5dbd6SEvan Quan 
159713f5dbd6SEvan Quan 	if (!pp_funcs->set_min_deep_sleep_dcefclk)
159813f5dbd6SEvan Quan 		return -EOPNOTSUPP;
159913f5dbd6SEvan Quan 
16003712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16013712e7a4SEvan Quan 	ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle,
160213f5dbd6SEvan Quan 						   clock);
16033712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16043712e7a4SEvan Quan 
16053712e7a4SEvan Quan 	return ret;
160613f5dbd6SEvan Quan }
160713f5dbd6SEvan Quan 
160813f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev,
160913f5dbd6SEvan Quan 					     uint32_t clock)
161013f5dbd6SEvan Quan {
161113f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
161213f5dbd6SEvan Quan 
161313f5dbd6SEvan Quan 	if (!pp_funcs->set_hard_min_dcefclk_by_freq)
161413f5dbd6SEvan Quan 		return;
161513f5dbd6SEvan Quan 
16163712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
161713f5dbd6SEvan Quan 	pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle,
161813f5dbd6SEvan Quan 					       clock);
16193712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
162013f5dbd6SEvan Quan }
162113f5dbd6SEvan Quan 
162213f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev,
162313f5dbd6SEvan Quan 					  uint32_t clock)
162413f5dbd6SEvan Quan {
162513f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
162613f5dbd6SEvan Quan 
162713f5dbd6SEvan Quan 	if (!pp_funcs->set_hard_min_fclk_by_freq)
162813f5dbd6SEvan Quan 		return;
162913f5dbd6SEvan Quan 
16303712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
163113f5dbd6SEvan Quan 	pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle,
163213f5dbd6SEvan Quan 					    clock);
16333712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
163413f5dbd6SEvan Quan }
163513f5dbd6SEvan Quan 
163613f5dbd6SEvan Quan int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev,
163713f5dbd6SEvan Quan 						   bool disable_memory_clock_switch)
163813f5dbd6SEvan Quan {
163913f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16403712e7a4SEvan Quan 	int ret = 0;
164113f5dbd6SEvan Quan 
164213f5dbd6SEvan Quan 	if (!pp_funcs->display_disable_memory_clock_switch)
164313f5dbd6SEvan Quan 		return 0;
164413f5dbd6SEvan Quan 
16453712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16463712e7a4SEvan Quan 	ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle,
164713f5dbd6SEvan Quan 							    disable_memory_clock_switch);
16483712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16493712e7a4SEvan Quan 
16503712e7a4SEvan Quan 	return ret;
165113f5dbd6SEvan Quan }
165213f5dbd6SEvan Quan 
165313f5dbd6SEvan Quan int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev,
165413f5dbd6SEvan Quan 						struct pp_smu_nv_clock_table *max_clocks)
165513f5dbd6SEvan Quan {
165613f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16573712e7a4SEvan Quan 	int ret = 0;
165813f5dbd6SEvan Quan 
165913f5dbd6SEvan Quan 	if (!pp_funcs->get_max_sustainable_clocks_by_dc)
166013f5dbd6SEvan Quan 		return -EOPNOTSUPP;
166113f5dbd6SEvan Quan 
16623712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16633712e7a4SEvan Quan 	ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle,
166413f5dbd6SEvan Quan 							 max_clocks);
16653712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16663712e7a4SEvan Quan 
16673712e7a4SEvan Quan 	return ret;
166813f5dbd6SEvan Quan }
166913f5dbd6SEvan Quan 
167013f5dbd6SEvan Quan enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev,
167113f5dbd6SEvan Quan 						  unsigned int *clock_values_in_khz,
167213f5dbd6SEvan Quan 						  unsigned int *num_states)
167313f5dbd6SEvan Quan {
167413f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16753712e7a4SEvan Quan 	int ret = 0;
167613f5dbd6SEvan Quan 
167713f5dbd6SEvan Quan 	if (!pp_funcs->get_uclk_dpm_states)
167813f5dbd6SEvan Quan 		return -EOPNOTSUPP;
167913f5dbd6SEvan Quan 
16803712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16813712e7a4SEvan Quan 	ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle,
168213f5dbd6SEvan Quan 					    clock_values_in_khz,
168313f5dbd6SEvan Quan 					    num_states);
16843712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16853712e7a4SEvan Quan 
16863712e7a4SEvan Quan 	return ret;
168713f5dbd6SEvan Quan }
168813f5dbd6SEvan Quan 
168913f5dbd6SEvan Quan int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev,
169013f5dbd6SEvan Quan 				   struct dpm_clocks *clock_table)
169113f5dbd6SEvan Quan {
169213f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16933712e7a4SEvan Quan 	int ret = 0;
169413f5dbd6SEvan Quan 
169513f5dbd6SEvan Quan 	if (!pp_funcs->get_dpm_clock_table)
169613f5dbd6SEvan Quan 		return -EOPNOTSUPP;
169713f5dbd6SEvan Quan 
16983712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16993712e7a4SEvan Quan 	ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle,
170013f5dbd6SEvan Quan 					    clock_table);
17013712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
17023712e7a4SEvan Quan 
17033712e7a4SEvan Quan 	return ret;
170413f5dbd6SEvan Quan }
1705