xref: /openbmc/linux/drivers/gpu/drm/amd/pm/amdgpu_dpm.c (revision c3ed0e72)
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 
1107101ab97SHuang Rui int amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev)
1117101ab97SHuang Rui {
1127101ab97SHuang Rui 	struct smu_context *smu = adev->powerplay.pp_handle;
1137101ab97SHuang Rui 	int ret = -EOPNOTSUPP;
1147101ab97SHuang Rui 
1157101ab97SHuang Rui 	mutex_lock(&adev->pm.mutex);
1167101ab97SHuang Rui 	ret = smu_set_gfx_power_up_by_imu(smu);
1177101ab97SHuang Rui 	mutex_unlock(&adev->pm.mutex);
1187101ab97SHuang Rui 
1197101ab97SHuang Rui 	msleep(10);
1207101ab97SHuang Rui 
1217101ab97SHuang Rui 	return ret;
1227101ab97SHuang Rui }
1237101ab97SHuang 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 
230230dd6bbSKenneth Feng int amdgpu_dpm_enable_gfx_features(struct amdgpu_device *adev)
231230dd6bbSKenneth Feng {
232230dd6bbSKenneth Feng 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
233230dd6bbSKenneth Feng 	void *pp_handle = adev->powerplay.pp_handle;
234230dd6bbSKenneth Feng 	int ret = 0;
235230dd6bbSKenneth Feng 
236230dd6bbSKenneth Feng 	if (!pp_funcs || !pp_funcs->asic_reset_enable_gfx_features)
237230dd6bbSKenneth Feng 		return -ENOENT;
238230dd6bbSKenneth Feng 
239230dd6bbSKenneth Feng 	mutex_lock(&adev->pm.mutex);
240230dd6bbSKenneth Feng 
241230dd6bbSKenneth Feng 	ret = pp_funcs->asic_reset_enable_gfx_features(pp_handle);
242230dd6bbSKenneth Feng 
243230dd6bbSKenneth Feng 	mutex_unlock(&adev->pm.mutex);
244230dd6bbSKenneth Feng 
245230dd6bbSKenneth Feng 	return ret;
246230dd6bbSKenneth Feng }
247230dd6bbSKenneth Feng 
248e098bc96SEvan Quan int amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
249e098bc96SEvan Quan {
250e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
251e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
252e098bc96SEvan Quan 	int ret = 0;
253e098bc96SEvan Quan 
2549ab5001aSDarren Powell 	if (!pp_funcs || !pp_funcs->set_asic_baco_state)
255e098bc96SEvan Quan 		return -ENOENT;
256e098bc96SEvan Quan 
2573712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
2583712e7a4SEvan Quan 
259e098bc96SEvan Quan 	/* enter BACO state */
260e098bc96SEvan Quan 	ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
261e098bc96SEvan Quan 	if (ret)
2623712e7a4SEvan Quan 		goto out;
263e098bc96SEvan Quan 
264e098bc96SEvan Quan 	/* exit BACO state */
265e098bc96SEvan Quan 	ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
266e098bc96SEvan Quan 
2673712e7a4SEvan Quan out:
2683712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
2693712e7a4SEvan Quan 	return ret;
270e098bc96SEvan Quan }
271e098bc96SEvan Quan 
272e098bc96SEvan Quan bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev)
273e098bc96SEvan Quan {
274ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
2753712e7a4SEvan Quan 	bool support_mode1_reset = false;
276e098bc96SEvan Quan 
2773712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
2783712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
2793712e7a4SEvan Quan 		support_mode1_reset = smu_mode1_reset_is_support(smu);
2803712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
2813712e7a4SEvan Quan 	}
282e098bc96SEvan Quan 
2833712e7a4SEvan Quan 	return support_mode1_reset;
284e098bc96SEvan Quan }
285e098bc96SEvan Quan 
286e098bc96SEvan Quan int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev)
287e098bc96SEvan Quan {
288ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
2893712e7a4SEvan Quan 	int ret = -EOPNOTSUPP;
290e098bc96SEvan Quan 
2913712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
2923712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
2933712e7a4SEvan Quan 		ret = smu_mode1_reset(smu);
2943712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
2953712e7a4SEvan Quan 	}
296e098bc96SEvan Quan 
2973712e7a4SEvan Quan 	return ret;
298e098bc96SEvan Quan }
299e098bc96SEvan Quan 
300e098bc96SEvan Quan int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
301e098bc96SEvan Quan 				    enum PP_SMC_POWER_PROFILE type,
302e098bc96SEvan Quan 				    bool en)
303e098bc96SEvan Quan {
304bab0f602SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
305e098bc96SEvan Quan 	int ret = 0;
306e098bc96SEvan Quan 
3077cf7a392SJingwen Chen 	if (amdgpu_sriov_vf(adev))
3087cf7a392SJingwen Chen 		return 0;
3097cf7a392SJingwen Chen 
3103712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->switch_power_profile) {
3113712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
312bab0f602SDarren Powell 		ret = pp_funcs->switch_power_profile(
313e098bc96SEvan Quan 			adev->powerplay.pp_handle, type, en);
3143712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3153712e7a4SEvan Quan 	}
316e098bc96SEvan Quan 
317e098bc96SEvan Quan 	return ret;
318e098bc96SEvan Quan }
319e098bc96SEvan Quan 
320e098bc96SEvan Quan int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
321e098bc96SEvan Quan 			       uint32_t pstate)
322e098bc96SEvan Quan {
323bab0f602SDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
324e098bc96SEvan Quan 	int ret = 0;
325e098bc96SEvan Quan 
3263712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->set_xgmi_pstate) {
3273712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
328bab0f602SDarren Powell 		ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle,
329e098bc96SEvan Quan 								pstate);
3303712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3313712e7a4SEvan Quan 	}
332e098bc96SEvan Quan 
333e098bc96SEvan Quan 	return ret;
334e098bc96SEvan Quan }
335e098bc96SEvan Quan 
336e098bc96SEvan Quan int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev,
337e098bc96SEvan Quan 			     uint32_t cstate)
338e098bc96SEvan Quan {
339e098bc96SEvan Quan 	int ret = 0;
340e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
341e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
342e098bc96SEvan Quan 
3433712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->set_df_cstate) {
3443712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
345e098bc96SEvan Quan 		ret = pp_funcs->set_df_cstate(pp_handle, cstate);
3463712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3473712e7a4SEvan Quan 	}
348e098bc96SEvan Quan 
349e098bc96SEvan Quan 	return ret;
350e098bc96SEvan Quan }
351e098bc96SEvan Quan 
352e098bc96SEvan Quan int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en)
353e098bc96SEvan Quan {
354ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
3553712e7a4SEvan Quan 	int ret = 0;
356e098bc96SEvan Quan 
3573712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
3583712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
3593712e7a4SEvan Quan 		ret = smu_allow_xgmi_power_down(smu, en);
3603712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3613712e7a4SEvan Quan 	}
362e098bc96SEvan Quan 
3633712e7a4SEvan Quan 	return ret;
364e098bc96SEvan Quan }
365e098bc96SEvan Quan 
366e098bc96SEvan Quan int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev)
367e098bc96SEvan Quan {
368e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
369e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs =
370e098bc96SEvan Quan 			adev->powerplay.pp_funcs;
371e098bc96SEvan Quan 	int ret = 0;
372e098bc96SEvan Quan 
3733712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) {
3743712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
375e098bc96SEvan Quan 		ret = pp_funcs->enable_mgpu_fan_boost(pp_handle);
3763712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3773712e7a4SEvan Quan 	}
378e098bc96SEvan Quan 
379e098bc96SEvan Quan 	return ret;
380e098bc96SEvan Quan }
381e098bc96SEvan Quan 
382e098bc96SEvan Quan int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev,
383e098bc96SEvan Quan 				      uint32_t msg_id)
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 = 0;
389e098bc96SEvan Quan 
3903712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->set_clockgating_by_smu) {
3913712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
392e098bc96SEvan Quan 		ret = pp_funcs->set_clockgating_by_smu(pp_handle,
393e098bc96SEvan Quan 						       msg_id);
3943712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
3953712e7a4SEvan Quan 	}
396e098bc96SEvan Quan 
397e098bc96SEvan Quan 	return ret;
398e098bc96SEvan Quan }
399e098bc96SEvan Quan 
400e098bc96SEvan Quan int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev,
401e098bc96SEvan Quan 				  bool acquire)
402e098bc96SEvan Quan {
403e098bc96SEvan Quan 	void *pp_handle = adev->powerplay.pp_handle;
404e098bc96SEvan Quan 	const struct amd_pm_funcs *pp_funcs =
405e098bc96SEvan Quan 			adev->powerplay.pp_funcs;
406e098bc96SEvan Quan 	int ret = -EOPNOTSUPP;
407e098bc96SEvan Quan 
4083712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->smu_i2c_bus_access) {
4093712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
410e098bc96SEvan Quan 		ret = pp_funcs->smu_i2c_bus_access(pp_handle,
411e098bc96SEvan Quan 						   acquire);
4123712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
4133712e7a4SEvan Quan 	}
414e098bc96SEvan Quan 
415e098bc96SEvan Quan 	return ret;
416e098bc96SEvan Quan }
417e098bc96SEvan Quan 
418e098bc96SEvan Quan void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
419e098bc96SEvan Quan {
420e098bc96SEvan Quan 	if (adev->pm.dpm_enabled) {
421e098bc96SEvan Quan 		mutex_lock(&adev->pm.mutex);
422e098bc96SEvan Quan 		if (power_supply_is_system_supplied() > 0)
423e098bc96SEvan Quan 			adev->pm.ac_power = true;
424e098bc96SEvan Quan 		else
425e098bc96SEvan Quan 			adev->pm.ac_power = false;
4263712e7a4SEvan Quan 
427e098bc96SEvan Quan 		if (adev->powerplay.pp_funcs &&
428e098bc96SEvan Quan 		    adev->powerplay.pp_funcs->enable_bapm)
429e098bc96SEvan Quan 			amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power);
430e098bc96SEvan Quan 
431e098bc96SEvan Quan 		if (is_support_sw_smu(adev))
432ebfc2533SEvan Quan 			smu_set_ac_dc(adev->powerplay.pp_handle);
4333712e7a4SEvan Quan 
4343712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
435e098bc96SEvan Quan 	}
436e098bc96SEvan Quan }
437e098bc96SEvan Quan 
438e098bc96SEvan Quan int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor,
439e098bc96SEvan Quan 			   void *data, uint32_t *size)
440e098bc96SEvan Quan {
4419ab5001aSDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
4423712e7a4SEvan Quan 	int ret = -EINVAL;
443e098bc96SEvan Quan 
444e098bc96SEvan Quan 	if (!data || !size)
445e098bc96SEvan Quan 		return -EINVAL;
446e098bc96SEvan Quan 
4473712e7a4SEvan Quan 	if (pp_funcs && pp_funcs->read_sensor) {
4483712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
4493712e7a4SEvan Quan 		ret = pp_funcs->read_sensor(adev->powerplay.pp_handle,
4503712e7a4SEvan Quan 					    sensor,
4513712e7a4SEvan Quan 					    data,
4523712e7a4SEvan Quan 					    size);
4533712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
4543712e7a4SEvan Quan 	}
455e098bc96SEvan Quan 
456e098bc96SEvan Quan 	return ret;
457e098bc96SEvan Quan }
458e098bc96SEvan Quan 
459*c3ed0e72SKun Liu int amdgpu_dpm_get_apu_thermal_limit(struct amdgpu_device *adev, uint32_t *limit)
460*c3ed0e72SKun Liu {
461*c3ed0e72SKun Liu 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
462*c3ed0e72SKun Liu 	int ret = -EINVAL;
463*c3ed0e72SKun Liu 
464*c3ed0e72SKun Liu 	if (pp_funcs && pp_funcs->get_apu_thermal_limit) {
465*c3ed0e72SKun Liu 		mutex_lock(&adev->pm.mutex);
466*c3ed0e72SKun Liu 		ret = pp_funcs->get_apu_thermal_limit(adev->powerplay.pp_handle, limit);
467*c3ed0e72SKun Liu 		mutex_unlock(&adev->pm.mutex);
468*c3ed0e72SKun Liu 	}
469*c3ed0e72SKun Liu 
470*c3ed0e72SKun Liu 	return ret;
471*c3ed0e72SKun Liu }
472*c3ed0e72SKun Liu 
473*c3ed0e72SKun Liu int amdgpu_dpm_set_apu_thermal_limit(struct amdgpu_device *adev, uint32_t limit)
474*c3ed0e72SKun Liu {
475*c3ed0e72SKun Liu 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
476*c3ed0e72SKun Liu 	int ret = -EINVAL;
477*c3ed0e72SKun Liu 
478*c3ed0e72SKun Liu 	if (pp_funcs && pp_funcs->set_apu_thermal_limit) {
479*c3ed0e72SKun Liu 		mutex_lock(&adev->pm.mutex);
480*c3ed0e72SKun Liu 		ret = pp_funcs->set_apu_thermal_limit(adev->powerplay.pp_handle, limit);
481*c3ed0e72SKun Liu 		mutex_unlock(&adev->pm.mutex);
482*c3ed0e72SKun Liu 	}
483*c3ed0e72SKun Liu 
484*c3ed0e72SKun Liu 	return ret;
485*c3ed0e72SKun Liu }
486*c3ed0e72SKun Liu 
48784176663SEvan Quan void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev)
488e098bc96SEvan Quan {
4896ddbd37fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
490a71849cdSEvan Quan 	int i;
491e098bc96SEvan Quan 
492e098bc96SEvan Quan 	if (!adev->pm.dpm_enabled)
493e098bc96SEvan Quan 		return;
494e098bc96SEvan Quan 
4956ddbd37fSEvan Quan 	if (!pp_funcs->pm_compute_clocks)
4966ddbd37fSEvan Quan 		return;
497e098bc96SEvan Quan 
498a71849cdSEvan Quan 	if (adev->mode_info.num_crtc)
499a71849cdSEvan Quan 		amdgpu_display_bandwidth_update(adev);
500a71849cdSEvan Quan 
501a71849cdSEvan Quan 	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
502a71849cdSEvan Quan 		struct amdgpu_ring *ring = adev->rings[i];
503a71849cdSEvan Quan 		if (ring && ring->sched.ready)
504a71849cdSEvan Quan 			amdgpu_fence_wait_empty(ring);
505a71849cdSEvan Quan 	}
506a71849cdSEvan Quan 
5073712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
5086ddbd37fSEvan Quan 	pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle);
5093712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
510e098bc96SEvan Quan }
511e098bc96SEvan Quan 
512e098bc96SEvan Quan void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
513e098bc96SEvan Quan {
514e098bc96SEvan Quan 	int ret = 0;
515e098bc96SEvan Quan 
516a71849cdSEvan Quan 	if (adev->family == AMDGPU_FAMILY_SI) {
517a71849cdSEvan Quan 		mutex_lock(&adev->pm.mutex);
518a71849cdSEvan Quan 		if (enable) {
519a71849cdSEvan Quan 			adev->pm.dpm.uvd_active = true;
520a71849cdSEvan Quan 			adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
521a71849cdSEvan Quan 		} else {
522a71849cdSEvan Quan 			adev->pm.dpm.uvd_active = false;
523a71849cdSEvan Quan 		}
524a71849cdSEvan Quan 		mutex_unlock(&adev->pm.mutex);
525a71849cdSEvan Quan 
526a71849cdSEvan Quan 		amdgpu_dpm_compute_clocks(adev);
527a71849cdSEvan Quan 		return;
528a71849cdSEvan Quan 	}
529a71849cdSEvan Quan 
530e098bc96SEvan Quan 	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable);
531e098bc96SEvan Quan 	if (ret)
532e098bc96SEvan Quan 		DRM_ERROR("Dpm %s uvd failed, ret = %d. \n",
533e098bc96SEvan Quan 			  enable ? "enable" : "disable", ret);
534e098bc96SEvan Quan }
535e098bc96SEvan Quan 
536e098bc96SEvan Quan void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
537e098bc96SEvan Quan {
538e098bc96SEvan Quan 	int ret = 0;
539e098bc96SEvan Quan 
540a71849cdSEvan Quan 	if (adev->family == AMDGPU_FAMILY_SI) {
541a71849cdSEvan Quan 		mutex_lock(&adev->pm.mutex);
542a71849cdSEvan Quan 		if (enable) {
543a71849cdSEvan Quan 			adev->pm.dpm.vce_active = true;
544a71849cdSEvan Quan 			/* XXX select vce level based on ring/task */
545a71849cdSEvan Quan 			adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
546a71849cdSEvan Quan 		} else {
547a71849cdSEvan Quan 			adev->pm.dpm.vce_active = false;
548a71849cdSEvan Quan 		}
549a71849cdSEvan Quan 		mutex_unlock(&adev->pm.mutex);
550a71849cdSEvan Quan 
551a71849cdSEvan Quan 		amdgpu_dpm_compute_clocks(adev);
552a71849cdSEvan Quan 		return;
553a71849cdSEvan Quan 	}
554a71849cdSEvan Quan 
555e098bc96SEvan Quan 	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable);
556e098bc96SEvan Quan 	if (ret)
557e098bc96SEvan Quan 		DRM_ERROR("Dpm %s vce failed, ret = %d. \n",
558e098bc96SEvan Quan 			  enable ? "enable" : "disable", ret);
559e098bc96SEvan Quan }
560e098bc96SEvan Quan 
561e098bc96SEvan Quan void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable)
562e098bc96SEvan Quan {
563e098bc96SEvan Quan 	int ret = 0;
564e098bc96SEvan Quan 
565e098bc96SEvan Quan 	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable);
566e098bc96SEvan Quan 	if (ret)
567e098bc96SEvan Quan 		DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n",
568e098bc96SEvan Quan 			  enable ? "enable" : "disable", ret);
569e098bc96SEvan Quan }
570e098bc96SEvan Quan 
571e098bc96SEvan Quan int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
572e098bc96SEvan Quan {
5733712e7a4SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
5743712e7a4SEvan Quan 	int r = 0;
575e098bc96SEvan Quan 
5761613f346SFlora Cui 	if (!pp_funcs || !pp_funcs->load_firmware)
5773712e7a4SEvan Quan 		return 0;
5783712e7a4SEvan Quan 
5793712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
5803712e7a4SEvan Quan 	r = pp_funcs->load_firmware(adev->powerplay.pp_handle);
581e098bc96SEvan Quan 	if (r) {
582e098bc96SEvan Quan 		pr_err("smu firmware loading failed\n");
5833712e7a4SEvan Quan 		goto out;
584e098bc96SEvan Quan 	}
5852e4b2f7bSEvan Quan 
5862e4b2f7bSEvan Quan 	if (smu_version)
587e098bc96SEvan Quan 		*smu_version = adev->pm.fw_version;
5882e4b2f7bSEvan Quan 
5893712e7a4SEvan Quan out:
5903712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
5913712e7a4SEvan Quan 	return r;
592e098bc96SEvan Quan }
593bc143d8bSEvan Quan 
594bc143d8bSEvan Quan int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable)
595bc143d8bSEvan Quan {
5963712e7a4SEvan Quan 	int ret = 0;
5973712e7a4SEvan Quan 
5983712e7a4SEvan Quan 	if (is_support_sw_smu(adev)) {
5993712e7a4SEvan Quan 		mutex_lock(&adev->pm.mutex);
6003712e7a4SEvan Quan 		ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle,
6013712e7a4SEvan Quan 						 enable);
6023712e7a4SEvan Quan 		mutex_unlock(&adev->pm.mutex);
6033712e7a4SEvan Quan 	}
6043712e7a4SEvan Quan 
6053712e7a4SEvan Quan 	return ret;
606bc143d8bSEvan Quan }
607bc143d8bSEvan Quan 
608bc143d8bSEvan Quan int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size)
609bc143d8bSEvan Quan {
610ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6113712e7a4SEvan Quan 	int ret = 0;
612ebfc2533SEvan Quan 
61393dde6ccSStanley.Yang 	if (!is_support_sw_smu(adev))
61493dde6ccSStanley.Yang 		return -EOPNOTSUPP;
61593dde6ccSStanley.Yang 
6163712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6173712e7a4SEvan Quan 	ret = smu_send_hbm_bad_pages_num(smu, size);
6183712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6193712e7a4SEvan Quan 
6203712e7a4SEvan Quan 	return ret;
621bc143d8bSEvan Quan }
622bc143d8bSEvan Quan 
623d510eccfSStanley.Yang int amdgpu_dpm_send_hbm_bad_channel_flag(struct amdgpu_device *adev, uint32_t size)
624d510eccfSStanley.Yang {
625d510eccfSStanley.Yang 	struct smu_context *smu = adev->powerplay.pp_handle;
626d510eccfSStanley.Yang 	int ret = 0;
627d510eccfSStanley.Yang 
62893dde6ccSStanley.Yang 	if (!is_support_sw_smu(adev))
62993dde6ccSStanley.Yang 		return -EOPNOTSUPP;
63093dde6ccSStanley.Yang 
631d510eccfSStanley.Yang 	mutex_lock(&adev->pm.mutex);
632d510eccfSStanley.Yang 	ret = smu_send_hbm_bad_channel_flag(smu, size);
633d510eccfSStanley.Yang 	mutex_unlock(&adev->pm.mutex);
634d510eccfSStanley.Yang 
635d510eccfSStanley.Yang 	return ret;
636d510eccfSStanley.Yang }
637d510eccfSStanley.Yang 
638bc143d8bSEvan Quan int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev,
639bc143d8bSEvan Quan 				  enum pp_clock_type type,
640bc143d8bSEvan Quan 				  uint32_t *min,
641bc143d8bSEvan Quan 				  uint32_t *max)
642bc143d8bSEvan Quan {
6433712e7a4SEvan Quan 	int ret = 0;
6443712e7a4SEvan Quan 
6453712e7a4SEvan Quan 	if (type != PP_SCLK)
6463712e7a4SEvan Quan 		return -EINVAL;
6473712e7a4SEvan Quan 
648bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
649bc143d8bSEvan Quan 		return -EOPNOTSUPP;
650bc143d8bSEvan Quan 
6513712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6523712e7a4SEvan Quan 	ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle,
6533712e7a4SEvan Quan 				     SMU_SCLK,
6543712e7a4SEvan Quan 				     min,
6553712e7a4SEvan Quan 				     max);
6563712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6573712e7a4SEvan Quan 
6583712e7a4SEvan Quan 	return ret;
659bc143d8bSEvan Quan }
660bc143d8bSEvan Quan 
661bc143d8bSEvan Quan int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev,
662bc143d8bSEvan Quan 				   enum pp_clock_type type,
663bc143d8bSEvan Quan 				   uint32_t min,
664bc143d8bSEvan Quan 				   uint32_t max)
665bc143d8bSEvan Quan {
666ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6673712e7a4SEvan Quan 	int ret = 0;
6683712e7a4SEvan Quan 
6693712e7a4SEvan Quan 	if (type != PP_SCLK)
6703712e7a4SEvan Quan 		return -EINVAL;
671ebfc2533SEvan Quan 
672bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
673bc143d8bSEvan Quan 		return -EOPNOTSUPP;
674bc143d8bSEvan Quan 
6753712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6763712e7a4SEvan Quan 	ret = smu_set_soft_freq_range(smu,
6773712e7a4SEvan Quan 				      SMU_SCLK,
6783712e7a4SEvan Quan 				      min,
6793712e7a4SEvan Quan 				      max);
6803712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6813712e7a4SEvan Quan 
6823712e7a4SEvan Quan 	return ret;
683bc143d8bSEvan Quan }
684bc143d8bSEvan Quan 
68513f5dbd6SEvan Quan int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev)
68613f5dbd6SEvan Quan {
687ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
6883712e7a4SEvan Quan 	int ret = 0;
689ebfc2533SEvan Quan 
69013f5dbd6SEvan Quan 	if (!is_support_sw_smu(adev))
69113f5dbd6SEvan Quan 		return 0;
69213f5dbd6SEvan Quan 
6933712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
6943712e7a4SEvan Quan 	ret = smu_write_watermarks_table(smu);
6953712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
6963712e7a4SEvan Quan 
6973712e7a4SEvan Quan 	return ret;
69813f5dbd6SEvan Quan }
69913f5dbd6SEvan Quan 
700bc143d8bSEvan Quan int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev,
701bc143d8bSEvan Quan 			      enum smu_event_type event,
702bc143d8bSEvan Quan 			      uint64_t event_arg)
703bc143d8bSEvan Quan {
704ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
7053712e7a4SEvan Quan 	int ret = 0;
706ebfc2533SEvan Quan 
707bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
708bc143d8bSEvan Quan 		return -EOPNOTSUPP;
709bc143d8bSEvan Quan 
7103712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
7113712e7a4SEvan Quan 	ret = smu_wait_for_event(smu, event, event_arg);
7123712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
7133712e7a4SEvan Quan 
7143712e7a4SEvan Quan 	return ret;
715bc143d8bSEvan Quan }
716bc143d8bSEvan Quan 
7170ad7347aSAndré Almeida int amdgpu_dpm_set_residency_gfxoff(struct amdgpu_device *adev, bool value)
7180ad7347aSAndré Almeida {
7190ad7347aSAndré Almeida 	struct smu_context *smu = adev->powerplay.pp_handle;
7200ad7347aSAndré Almeida 	int ret = 0;
7210ad7347aSAndré Almeida 
7220ad7347aSAndré Almeida 	if (!is_support_sw_smu(adev))
7230ad7347aSAndré Almeida 		return -EOPNOTSUPP;
7240ad7347aSAndré Almeida 
7250ad7347aSAndré Almeida 	mutex_lock(&adev->pm.mutex);
7260ad7347aSAndré Almeida 	ret = smu_set_residency_gfxoff(smu, value);
7270ad7347aSAndré Almeida 	mutex_unlock(&adev->pm.mutex);
7280ad7347aSAndré Almeida 
7290ad7347aSAndré Almeida 	return ret;
7300ad7347aSAndré Almeida }
7310ad7347aSAndré Almeida 
7320ad7347aSAndré Almeida int amdgpu_dpm_get_residency_gfxoff(struct amdgpu_device *adev, u32 *value)
7330ad7347aSAndré Almeida {
7340ad7347aSAndré Almeida 	struct smu_context *smu = adev->powerplay.pp_handle;
7350ad7347aSAndré Almeida 	int ret = 0;
7360ad7347aSAndré Almeida 
7370ad7347aSAndré Almeida 	if (!is_support_sw_smu(adev))
7380ad7347aSAndré Almeida 		return -EOPNOTSUPP;
7390ad7347aSAndré Almeida 
7400ad7347aSAndré Almeida 	mutex_lock(&adev->pm.mutex);
7410ad7347aSAndré Almeida 	ret = smu_get_residency_gfxoff(smu, value);
7420ad7347aSAndré Almeida 	mutex_unlock(&adev->pm.mutex);
7430ad7347aSAndré Almeida 
7440ad7347aSAndré Almeida 	return ret;
7450ad7347aSAndré Almeida }
7460ad7347aSAndré Almeida 
7470ad7347aSAndré Almeida int amdgpu_dpm_get_entrycount_gfxoff(struct amdgpu_device *adev, u64 *value)
7480ad7347aSAndré Almeida {
7490ad7347aSAndré Almeida 	struct smu_context *smu = adev->powerplay.pp_handle;
7500ad7347aSAndré Almeida 	int ret = 0;
7510ad7347aSAndré Almeida 
7520ad7347aSAndré Almeida 	if (!is_support_sw_smu(adev))
7530ad7347aSAndré Almeida 		return -EOPNOTSUPP;
7540ad7347aSAndré Almeida 
7550ad7347aSAndré Almeida 	mutex_lock(&adev->pm.mutex);
7560ad7347aSAndré Almeida 	ret = smu_get_entrycount_gfxoff(smu, value);
7570ad7347aSAndré Almeida 	mutex_unlock(&adev->pm.mutex);
7580ad7347aSAndré Almeida 
7590ad7347aSAndré Almeida 	return ret;
7600ad7347aSAndré Almeida }
7610ad7347aSAndré Almeida 
762bc143d8bSEvan Quan int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value)
763bc143d8bSEvan Quan {
764ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
7653712e7a4SEvan Quan 	int ret = 0;
766ebfc2533SEvan Quan 
767bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
768bc143d8bSEvan Quan 		return -EOPNOTSUPP;
769bc143d8bSEvan Quan 
7703712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
7713712e7a4SEvan Quan 	ret = smu_get_status_gfxoff(smu, value);
7723712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
7733712e7a4SEvan Quan 
7743712e7a4SEvan Quan 	return ret;
775bc143d8bSEvan Quan }
776bc143d8bSEvan Quan 
777bc143d8bSEvan Quan uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev)
778bc143d8bSEvan Quan {
779ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
780ebfc2533SEvan Quan 
7813712e7a4SEvan Quan 	if (!is_support_sw_smu(adev))
7823712e7a4SEvan Quan 		return 0;
7833712e7a4SEvan Quan 
784ebfc2533SEvan Quan 	return atomic64_read(&smu->throttle_int_counter);
785bc143d8bSEvan Quan }
786bc143d8bSEvan Quan 
787bc143d8bSEvan Quan /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set
788bc143d8bSEvan Quan  * @adev: amdgpu_device pointer
789bc143d8bSEvan Quan  * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry)
790bc143d8bSEvan Quan  *
791bc143d8bSEvan Quan  */
792bc143d8bSEvan Quan void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev,
793bc143d8bSEvan Quan 				 enum gfx_change_state state)
794bc143d8bSEvan Quan {
795bc143d8bSEvan Quan 	mutex_lock(&adev->pm.mutex);
796bc143d8bSEvan Quan 	if (adev->powerplay.pp_funcs &&
797bc143d8bSEvan Quan 	    adev->powerplay.pp_funcs->gfx_state_change_set)
798bc143d8bSEvan Quan 		((adev)->powerplay.pp_funcs->gfx_state_change_set(
799bc143d8bSEvan Quan 			(adev)->powerplay.pp_handle, state));
800bc143d8bSEvan Quan 	mutex_unlock(&adev->pm.mutex);
801bc143d8bSEvan Quan }
802bc143d8bSEvan Quan 
803bc143d8bSEvan Quan int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev,
804bc143d8bSEvan Quan 			    void *umc_ecc)
805bc143d8bSEvan Quan {
806ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
807a29d44aeSStanley.Yang 	int ret = 0;
808ebfc2533SEvan Quan 
809bc143d8bSEvan Quan 	if (!is_support_sw_smu(adev))
810bc143d8bSEvan Quan 		return -EOPNOTSUPP;
811bc143d8bSEvan Quan 
812a29d44aeSStanley.Yang 	mutex_lock(&adev->pm.mutex);
813a29d44aeSStanley.Yang 	ret = smu_get_ecc_info(smu, umc_ecc);
814a29d44aeSStanley.Yang 	mutex_unlock(&adev->pm.mutex);
815a29d44aeSStanley.Yang 
816a29d44aeSStanley.Yang 	return ret;
817bc143d8bSEvan Quan }
81879c65f3fSEvan Quan 
81979c65f3fSEvan Quan struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev,
82079c65f3fSEvan Quan 						     uint32_t idx)
82179c65f3fSEvan Quan {
82279c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
8233712e7a4SEvan Quan 	struct amd_vce_state *vstate = NULL;
82479c65f3fSEvan Quan 
82579c65f3fSEvan Quan 	if (!pp_funcs->get_vce_clock_state)
82679c65f3fSEvan Quan 		return NULL;
82779c65f3fSEvan Quan 
8283712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
8293712e7a4SEvan Quan 	vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle,
83079c65f3fSEvan Quan 					       idx);
8313712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
8323712e7a4SEvan Quan 
8333712e7a4SEvan Quan 	return vstate;
83479c65f3fSEvan Quan }
83579c65f3fSEvan Quan 
83679c65f3fSEvan Quan void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev,
83779c65f3fSEvan Quan 					enum amd_pm_state_type *state)
83879c65f3fSEvan Quan {
83979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
84079c65f3fSEvan Quan 
8413712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
8423712e7a4SEvan Quan 
84379c65f3fSEvan Quan 	if (!pp_funcs->get_current_power_state) {
84479c65f3fSEvan Quan 		*state = adev->pm.dpm.user_state;
8453712e7a4SEvan Quan 		goto out;
84679c65f3fSEvan Quan 	}
84779c65f3fSEvan Quan 
84879c65f3fSEvan Quan 	*state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle);
84979c65f3fSEvan Quan 	if (*state < POWER_STATE_TYPE_DEFAULT ||
85079c65f3fSEvan Quan 	    *state > POWER_STATE_TYPE_INTERNAL_3DPERF)
85179c65f3fSEvan Quan 		*state = adev->pm.dpm.user_state;
8523712e7a4SEvan Quan 
8533712e7a4SEvan Quan out:
8543712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
85579c65f3fSEvan Quan }
85679c65f3fSEvan Quan 
85779c65f3fSEvan Quan void amdgpu_dpm_set_power_state(struct amdgpu_device *adev,
85879c65f3fSEvan Quan 				enum amd_pm_state_type state)
85979c65f3fSEvan Quan {
8603712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
86179c65f3fSEvan Quan 	adev->pm.dpm.user_state = state;
8623712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
86379c65f3fSEvan Quan 
86479c65f3fSEvan Quan 	if (is_support_sw_smu(adev))
86579c65f3fSEvan Quan 		return;
86679c65f3fSEvan Quan 
86779c65f3fSEvan Quan 	if (amdgpu_dpm_dispatch_task(adev,
86879c65f3fSEvan Quan 				     AMD_PP_TASK_ENABLE_USER_STATE,
86979c65f3fSEvan Quan 				     &state) == -EOPNOTSUPP)
87084176663SEvan Quan 		amdgpu_dpm_compute_clocks(adev);
87179c65f3fSEvan Quan }
87279c65f3fSEvan Quan 
87375513bf5SEvan Quan enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev)
87479c65f3fSEvan Quan {
87579c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
87679c65f3fSEvan Quan 	enum amd_dpm_forced_level level;
87779c65f3fSEvan Quan 
87839dbde65SLijo Lazar 	if (!pp_funcs)
87939dbde65SLijo Lazar 		return AMD_DPM_FORCED_LEVEL_AUTO;
88039dbde65SLijo Lazar 
88175513bf5SEvan Quan 	mutex_lock(&adev->pm.mutex);
88279c65f3fSEvan Quan 	if (pp_funcs->get_performance_level)
88379c65f3fSEvan Quan 		level = pp_funcs->get_performance_level(adev->powerplay.pp_handle);
88479c65f3fSEvan Quan 	else
88579c65f3fSEvan Quan 		level = adev->pm.dpm.forced_level;
8863712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
88779c65f3fSEvan Quan 
88879c65f3fSEvan Quan 	return level;
88979c65f3fSEvan Quan }
89079c65f3fSEvan Quan 
89179c65f3fSEvan Quan int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev,
89279c65f3fSEvan Quan 				       enum amd_dpm_forced_level level)
89379c65f3fSEvan Quan {
89479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
89554c73b51SAlex Deucher 	enum amd_dpm_forced_level current_level;
89654c73b51SAlex Deucher 	uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
89754c73b51SAlex Deucher 					AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
89854c73b51SAlex Deucher 					AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
89954c73b51SAlex Deucher 					AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
90079c65f3fSEvan Quan 
901eea5c7b3SHuang Rui 	if (!pp_funcs || !pp_funcs->force_performance_level)
9023712e7a4SEvan Quan 		return 0;
9033712e7a4SEvan Quan 
90475513bf5SEvan Quan 	if (adev->pm.dpm.thermal_active)
90575513bf5SEvan Quan 		return -EINVAL;
9063712e7a4SEvan Quan 
90775513bf5SEvan Quan 	current_level = amdgpu_dpm_get_performance_level(adev);
90875513bf5SEvan Quan 	if (current_level == level)
90975513bf5SEvan Quan 		return 0;
91054c73b51SAlex Deucher 
91154c73b51SAlex Deucher 	if (adev->asic_type == CHIP_RAVEN) {
91254c73b51SAlex Deucher 		if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) {
91354c73b51SAlex Deucher 			if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
91454c73b51SAlex Deucher 			    level == AMD_DPM_FORCED_LEVEL_MANUAL)
91554c73b51SAlex Deucher 				amdgpu_gfx_off_ctrl(adev, false);
91654c73b51SAlex Deucher 			else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL &&
91754c73b51SAlex Deucher 				 level != AMD_DPM_FORCED_LEVEL_MANUAL)
91854c73b51SAlex Deucher 				amdgpu_gfx_off_ctrl(adev, true);
91954c73b51SAlex Deucher 		}
92054c73b51SAlex Deucher 	}
92154c73b51SAlex Deucher 
92254c73b51SAlex Deucher 	if (!(current_level & profile_mode_mask) &&
92375513bf5SEvan Quan 	    (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT))
92475513bf5SEvan Quan 		return -EINVAL;
92554c73b51SAlex Deucher 
92654c73b51SAlex Deucher 	if (!(current_level & profile_mode_mask) &&
92754c73b51SAlex Deucher 	      (level & profile_mode_mask)) {
92854c73b51SAlex Deucher 		/* enter UMD Pstate */
92954c73b51SAlex Deucher 		amdgpu_device_ip_set_powergating_state(adev,
93054c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
93154c73b51SAlex Deucher 						       AMD_PG_STATE_UNGATE);
93254c73b51SAlex Deucher 		amdgpu_device_ip_set_clockgating_state(adev,
93354c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
93454c73b51SAlex Deucher 						       AMD_CG_STATE_UNGATE);
93554c73b51SAlex Deucher 	} else if ((current_level & profile_mode_mask) &&
93654c73b51SAlex Deucher 		    !(level & profile_mode_mask)) {
93754c73b51SAlex Deucher 		/* exit UMD Pstate */
93854c73b51SAlex Deucher 		amdgpu_device_ip_set_clockgating_state(adev,
93954c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
94054c73b51SAlex Deucher 						       AMD_CG_STATE_GATE);
94154c73b51SAlex Deucher 		amdgpu_device_ip_set_powergating_state(adev,
94254c73b51SAlex Deucher 						       AMD_IP_BLOCK_TYPE_GFX,
94354c73b51SAlex Deucher 						       AMD_PG_STATE_GATE);
94454c73b51SAlex Deucher 	}
94554c73b51SAlex Deucher 
94675513bf5SEvan Quan 	mutex_lock(&adev->pm.mutex);
94779c65f3fSEvan Quan 
94875513bf5SEvan Quan 	if (pp_funcs->force_performance_level(adev->powerplay.pp_handle,
94975513bf5SEvan Quan 					      level)) {
95075513bf5SEvan Quan 		mutex_unlock(&adev->pm.mutex);
95175513bf5SEvan Quan 		return -EINVAL;
95275513bf5SEvan Quan 	}
95375513bf5SEvan Quan 
95479c65f3fSEvan Quan 	adev->pm.dpm.forced_level = level;
95579c65f3fSEvan Quan 
9563712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9573712e7a4SEvan Quan 
95875513bf5SEvan Quan 	return 0;
95979c65f3fSEvan Quan }
96079c65f3fSEvan Quan 
96179c65f3fSEvan Quan int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev,
96279c65f3fSEvan Quan 				 struct pp_states_info *states)
96379c65f3fSEvan Quan {
96479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9653712e7a4SEvan Quan 	int ret = 0;
96679c65f3fSEvan Quan 
96779c65f3fSEvan Quan 	if (!pp_funcs->get_pp_num_states)
96879c65f3fSEvan Quan 		return -EOPNOTSUPP;
96979c65f3fSEvan Quan 
9703712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
9713712e7a4SEvan Quan 	ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle,
9723712e7a4SEvan Quan 					  states);
9733712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9743712e7a4SEvan Quan 
9753712e7a4SEvan Quan 	return ret;
97679c65f3fSEvan Quan }
97779c65f3fSEvan Quan 
97879c65f3fSEvan Quan int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev,
97979c65f3fSEvan Quan 			      enum amd_pp_task task_id,
98079c65f3fSEvan Quan 			      enum amd_pm_state_type *user_state)
98179c65f3fSEvan Quan {
98279c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
9833712e7a4SEvan Quan 	int ret = 0;
98479c65f3fSEvan Quan 
98579c65f3fSEvan Quan 	if (!pp_funcs->dispatch_tasks)
98679c65f3fSEvan Quan 		return -EOPNOTSUPP;
98779c65f3fSEvan Quan 
9883712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
9893712e7a4SEvan Quan 	ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle,
9903712e7a4SEvan Quan 				       task_id,
9913712e7a4SEvan Quan 				       user_state);
9923712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
9933712e7a4SEvan Quan 
9943712e7a4SEvan Quan 	return ret;
99579c65f3fSEvan Quan }
99679c65f3fSEvan Quan 
99779c65f3fSEvan Quan int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table)
99879c65f3fSEvan Quan {
99979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10003712e7a4SEvan Quan 	int ret = 0;
100179c65f3fSEvan Quan 
100279c65f3fSEvan Quan 	if (!pp_funcs->get_pp_table)
100379c65f3fSEvan Quan 		return 0;
100479c65f3fSEvan Quan 
10053712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10063712e7a4SEvan Quan 	ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle,
10073712e7a4SEvan Quan 				     table);
10083712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10093712e7a4SEvan Quan 
10103712e7a4SEvan Quan 	return ret;
101179c65f3fSEvan Quan }
101279c65f3fSEvan Quan 
101379c65f3fSEvan Quan int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev,
101479c65f3fSEvan Quan 				      uint32_t type,
101579c65f3fSEvan Quan 				      long *input,
101679c65f3fSEvan Quan 				      uint32_t size)
101779c65f3fSEvan Quan {
101879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10193712e7a4SEvan Quan 	int ret = 0;
102079c65f3fSEvan Quan 
102179c65f3fSEvan Quan 	if (!pp_funcs->set_fine_grain_clk_vol)
102279c65f3fSEvan Quan 		return 0;
102379c65f3fSEvan Quan 
10243712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10253712e7a4SEvan Quan 	ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle,
102679c65f3fSEvan Quan 					       type,
102779c65f3fSEvan Quan 					       input,
102879c65f3fSEvan Quan 					       size);
10293712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10303712e7a4SEvan Quan 
10313712e7a4SEvan Quan 	return ret;
103279c65f3fSEvan Quan }
103379c65f3fSEvan Quan 
103479c65f3fSEvan Quan int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev,
103579c65f3fSEvan Quan 				  uint32_t type,
103679c65f3fSEvan Quan 				  long *input,
103779c65f3fSEvan Quan 				  uint32_t size)
103879c65f3fSEvan Quan {
103979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10403712e7a4SEvan Quan 	int ret = 0;
104179c65f3fSEvan Quan 
104279c65f3fSEvan Quan 	if (!pp_funcs->odn_edit_dpm_table)
104379c65f3fSEvan Quan 		return 0;
104479c65f3fSEvan Quan 
10453712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10463712e7a4SEvan Quan 	ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle,
104779c65f3fSEvan Quan 					   type,
104879c65f3fSEvan Quan 					   input,
104979c65f3fSEvan Quan 					   size);
10503712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10513712e7a4SEvan Quan 
10523712e7a4SEvan Quan 	return ret;
105379c65f3fSEvan Quan }
105479c65f3fSEvan Quan 
105579c65f3fSEvan Quan int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
105679c65f3fSEvan Quan 				  enum pp_clock_type type,
105779c65f3fSEvan Quan 				  char *buf)
105879c65f3fSEvan Quan {
105979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10603712e7a4SEvan Quan 	int ret = 0;
106179c65f3fSEvan Quan 
106279c65f3fSEvan Quan 	if (!pp_funcs->print_clock_levels)
106379c65f3fSEvan Quan 		return 0;
106479c65f3fSEvan Quan 
10653712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
10663712e7a4SEvan Quan 	ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle,
106779c65f3fSEvan Quan 					   type,
106879c65f3fSEvan Quan 					   buf);
10693712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
10703712e7a4SEvan Quan 
10713712e7a4SEvan Quan 	return ret;
107279c65f3fSEvan Quan }
107379c65f3fSEvan Quan 
10745d64f9bbSDarren Powell int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev,
10755d64f9bbSDarren Powell 				  enum pp_clock_type type,
10765d64f9bbSDarren Powell 				  char *buf,
10775d64f9bbSDarren Powell 				  int *offset)
10785d64f9bbSDarren Powell {
10795d64f9bbSDarren Powell 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10805d64f9bbSDarren Powell 	int ret = 0;
10815d64f9bbSDarren Powell 
10825d64f9bbSDarren Powell 	if (!pp_funcs->emit_clock_levels)
10835d64f9bbSDarren Powell 		return -ENOENT;
10845d64f9bbSDarren Powell 
10855d64f9bbSDarren Powell 	mutex_lock(&adev->pm.mutex);
10865d64f9bbSDarren Powell 	ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle,
10875d64f9bbSDarren Powell 					   type,
10885d64f9bbSDarren Powell 					   buf,
10895d64f9bbSDarren Powell 					   offset);
10905d64f9bbSDarren Powell 	mutex_unlock(&adev->pm.mutex);
10915d64f9bbSDarren Powell 
10925d64f9bbSDarren Powell 	return ret;
10935d64f9bbSDarren Powell }
10945d64f9bbSDarren Powell 
109579c65f3fSEvan Quan int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
109679c65f3fSEvan Quan 				    uint64_t ppfeature_masks)
109779c65f3fSEvan Quan {
109879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10993712e7a4SEvan Quan 	int ret = 0;
110079c65f3fSEvan Quan 
110179c65f3fSEvan Quan 	if (!pp_funcs->set_ppfeature_status)
110279c65f3fSEvan Quan 		return 0;
110379c65f3fSEvan Quan 
11043712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11053712e7a4SEvan Quan 	ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle,
110679c65f3fSEvan Quan 					     ppfeature_masks);
11073712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11083712e7a4SEvan Quan 
11093712e7a4SEvan Quan 	return ret;
111079c65f3fSEvan Quan }
111179c65f3fSEvan Quan 
111279c65f3fSEvan Quan int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf)
111379c65f3fSEvan Quan {
111479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11153712e7a4SEvan Quan 	int ret = 0;
111679c65f3fSEvan Quan 
111779c65f3fSEvan Quan 	if (!pp_funcs->get_ppfeature_status)
111879c65f3fSEvan Quan 		return 0;
111979c65f3fSEvan Quan 
11203712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11213712e7a4SEvan Quan 	ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle,
112279c65f3fSEvan Quan 					     buf);
11233712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11243712e7a4SEvan Quan 
11253712e7a4SEvan Quan 	return ret;
112679c65f3fSEvan Quan }
112779c65f3fSEvan Quan 
112879c65f3fSEvan Quan int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev,
112979c65f3fSEvan Quan 				 enum pp_clock_type type,
113079c65f3fSEvan Quan 				 uint32_t mask)
113179c65f3fSEvan Quan {
113279c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11333712e7a4SEvan Quan 	int ret = 0;
113479c65f3fSEvan Quan 
113579c65f3fSEvan Quan 	if (!pp_funcs->force_clock_level)
113679c65f3fSEvan Quan 		return 0;
113779c65f3fSEvan Quan 
11383712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11393712e7a4SEvan Quan 	ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle,
114079c65f3fSEvan Quan 					  type,
114179c65f3fSEvan Quan 					  mask);
11423712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11433712e7a4SEvan Quan 
11443712e7a4SEvan Quan 	return ret;
114579c65f3fSEvan Quan }
114679c65f3fSEvan Quan 
114779c65f3fSEvan Quan int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev)
114879c65f3fSEvan Quan {
114979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11503712e7a4SEvan Quan 	int ret = 0;
115179c65f3fSEvan Quan 
115279c65f3fSEvan Quan 	if (!pp_funcs->get_sclk_od)
115379c65f3fSEvan Quan 		return 0;
115479c65f3fSEvan Quan 
11553712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11563712e7a4SEvan Quan 	ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle);
11573712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11583712e7a4SEvan Quan 
11593712e7a4SEvan Quan 	return ret;
116079c65f3fSEvan Quan }
116179c65f3fSEvan Quan 
116279c65f3fSEvan Quan int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value)
116379c65f3fSEvan Quan {
116479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
116579c65f3fSEvan Quan 
116679c65f3fSEvan Quan 	if (is_support_sw_smu(adev))
116779c65f3fSEvan Quan 		return 0;
116879c65f3fSEvan Quan 
11693712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
117079c65f3fSEvan Quan 	if (pp_funcs->set_sclk_od)
117179c65f3fSEvan Quan 		pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value);
11723712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
117379c65f3fSEvan Quan 
117479c65f3fSEvan Quan 	if (amdgpu_dpm_dispatch_task(adev,
117579c65f3fSEvan Quan 				     AMD_PP_TASK_READJUST_POWER_STATE,
117679c65f3fSEvan Quan 				     NULL) == -EOPNOTSUPP) {
117779c65f3fSEvan Quan 		adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
117884176663SEvan Quan 		amdgpu_dpm_compute_clocks(adev);
117979c65f3fSEvan Quan 	}
118079c65f3fSEvan Quan 
118179c65f3fSEvan Quan 	return 0;
118279c65f3fSEvan Quan }
118379c65f3fSEvan Quan 
118479c65f3fSEvan Quan int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev)
118579c65f3fSEvan Quan {
118679c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11873712e7a4SEvan Quan 	int ret = 0;
118879c65f3fSEvan Quan 
118979c65f3fSEvan Quan 	if (!pp_funcs->get_mclk_od)
119079c65f3fSEvan Quan 		return 0;
119179c65f3fSEvan Quan 
11923712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
11933712e7a4SEvan Quan 	ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle);
11943712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
11953712e7a4SEvan Quan 
11963712e7a4SEvan Quan 	return ret;
119779c65f3fSEvan Quan }
119879c65f3fSEvan Quan 
119979c65f3fSEvan Quan int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value)
120079c65f3fSEvan Quan {
120179c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
120279c65f3fSEvan Quan 
120379c65f3fSEvan Quan 	if (is_support_sw_smu(adev))
120479c65f3fSEvan Quan 		return 0;
120579c65f3fSEvan Quan 
12063712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
120779c65f3fSEvan Quan 	if (pp_funcs->set_mclk_od)
120879c65f3fSEvan Quan 		pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value);
12093712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
121079c65f3fSEvan Quan 
121179c65f3fSEvan Quan 	if (amdgpu_dpm_dispatch_task(adev,
121279c65f3fSEvan Quan 				     AMD_PP_TASK_READJUST_POWER_STATE,
121379c65f3fSEvan Quan 				     NULL) == -EOPNOTSUPP) {
121479c65f3fSEvan Quan 		adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps;
121584176663SEvan Quan 		amdgpu_dpm_compute_clocks(adev);
121679c65f3fSEvan Quan 	}
121779c65f3fSEvan Quan 
121879c65f3fSEvan Quan 	return 0;
121979c65f3fSEvan Quan }
122079c65f3fSEvan Quan 
122179c65f3fSEvan Quan int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev,
122279c65f3fSEvan Quan 				      char *buf)
122379c65f3fSEvan Quan {
122479c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12253712e7a4SEvan Quan 	int ret = 0;
122679c65f3fSEvan Quan 
122779c65f3fSEvan Quan 	if (!pp_funcs->get_power_profile_mode)
122879c65f3fSEvan Quan 		return -EOPNOTSUPP;
122979c65f3fSEvan Quan 
12303712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12313712e7a4SEvan Quan 	ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle,
123279c65f3fSEvan Quan 					       buf);
12333712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12343712e7a4SEvan Quan 
12353712e7a4SEvan Quan 	return ret;
123679c65f3fSEvan Quan }
123779c65f3fSEvan Quan 
123879c65f3fSEvan Quan int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev,
123979c65f3fSEvan Quan 				      long *input, uint32_t size)
124079c65f3fSEvan Quan {
124179c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12423712e7a4SEvan Quan 	int ret = 0;
124379c65f3fSEvan Quan 
124479c65f3fSEvan Quan 	if (!pp_funcs->set_power_profile_mode)
124579c65f3fSEvan Quan 		return 0;
124679c65f3fSEvan Quan 
12473712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12483712e7a4SEvan Quan 	ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle,
124979c65f3fSEvan Quan 					       input,
125079c65f3fSEvan Quan 					       size);
12513712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12523712e7a4SEvan Quan 
12533712e7a4SEvan Quan 	return ret;
125479c65f3fSEvan Quan }
125579c65f3fSEvan Quan 
125679c65f3fSEvan Quan int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table)
125779c65f3fSEvan Quan {
125879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12593712e7a4SEvan Quan 	int ret = 0;
126079c65f3fSEvan Quan 
126179c65f3fSEvan Quan 	if (!pp_funcs->get_gpu_metrics)
126279c65f3fSEvan Quan 		return 0;
126379c65f3fSEvan Quan 
12643712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12653712e7a4SEvan Quan 	ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle,
12663712e7a4SEvan Quan 					table);
12673712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
12683712e7a4SEvan Quan 
12693712e7a4SEvan Quan 	return ret;
127079c65f3fSEvan Quan }
127179c65f3fSEvan Quan 
127279c65f3fSEvan Quan int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev,
127379c65f3fSEvan Quan 				    uint32_t *fan_mode)
127479c65f3fSEvan Quan {
127579c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1276685fae24SEvan Quan 	int ret = 0;
127779c65f3fSEvan Quan 
127879c65f3fSEvan Quan 	if (!pp_funcs->get_fan_control_mode)
127979c65f3fSEvan Quan 		return -EOPNOTSUPP;
128079c65f3fSEvan Quan 
12813712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
1282685fae24SEvan Quan 	ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle,
1283685fae24SEvan Quan 					     fan_mode);
12843712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
128579c65f3fSEvan Quan 
1286685fae24SEvan Quan 	return ret;
128779c65f3fSEvan Quan }
128879c65f3fSEvan Quan 
128979c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev,
129079c65f3fSEvan Quan 				 uint32_t speed)
129179c65f3fSEvan Quan {
129279c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12933712e7a4SEvan Quan 	int ret = 0;
129479c65f3fSEvan Quan 
129579c65f3fSEvan Quan 	if (!pp_funcs->set_fan_speed_pwm)
1296685fae24SEvan Quan 		return -EOPNOTSUPP;
129779c65f3fSEvan Quan 
12983712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
12993712e7a4SEvan Quan 	ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle,
13003712e7a4SEvan Quan 					  speed);
13013712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13023712e7a4SEvan Quan 
13033712e7a4SEvan Quan 	return ret;
130479c65f3fSEvan Quan }
130579c65f3fSEvan Quan 
130679c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev,
130779c65f3fSEvan Quan 				 uint32_t *speed)
130879c65f3fSEvan Quan {
130979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13103712e7a4SEvan Quan 	int ret = 0;
131179c65f3fSEvan Quan 
131279c65f3fSEvan Quan 	if (!pp_funcs->get_fan_speed_pwm)
1313685fae24SEvan Quan 		return -EOPNOTSUPP;
131479c65f3fSEvan Quan 
13153712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13163712e7a4SEvan Quan 	ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle,
13173712e7a4SEvan Quan 					  speed);
13183712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13193712e7a4SEvan Quan 
13203712e7a4SEvan Quan 	return ret;
132179c65f3fSEvan Quan }
132279c65f3fSEvan Quan 
132379c65f3fSEvan Quan int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev,
132479c65f3fSEvan Quan 				 uint32_t *speed)
132579c65f3fSEvan Quan {
132679c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13273712e7a4SEvan Quan 	int ret = 0;
132879c65f3fSEvan Quan 
132979c65f3fSEvan Quan 	if (!pp_funcs->get_fan_speed_rpm)
1330685fae24SEvan Quan 		return -EOPNOTSUPP;
133179c65f3fSEvan Quan 
13323712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13333712e7a4SEvan Quan 	ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle,
13343712e7a4SEvan Quan 					  speed);
13353712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13363712e7a4SEvan Quan 
13373712e7a4SEvan Quan 	return ret;
133879c65f3fSEvan Quan }
133979c65f3fSEvan Quan 
134079c65f3fSEvan Quan int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev,
134179c65f3fSEvan Quan 				 uint32_t speed)
134279c65f3fSEvan Quan {
134379c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13443712e7a4SEvan Quan 	int ret = 0;
134579c65f3fSEvan Quan 
134679c65f3fSEvan Quan 	if (!pp_funcs->set_fan_speed_rpm)
1347685fae24SEvan Quan 		return -EOPNOTSUPP;
134879c65f3fSEvan Quan 
13493712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13503712e7a4SEvan Quan 	ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle,
13513712e7a4SEvan Quan 					  speed);
13523712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13533712e7a4SEvan Quan 
13543712e7a4SEvan Quan 	return ret;
135579c65f3fSEvan Quan }
135679c65f3fSEvan Quan 
135779c65f3fSEvan Quan int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev,
135879c65f3fSEvan Quan 				    uint32_t mode)
135979c65f3fSEvan Quan {
136079c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
1361685fae24SEvan Quan 	int ret = 0;
136279c65f3fSEvan Quan 
136379c65f3fSEvan Quan 	if (!pp_funcs->set_fan_control_mode)
136479c65f3fSEvan Quan 		return -EOPNOTSUPP;
136579c65f3fSEvan Quan 
13663712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
1367685fae24SEvan Quan 	ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle,
13683712e7a4SEvan Quan 					     mode);
13693712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
137079c65f3fSEvan Quan 
1371685fae24SEvan Quan 	return ret;
137279c65f3fSEvan Quan }
137379c65f3fSEvan Quan 
137479c65f3fSEvan Quan int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev,
137579c65f3fSEvan Quan 			       uint32_t *limit,
137679c65f3fSEvan Quan 			       enum pp_power_limit_level pp_limit_level,
137779c65f3fSEvan Quan 			       enum pp_power_type power_type)
137879c65f3fSEvan Quan {
137979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13803712e7a4SEvan Quan 	int ret = 0;
138179c65f3fSEvan Quan 
138279c65f3fSEvan Quan 	if (!pp_funcs->get_power_limit)
138379c65f3fSEvan Quan 		return -ENODATA;
138479c65f3fSEvan Quan 
13853712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
13863712e7a4SEvan Quan 	ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle,
138779c65f3fSEvan Quan 					limit,
138879c65f3fSEvan Quan 					pp_limit_level,
138979c65f3fSEvan Quan 					power_type);
13903712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
13913712e7a4SEvan Quan 
13923712e7a4SEvan Quan 	return ret;
139379c65f3fSEvan Quan }
139479c65f3fSEvan Quan 
139579c65f3fSEvan Quan int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev,
139679c65f3fSEvan Quan 			       uint32_t limit)
139779c65f3fSEvan Quan {
139879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
13993712e7a4SEvan Quan 	int ret = 0;
140079c65f3fSEvan Quan 
140179c65f3fSEvan Quan 	if (!pp_funcs->set_power_limit)
140279c65f3fSEvan Quan 		return -EINVAL;
140379c65f3fSEvan Quan 
14043712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14053712e7a4SEvan Quan 	ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle,
14063712e7a4SEvan Quan 					limit);
14073712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14083712e7a4SEvan Quan 
14093712e7a4SEvan Quan 	return ret;
141079c65f3fSEvan Quan }
141179c65f3fSEvan Quan 
141279c65f3fSEvan Quan int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev)
141379c65f3fSEvan Quan {
14143712e7a4SEvan Quan 	bool cclk_dpm_supported = false;
14153712e7a4SEvan Quan 
141679c65f3fSEvan Quan 	if (!is_support_sw_smu(adev))
141779c65f3fSEvan Quan 		return false;
141879c65f3fSEvan Quan 
14193712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14203712e7a4SEvan Quan 	cclk_dpm_supported = is_support_cclk_dpm(adev);
14213712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14223712e7a4SEvan Quan 
14233712e7a4SEvan Quan 	return (int)cclk_dpm_supported;
142479c65f3fSEvan Quan }
142579c65f3fSEvan Quan 
142679c65f3fSEvan Quan int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
142779c65f3fSEvan Quan 						       struct seq_file *m)
142879c65f3fSEvan Quan {
142979c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
143079c65f3fSEvan Quan 
143179c65f3fSEvan Quan 	if (!pp_funcs->debugfs_print_current_performance_level)
143279c65f3fSEvan Quan 		return -EOPNOTSUPP;
143379c65f3fSEvan Quan 
14343712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
143579c65f3fSEvan Quan 	pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle,
143679c65f3fSEvan Quan 							  m);
14373712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
143879c65f3fSEvan Quan 
143979c65f3fSEvan Quan 	return 0;
144079c65f3fSEvan Quan }
144179c65f3fSEvan Quan 
144279c65f3fSEvan Quan int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev,
144379c65f3fSEvan Quan 				       void **addr,
144479c65f3fSEvan Quan 				       size_t *size)
144579c65f3fSEvan Quan {
144679c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14473712e7a4SEvan Quan 	int ret = 0;
144879c65f3fSEvan Quan 
144979c65f3fSEvan Quan 	if (!pp_funcs->get_smu_prv_buf_details)
145079c65f3fSEvan Quan 		return -ENOSYS;
145179c65f3fSEvan Quan 
14523712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14533712e7a4SEvan Quan 	ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle,
145479c65f3fSEvan Quan 						addr,
145579c65f3fSEvan Quan 						size);
14563712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14573712e7a4SEvan Quan 
14583712e7a4SEvan Quan 	return ret;
145979c65f3fSEvan Quan }
146079c65f3fSEvan Quan 
146179c65f3fSEvan Quan int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev)
146279c65f3fSEvan Quan {
146379c65f3fSEvan Quan 	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
1464ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
146579c65f3fSEvan Quan 
1466ebfc2533SEvan Quan 	if ((is_support_sw_smu(adev) && smu->od_enabled) ||
1467ebfc2533SEvan Quan 	    (is_support_sw_smu(adev) && smu->is_apu) ||
146879c65f3fSEvan Quan 		(!is_support_sw_smu(adev) && hwmgr->od_enabled))
146979c65f3fSEvan Quan 		return true;
147079c65f3fSEvan Quan 
147179c65f3fSEvan Quan 	return false;
147279c65f3fSEvan Quan }
147379c65f3fSEvan Quan 
147479c65f3fSEvan Quan int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev,
147579c65f3fSEvan Quan 			    const char *buf,
147679c65f3fSEvan Quan 			    size_t size)
147779c65f3fSEvan Quan {
147879c65f3fSEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
14793712e7a4SEvan Quan 	int ret = 0;
148079c65f3fSEvan Quan 
148179c65f3fSEvan Quan 	if (!pp_funcs->set_pp_table)
148279c65f3fSEvan Quan 		return -EOPNOTSUPP;
148379c65f3fSEvan Quan 
14843712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
14853712e7a4SEvan Quan 	ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle,
148679c65f3fSEvan Quan 				     buf,
148779c65f3fSEvan Quan 				     size);
14883712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
14893712e7a4SEvan Quan 
14903712e7a4SEvan Quan 	return ret;
149179c65f3fSEvan Quan }
149279c65f3fSEvan Quan 
149379c65f3fSEvan Quan int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev)
149479c65f3fSEvan Quan {
1495ebfc2533SEvan Quan 	struct smu_context *smu = adev->powerplay.pp_handle;
1496ebfc2533SEvan Quan 
14973712e7a4SEvan Quan 	if (!is_support_sw_smu(adev))
14983712e7a4SEvan Quan 		return INT_MAX;
14993712e7a4SEvan Quan 
1500ebfc2533SEvan Quan 	return smu->cpu_core_num;
150179c65f3fSEvan Quan }
150279c65f3fSEvan Quan 
150379c65f3fSEvan Quan void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev)
150479c65f3fSEvan Quan {
150579c65f3fSEvan Quan 	if (!is_support_sw_smu(adev))
150679c65f3fSEvan Quan 		return;
150779c65f3fSEvan Quan 
150879c65f3fSEvan Quan 	amdgpu_smu_stb_debug_fs_init(adev);
150979c65f3fSEvan Quan }
151013f5dbd6SEvan Quan 
151113f5dbd6SEvan Quan int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev,
151213f5dbd6SEvan Quan 					    const struct amd_pp_display_configuration *input)
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->display_configuration_change)
151813f5dbd6SEvan Quan 		return 0;
151913f5dbd6SEvan Quan 
15203712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15213712e7a4SEvan Quan 	ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle,
152213f5dbd6SEvan Quan 						     input);
15233712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15243712e7a4SEvan Quan 
15253712e7a4SEvan Quan 	return ret;
152613f5dbd6SEvan Quan }
152713f5dbd6SEvan Quan 
152813f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev,
152913f5dbd6SEvan Quan 				 enum amd_pp_clock_type type,
153013f5dbd6SEvan Quan 				 struct amd_pp_clocks *clocks)
153113f5dbd6SEvan Quan {
153213f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15333712e7a4SEvan Quan 	int ret = 0;
153413f5dbd6SEvan Quan 
153513f5dbd6SEvan Quan 	if (!pp_funcs->get_clock_by_type)
153613f5dbd6SEvan Quan 		return 0;
153713f5dbd6SEvan Quan 
15383712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15393712e7a4SEvan Quan 	ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle,
154013f5dbd6SEvan Quan 					  type,
154113f5dbd6SEvan Quan 					  clocks);
15423712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15433712e7a4SEvan Quan 
15443712e7a4SEvan Quan 	return ret;
154513f5dbd6SEvan Quan }
154613f5dbd6SEvan Quan 
154713f5dbd6SEvan Quan int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev,
154813f5dbd6SEvan Quan 						struct amd_pp_simple_clock_info *clocks)
154913f5dbd6SEvan Quan {
155013f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15513712e7a4SEvan Quan 	int ret = 0;
155213f5dbd6SEvan Quan 
155313f5dbd6SEvan Quan 	if (!pp_funcs->get_display_mode_validation_clocks)
155413f5dbd6SEvan Quan 		return 0;
155513f5dbd6SEvan Quan 
15563712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15573712e7a4SEvan Quan 	ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle,
155813f5dbd6SEvan Quan 							   clocks);
15593712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15603712e7a4SEvan Quan 
15613712e7a4SEvan Quan 	return ret;
156213f5dbd6SEvan Quan }
156313f5dbd6SEvan Quan 
156413f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev,
156513f5dbd6SEvan Quan 					      enum amd_pp_clock_type type,
156613f5dbd6SEvan Quan 					      struct pp_clock_levels_with_latency *clocks)
156713f5dbd6SEvan Quan {
156813f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15693712e7a4SEvan Quan 	int ret = 0;
157013f5dbd6SEvan Quan 
157113f5dbd6SEvan Quan 	if (!pp_funcs->get_clock_by_type_with_latency)
157213f5dbd6SEvan Quan 		return 0;
157313f5dbd6SEvan Quan 
15743712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15753712e7a4SEvan Quan 	ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle,
157613f5dbd6SEvan Quan 						       type,
157713f5dbd6SEvan Quan 						       clocks);
15783712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15793712e7a4SEvan Quan 
15803712e7a4SEvan Quan 	return ret;
158113f5dbd6SEvan Quan }
158213f5dbd6SEvan Quan 
158313f5dbd6SEvan Quan int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev,
158413f5dbd6SEvan Quan 					      enum amd_pp_clock_type type,
158513f5dbd6SEvan Quan 					      struct pp_clock_levels_with_voltage *clocks)
158613f5dbd6SEvan Quan {
158713f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
15883712e7a4SEvan Quan 	int ret = 0;
158913f5dbd6SEvan Quan 
159013f5dbd6SEvan Quan 	if (!pp_funcs->get_clock_by_type_with_voltage)
159113f5dbd6SEvan Quan 		return 0;
159213f5dbd6SEvan Quan 
15933712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
15943712e7a4SEvan Quan 	ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle,
159513f5dbd6SEvan Quan 						       type,
159613f5dbd6SEvan Quan 						       clocks);
15973712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
15983712e7a4SEvan Quan 
15993712e7a4SEvan Quan 	return ret;
160013f5dbd6SEvan Quan }
160113f5dbd6SEvan Quan 
160213f5dbd6SEvan Quan int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev,
160313f5dbd6SEvan Quan 					       void *clock_ranges)
160413f5dbd6SEvan Quan {
160513f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16063712e7a4SEvan Quan 	int ret = 0;
160713f5dbd6SEvan Quan 
160813f5dbd6SEvan Quan 	if (!pp_funcs->set_watermarks_for_clocks_ranges)
160913f5dbd6SEvan Quan 		return -EOPNOTSUPP;
161013f5dbd6SEvan Quan 
16113712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16123712e7a4SEvan Quan 	ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle,
161313f5dbd6SEvan Quan 							 clock_ranges);
16143712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16153712e7a4SEvan Quan 
16163712e7a4SEvan Quan 	return ret;
161713f5dbd6SEvan Quan }
161813f5dbd6SEvan Quan 
161913f5dbd6SEvan Quan int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev,
162013f5dbd6SEvan Quan 					     struct pp_display_clock_request *clock)
162113f5dbd6SEvan Quan {
162213f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16233712e7a4SEvan Quan 	int ret = 0;
162413f5dbd6SEvan Quan 
162513f5dbd6SEvan Quan 	if (!pp_funcs->display_clock_voltage_request)
162613f5dbd6SEvan Quan 		return -EOPNOTSUPP;
162713f5dbd6SEvan Quan 
16283712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16293712e7a4SEvan Quan 	ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle,
163013f5dbd6SEvan Quan 						      clock);
16313712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16323712e7a4SEvan Quan 
16333712e7a4SEvan Quan 	return ret;
163413f5dbd6SEvan Quan }
163513f5dbd6SEvan Quan 
163613f5dbd6SEvan Quan int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev,
163713f5dbd6SEvan Quan 				  struct amd_pp_clock_info *clocks)
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->get_current_clocks)
164313f5dbd6SEvan Quan 		return -EOPNOTSUPP;
164413f5dbd6SEvan Quan 
16453712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16463712e7a4SEvan Quan 	ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle,
164713f5dbd6SEvan Quan 					   clocks);
16483712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16493712e7a4SEvan Quan 
16503712e7a4SEvan Quan 	return ret;
165113f5dbd6SEvan Quan }
165213f5dbd6SEvan Quan 
165313f5dbd6SEvan Quan void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev)
165413f5dbd6SEvan Quan {
165513f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
165613f5dbd6SEvan Quan 
165713f5dbd6SEvan Quan 	if (!pp_funcs->notify_smu_enable_pwe)
165813f5dbd6SEvan Quan 		return;
165913f5dbd6SEvan Quan 
16603712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
166113f5dbd6SEvan Quan 	pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle);
16623712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
166313f5dbd6SEvan Quan }
166413f5dbd6SEvan Quan 
166513f5dbd6SEvan Quan int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev,
166613f5dbd6SEvan Quan 					uint32_t count)
166713f5dbd6SEvan Quan {
166813f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16693712e7a4SEvan Quan 	int ret = 0;
167013f5dbd6SEvan Quan 
167113f5dbd6SEvan Quan 	if (!pp_funcs->set_active_display_count)
167213f5dbd6SEvan Quan 		return -EOPNOTSUPP;
167313f5dbd6SEvan Quan 
16743712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16753712e7a4SEvan Quan 	ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle,
167613f5dbd6SEvan Quan 						 count);
16773712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16783712e7a4SEvan Quan 
16793712e7a4SEvan Quan 	return ret;
168013f5dbd6SEvan Quan }
168113f5dbd6SEvan Quan 
168213f5dbd6SEvan Quan int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev,
168313f5dbd6SEvan Quan 					  uint32_t clock)
168413f5dbd6SEvan Quan {
168513f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
16863712e7a4SEvan Quan 	int ret = 0;
168713f5dbd6SEvan Quan 
168813f5dbd6SEvan Quan 	if (!pp_funcs->set_min_deep_sleep_dcefclk)
168913f5dbd6SEvan Quan 		return -EOPNOTSUPP;
169013f5dbd6SEvan Quan 
16913712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
16923712e7a4SEvan Quan 	ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle,
169313f5dbd6SEvan Quan 						   clock);
16943712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
16953712e7a4SEvan Quan 
16963712e7a4SEvan Quan 	return ret;
169713f5dbd6SEvan Quan }
169813f5dbd6SEvan Quan 
169913f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev,
170013f5dbd6SEvan Quan 					     uint32_t clock)
170113f5dbd6SEvan Quan {
170213f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
170313f5dbd6SEvan Quan 
170413f5dbd6SEvan Quan 	if (!pp_funcs->set_hard_min_dcefclk_by_freq)
170513f5dbd6SEvan Quan 		return;
170613f5dbd6SEvan Quan 
17073712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
170813f5dbd6SEvan Quan 	pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle,
170913f5dbd6SEvan Quan 					       clock);
17103712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
171113f5dbd6SEvan Quan }
171213f5dbd6SEvan Quan 
171313f5dbd6SEvan Quan void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev,
171413f5dbd6SEvan Quan 					  uint32_t clock)
171513f5dbd6SEvan Quan {
171613f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
171713f5dbd6SEvan Quan 
171813f5dbd6SEvan Quan 	if (!pp_funcs->set_hard_min_fclk_by_freq)
171913f5dbd6SEvan Quan 		return;
172013f5dbd6SEvan Quan 
17213712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
172213f5dbd6SEvan Quan 	pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle,
172313f5dbd6SEvan Quan 					    clock);
17243712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
172513f5dbd6SEvan Quan }
172613f5dbd6SEvan Quan 
172713f5dbd6SEvan Quan int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev,
172813f5dbd6SEvan Quan 						   bool disable_memory_clock_switch)
172913f5dbd6SEvan Quan {
173013f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
17313712e7a4SEvan Quan 	int ret = 0;
173213f5dbd6SEvan Quan 
173313f5dbd6SEvan Quan 	if (!pp_funcs->display_disable_memory_clock_switch)
173413f5dbd6SEvan Quan 		return 0;
173513f5dbd6SEvan Quan 
17363712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
17373712e7a4SEvan Quan 	ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle,
173813f5dbd6SEvan Quan 							    disable_memory_clock_switch);
17393712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
17403712e7a4SEvan Quan 
17413712e7a4SEvan Quan 	return ret;
174213f5dbd6SEvan Quan }
174313f5dbd6SEvan Quan 
174413f5dbd6SEvan Quan int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev,
174513f5dbd6SEvan Quan 						struct pp_smu_nv_clock_table *max_clocks)
174613f5dbd6SEvan Quan {
174713f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
17483712e7a4SEvan Quan 	int ret = 0;
174913f5dbd6SEvan Quan 
175013f5dbd6SEvan Quan 	if (!pp_funcs->get_max_sustainable_clocks_by_dc)
175113f5dbd6SEvan Quan 		return -EOPNOTSUPP;
175213f5dbd6SEvan Quan 
17533712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
17543712e7a4SEvan Quan 	ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle,
175513f5dbd6SEvan Quan 							 max_clocks);
17563712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
17573712e7a4SEvan Quan 
17583712e7a4SEvan Quan 	return ret;
175913f5dbd6SEvan Quan }
176013f5dbd6SEvan Quan 
176113f5dbd6SEvan Quan enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev,
176213f5dbd6SEvan Quan 						  unsigned int *clock_values_in_khz,
176313f5dbd6SEvan Quan 						  unsigned int *num_states)
176413f5dbd6SEvan Quan {
176513f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
17663712e7a4SEvan Quan 	int ret = 0;
176713f5dbd6SEvan Quan 
176813f5dbd6SEvan Quan 	if (!pp_funcs->get_uclk_dpm_states)
176913f5dbd6SEvan Quan 		return -EOPNOTSUPP;
177013f5dbd6SEvan Quan 
17713712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
17723712e7a4SEvan Quan 	ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle,
177313f5dbd6SEvan Quan 					    clock_values_in_khz,
177413f5dbd6SEvan Quan 					    num_states);
17753712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
17763712e7a4SEvan Quan 
17773712e7a4SEvan Quan 	return ret;
177813f5dbd6SEvan Quan }
177913f5dbd6SEvan Quan 
178013f5dbd6SEvan Quan int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev,
178113f5dbd6SEvan Quan 				   struct dpm_clocks *clock_table)
178213f5dbd6SEvan Quan {
178313f5dbd6SEvan Quan 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
17843712e7a4SEvan Quan 	int ret = 0;
178513f5dbd6SEvan Quan 
178613f5dbd6SEvan Quan 	if (!pp_funcs->get_dpm_clock_table)
178713f5dbd6SEvan Quan 		return -EOPNOTSUPP;
178813f5dbd6SEvan Quan 
17893712e7a4SEvan Quan 	mutex_lock(&adev->pm.mutex);
17903712e7a4SEvan Quan 	ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle,
179113f5dbd6SEvan Quan 					    clock_table);
17923712e7a4SEvan Quan 	mutex_unlock(&adev->pm.mutex);
17933712e7a4SEvan Quan 
17943712e7a4SEvan Quan 	return ret;
179513f5dbd6SEvan Quan }
1796