xref: /dragonfly/sys/dev/drm/amd/powerplay/hwmgr/hwmgr.c (revision b843c749)
1*b843c749SSergey Zigachev /*
2*b843c749SSergey Zigachev  * Copyright 2015 Advanced Micro Devices, Inc.
3*b843c749SSergey Zigachev  *
4*b843c749SSergey Zigachev  * Permission is hereby granted, free of charge, to any person obtaining a
5*b843c749SSergey Zigachev  * copy of this software and associated documentation files (the "Software"),
6*b843c749SSergey Zigachev  * to deal in the Software without restriction, including without limitation
7*b843c749SSergey Zigachev  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*b843c749SSergey Zigachev  * and/or sell copies of the Software, and to permit persons to whom the
9*b843c749SSergey Zigachev  * Software is furnished to do so, subject to the following conditions:
10*b843c749SSergey Zigachev  *
11*b843c749SSergey Zigachev  * The above copyright notice and this permission notice shall be included in
12*b843c749SSergey Zigachev  * all copies or substantial portions of the Software.
13*b843c749SSergey Zigachev  *
14*b843c749SSergey Zigachev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*b843c749SSergey Zigachev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*b843c749SSergey Zigachev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*b843c749SSergey Zigachev  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*b843c749SSergey Zigachev  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*b843c749SSergey Zigachev  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*b843c749SSergey Zigachev  * OTHER DEALINGS IN THE SOFTWARE.
21*b843c749SSergey Zigachev  *
22*b843c749SSergey Zigachev  */
23*b843c749SSergey Zigachev 
24*b843c749SSergey Zigachev #include "pp_debug.h"
25*b843c749SSergey Zigachev #include <linux/delay.h>
26*b843c749SSergey Zigachev #include <linux/kernel.h>
27*b843c749SSergey Zigachev #include <linux/slab.h>
28*b843c749SSergey Zigachev #include <linux/types.h>
29*b843c749SSergey Zigachev #include <linux/pci.h>
30*b843c749SSergey Zigachev #include <drm/amdgpu_drm.h>
31*b843c749SSergey Zigachev #include "power_state.h"
32*b843c749SSergey Zigachev #include "hwmgr.h"
33*b843c749SSergey Zigachev #include "ppsmc.h"
34*b843c749SSergey Zigachev #include "amd_acpi.h"
35*b843c749SSergey Zigachev #include "pp_psm.h"
36*b843c749SSergey Zigachev 
37*b843c749SSergey Zigachev extern const struct pp_smumgr_func ci_smu_funcs;
38*b843c749SSergey Zigachev extern const struct pp_smumgr_func smu8_smu_funcs;
39*b843c749SSergey Zigachev extern const struct pp_smumgr_func iceland_smu_funcs;
40*b843c749SSergey Zigachev extern const struct pp_smumgr_func tonga_smu_funcs;
41*b843c749SSergey Zigachev extern const struct pp_smumgr_func fiji_smu_funcs;
42*b843c749SSergey Zigachev extern const struct pp_smumgr_func polaris10_smu_funcs;
43*b843c749SSergey Zigachev extern const struct pp_smumgr_func vegam_smu_funcs;
44*b843c749SSergey Zigachev extern const struct pp_smumgr_func vega10_smu_funcs;
45*b843c749SSergey Zigachev extern const struct pp_smumgr_func vega12_smu_funcs;
46*b843c749SSergey Zigachev extern const struct pp_smumgr_func smu10_smu_funcs;
47*b843c749SSergey Zigachev 
48*b843c749SSergey Zigachev extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr);
49*b843c749SSergey Zigachev extern int smu8_init_function_pointers(struct pp_hwmgr *hwmgr);
50*b843c749SSergey Zigachev extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr);
51*b843c749SSergey Zigachev extern int vega12_hwmgr_init(struct pp_hwmgr *hwmgr);
52*b843c749SSergey Zigachev extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr);
53*b843c749SSergey Zigachev 
54*b843c749SSergey Zigachev static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
55*b843c749SSergey Zigachev static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr);
56*b843c749SSergey Zigachev static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr);
57*b843c749SSergey Zigachev static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr);
58*b843c749SSergey Zigachev static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr);
59*b843c749SSergey Zigachev static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr);
60*b843c749SSergey Zigachev static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);
61*b843c749SSergey Zigachev 
62*b843c749SSergey Zigachev 
hwmgr_init_workload_prority(struct pp_hwmgr * hwmgr)63*b843c749SSergey Zigachev static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
64*b843c749SSergey Zigachev {
65*b843c749SSergey Zigachev 	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2;
66*b843c749SSergey Zigachev 	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0;
67*b843c749SSergey Zigachev 	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1;
68*b843c749SSergey Zigachev 	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3;
69*b843c749SSergey Zigachev 	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4;
70*b843c749SSergey Zigachev 
71*b843c749SSergey Zigachev 	hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING;
72*b843c749SSergey Zigachev 	hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO;
73*b843c749SSergey Zigachev 	hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
74*b843c749SSergey Zigachev 	hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR;
75*b843c749SSergey Zigachev 	hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE;
76*b843c749SSergey Zigachev }
77*b843c749SSergey Zigachev 
hwmgr_early_init(struct pp_hwmgr * hwmgr)78*b843c749SSergey Zigachev int hwmgr_early_init(struct pp_hwmgr *hwmgr)
79*b843c749SSergey Zigachev {
80*b843c749SSergey Zigachev 	if (!hwmgr)
81*b843c749SSergey Zigachev 		return -EINVAL;
82*b843c749SSergey Zigachev 
83*b843c749SSergey Zigachev 	hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
84*b843c749SSergey Zigachev 	hwmgr->pp_table_version = PP_TABLE_V1;
85*b843c749SSergey Zigachev 	hwmgr->dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
86*b843c749SSergey Zigachev 	hwmgr->request_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
87*b843c749SSergey Zigachev 	hwmgr_init_default_caps(hwmgr);
88*b843c749SSergey Zigachev 	hwmgr_set_user_specify_caps(hwmgr);
89*b843c749SSergey Zigachev 	hwmgr->fan_ctrl_is_in_default_mode = true;
90*b843c749SSergey Zigachev 	hwmgr->reload_fw = 1;
91*b843c749SSergey Zigachev 	hwmgr_init_workload_prority(hwmgr);
92*b843c749SSergey Zigachev 
93*b843c749SSergey Zigachev 	switch (hwmgr->chip_family) {
94*b843c749SSergey Zigachev 	case AMDGPU_FAMILY_CI:
95*b843c749SSergey Zigachev 		hwmgr->smumgr_funcs = &ci_smu_funcs;
96*b843c749SSergey Zigachev 		ci_set_asic_special_caps(hwmgr);
97*b843c749SSergey Zigachev 		hwmgr->feature_mask &= ~(PP_VBI_TIME_SUPPORT_MASK |
98*b843c749SSergey Zigachev 					 PP_ENABLE_GFX_CG_THRU_SMU |
99*b843c749SSergey Zigachev 					 PP_GFXOFF_MASK);
100*b843c749SSergey Zigachev 		hwmgr->pp_table_version = PP_TABLE_V0;
101*b843c749SSergey Zigachev 		hwmgr->od_enabled = false;
102*b843c749SSergey Zigachev 		smu7_init_function_pointers(hwmgr);
103*b843c749SSergey Zigachev 		break;
104*b843c749SSergey Zigachev 	case AMDGPU_FAMILY_CZ:
105*b843c749SSergey Zigachev 		hwmgr->od_enabled = false;
106*b843c749SSergey Zigachev 		hwmgr->smumgr_funcs = &smu8_smu_funcs;
107*b843c749SSergey Zigachev 		hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
108*b843c749SSergey Zigachev 		smu8_init_function_pointers(hwmgr);
109*b843c749SSergey Zigachev 		break;
110*b843c749SSergey Zigachev 	case AMDGPU_FAMILY_VI:
111*b843c749SSergey Zigachev 		hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
112*b843c749SSergey Zigachev 		switch (hwmgr->chip_id) {
113*b843c749SSergey Zigachev 		case CHIP_TOPAZ:
114*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &iceland_smu_funcs;
115*b843c749SSergey Zigachev 			topaz_set_asic_special_caps(hwmgr);
116*b843c749SSergey Zigachev 			hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
117*b843c749SSergey Zigachev 						PP_ENABLE_GFX_CG_THRU_SMU);
118*b843c749SSergey Zigachev 			hwmgr->pp_table_version = PP_TABLE_V0;
119*b843c749SSergey Zigachev 			hwmgr->od_enabled = false;
120*b843c749SSergey Zigachev 			break;
121*b843c749SSergey Zigachev 		case CHIP_TONGA:
122*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &tonga_smu_funcs;
123*b843c749SSergey Zigachev 			tonga_set_asic_special_caps(hwmgr);
124*b843c749SSergey Zigachev 			hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK;
125*b843c749SSergey Zigachev 			break;
126*b843c749SSergey Zigachev 		case CHIP_FIJI:
127*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &fiji_smu_funcs;
128*b843c749SSergey Zigachev 			fiji_set_asic_special_caps(hwmgr);
129*b843c749SSergey Zigachev 			hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
130*b843c749SSergey Zigachev 						PP_ENABLE_GFX_CG_THRU_SMU);
131*b843c749SSergey Zigachev 			break;
132*b843c749SSergey Zigachev 		case CHIP_POLARIS11:
133*b843c749SSergey Zigachev 		case CHIP_POLARIS10:
134*b843c749SSergey Zigachev 		case CHIP_POLARIS12:
135*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &polaris10_smu_funcs;
136*b843c749SSergey Zigachev 			polaris_set_asic_special_caps(hwmgr);
137*b843c749SSergey Zigachev 			hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
138*b843c749SSergey Zigachev 			break;
139*b843c749SSergey Zigachev 		case CHIP_VEGAM:
140*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &vegam_smu_funcs;
141*b843c749SSergey Zigachev 			polaris_set_asic_special_caps(hwmgr);
142*b843c749SSergey Zigachev 			hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
143*b843c749SSergey Zigachev 			break;
144*b843c749SSergey Zigachev 		default:
145*b843c749SSergey Zigachev 			return -EINVAL;
146*b843c749SSergey Zigachev 		}
147*b843c749SSergey Zigachev 		smu7_init_function_pointers(hwmgr);
148*b843c749SSergey Zigachev 		break;
149*b843c749SSergey Zigachev 	case AMDGPU_FAMILY_AI:
150*b843c749SSergey Zigachev 		switch (hwmgr->chip_id) {
151*b843c749SSergey Zigachev 		case CHIP_VEGA10:
152*b843c749SSergey Zigachev 		case CHIP_VEGA20:
153*b843c749SSergey Zigachev 			hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
154*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &vega10_smu_funcs;
155*b843c749SSergey Zigachev 			vega10_hwmgr_init(hwmgr);
156*b843c749SSergey Zigachev 			break;
157*b843c749SSergey Zigachev 		case CHIP_VEGA12:
158*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &vega12_smu_funcs;
159*b843c749SSergey Zigachev 			vega12_hwmgr_init(hwmgr);
160*b843c749SSergey Zigachev 			break;
161*b843c749SSergey Zigachev 		default:
162*b843c749SSergey Zigachev 			return -EINVAL;
163*b843c749SSergey Zigachev 		}
164*b843c749SSergey Zigachev 		break;
165*b843c749SSergey Zigachev 	case AMDGPU_FAMILY_RV:
166*b843c749SSergey Zigachev 		switch (hwmgr->chip_id) {
167*b843c749SSergey Zigachev 		case CHIP_RAVEN:
168*b843c749SSergey Zigachev 			hwmgr->od_enabled = false;
169*b843c749SSergey Zigachev 			hwmgr->smumgr_funcs = &smu10_smu_funcs;
170*b843c749SSergey Zigachev 			smu10_init_function_pointers(hwmgr);
171*b843c749SSergey Zigachev 			break;
172*b843c749SSergey Zigachev 		default:
173*b843c749SSergey Zigachev 			return -EINVAL;
174*b843c749SSergey Zigachev 		}
175*b843c749SSergey Zigachev 		break;
176*b843c749SSergey Zigachev 	default:
177*b843c749SSergey Zigachev 		return -EINVAL;
178*b843c749SSergey Zigachev 	}
179*b843c749SSergey Zigachev 
180*b843c749SSergey Zigachev 	return 0;
181*b843c749SSergey Zigachev }
182*b843c749SSergey Zigachev 
hwmgr_sw_init(struct pp_hwmgr * hwmgr)183*b843c749SSergey Zigachev int hwmgr_sw_init(struct pp_hwmgr *hwmgr)
184*b843c749SSergey Zigachev {
185*b843c749SSergey Zigachev 	if (!hwmgr|| !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->smu_init)
186*b843c749SSergey Zigachev 		return -EINVAL;
187*b843c749SSergey Zigachev 
188*b843c749SSergey Zigachev 	phm_register_irq_handlers(hwmgr);
189*b843c749SSergey Zigachev 
190*b843c749SSergey Zigachev 	return hwmgr->smumgr_funcs->smu_init(hwmgr);
191*b843c749SSergey Zigachev }
192*b843c749SSergey Zigachev 
193*b843c749SSergey Zigachev 
hwmgr_sw_fini(struct pp_hwmgr * hwmgr)194*b843c749SSergey Zigachev int hwmgr_sw_fini(struct pp_hwmgr *hwmgr)
195*b843c749SSergey Zigachev {
196*b843c749SSergey Zigachev 	if (hwmgr && hwmgr->smumgr_funcs && hwmgr->smumgr_funcs->smu_fini)
197*b843c749SSergey Zigachev 		hwmgr->smumgr_funcs->smu_fini(hwmgr);
198*b843c749SSergey Zigachev 
199*b843c749SSergey Zigachev 	return 0;
200*b843c749SSergey Zigachev }
201*b843c749SSergey Zigachev 
hwmgr_hw_init(struct pp_hwmgr * hwmgr)202*b843c749SSergey Zigachev int hwmgr_hw_init(struct pp_hwmgr *hwmgr)
203*b843c749SSergey Zigachev {
204*b843c749SSergey Zigachev 	int ret = 0;
205*b843c749SSergey Zigachev 
206*b843c749SSergey Zigachev 	if (!hwmgr || !hwmgr->smumgr_funcs)
207*b843c749SSergey Zigachev 		return -EINVAL;
208*b843c749SSergey Zigachev 
209*b843c749SSergey Zigachev 	if (hwmgr->smumgr_funcs->start_smu) {
210*b843c749SSergey Zigachev 		ret = hwmgr->smumgr_funcs->start_smu(hwmgr);
211*b843c749SSergey Zigachev 		if (ret) {
212*b843c749SSergey Zigachev 			pr_err("smc start failed\n");
213*b843c749SSergey Zigachev 			return -EINVAL;
214*b843c749SSergey Zigachev 		}
215*b843c749SSergey Zigachev 	}
216*b843c749SSergey Zigachev 
217*b843c749SSergey Zigachev 	if (!hwmgr->pm_en)
218*b843c749SSergey Zigachev 		return 0;
219*b843c749SSergey Zigachev 
220*b843c749SSergey Zigachev 	if (!hwmgr->pptable_func ||
221*b843c749SSergey Zigachev 	    !hwmgr->pptable_func->pptable_init ||
222*b843c749SSergey Zigachev 	    !hwmgr->hwmgr_func->backend_init) {
223*b843c749SSergey Zigachev 		hwmgr->pm_en = false;
224*b843c749SSergey Zigachev 		pr_info("dpm not supported \n");
225*b843c749SSergey Zigachev 		return 0;
226*b843c749SSergey Zigachev 	}
227*b843c749SSergey Zigachev 
228*b843c749SSergey Zigachev 	ret = hwmgr->pptable_func->pptable_init(hwmgr);
229*b843c749SSergey Zigachev 	if (ret)
230*b843c749SSergey Zigachev 		goto err;
231*b843c749SSergey Zigachev 
232*b843c749SSergey Zigachev 	((struct amdgpu_device *)hwmgr->adev)->pm.no_fan =
233*b843c749SSergey Zigachev 				hwmgr->thermal_controller.fanInfo.bNoFan;
234*b843c749SSergey Zigachev 
235*b843c749SSergey Zigachev 	ret = hwmgr->hwmgr_func->backend_init(hwmgr);
236*b843c749SSergey Zigachev 	if (ret)
237*b843c749SSergey Zigachev 		goto err1;
238*b843c749SSergey Zigachev  /* make sure dc limits are valid */
239*b843c749SSergey Zigachev 	if ((hwmgr->dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
240*b843c749SSergey Zigachev 			(hwmgr->dyn_state.max_clock_voltage_on_dc.mclk == 0))
241*b843c749SSergey Zigachev 			hwmgr->dyn_state.max_clock_voltage_on_dc =
242*b843c749SSergey Zigachev 					hwmgr->dyn_state.max_clock_voltage_on_ac;
243*b843c749SSergey Zigachev 
244*b843c749SSergey Zigachev 	ret = psm_init_power_state_table(hwmgr);
245*b843c749SSergey Zigachev 	if (ret)
246*b843c749SSergey Zigachev 		goto err2;
247*b843c749SSergey Zigachev 
248*b843c749SSergey Zigachev 	ret = phm_setup_asic(hwmgr);
249*b843c749SSergey Zigachev 	if (ret)
250*b843c749SSergey Zigachev 		goto err2;
251*b843c749SSergey Zigachev 
252*b843c749SSergey Zigachev 	ret = phm_enable_dynamic_state_management(hwmgr);
253*b843c749SSergey Zigachev 	if (ret)
254*b843c749SSergey Zigachev 		goto err2;
255*b843c749SSergey Zigachev 	ret = phm_start_thermal_controller(hwmgr);
256*b843c749SSergey Zigachev 	ret |= psm_set_performance_states(hwmgr);
257*b843c749SSergey Zigachev 	if (ret)
258*b843c749SSergey Zigachev 		goto err2;
259*b843c749SSergey Zigachev 
260*b843c749SSergey Zigachev 	((struct amdgpu_device *)hwmgr->adev)->pm.dpm_enabled = true;
261*b843c749SSergey Zigachev 
262*b843c749SSergey Zigachev 	return 0;
263*b843c749SSergey Zigachev err2:
264*b843c749SSergey Zigachev 	if (hwmgr->hwmgr_func->backend_fini)
265*b843c749SSergey Zigachev 		hwmgr->hwmgr_func->backend_fini(hwmgr);
266*b843c749SSergey Zigachev err1:
267*b843c749SSergey Zigachev 	if (hwmgr->pptable_func->pptable_fini)
268*b843c749SSergey Zigachev 		hwmgr->pptable_func->pptable_fini(hwmgr);
269*b843c749SSergey Zigachev err:
270*b843c749SSergey Zigachev 	return ret;
271*b843c749SSergey Zigachev }
272*b843c749SSergey Zigachev 
hwmgr_hw_fini(struct pp_hwmgr * hwmgr)273*b843c749SSergey Zigachev int hwmgr_hw_fini(struct pp_hwmgr *hwmgr)
274*b843c749SSergey Zigachev {
275*b843c749SSergey Zigachev 	if (!hwmgr || !hwmgr->pm_en)
276*b843c749SSergey Zigachev 		return 0;
277*b843c749SSergey Zigachev 
278*b843c749SSergey Zigachev 	phm_stop_thermal_controller(hwmgr);
279*b843c749SSergey Zigachev 	psm_set_boot_states(hwmgr);
280*b843c749SSergey Zigachev 	psm_adjust_power_state_dynamic(hwmgr, false, NULL);
281*b843c749SSergey Zigachev 	phm_disable_dynamic_state_management(hwmgr);
282*b843c749SSergey Zigachev 	phm_disable_clock_power_gatings(hwmgr);
283*b843c749SSergey Zigachev 
284*b843c749SSergey Zigachev 	if (hwmgr->hwmgr_func->backend_fini)
285*b843c749SSergey Zigachev 		hwmgr->hwmgr_func->backend_fini(hwmgr);
286*b843c749SSergey Zigachev 	if (hwmgr->pptable_func->pptable_fini)
287*b843c749SSergey Zigachev 		hwmgr->pptable_func->pptable_fini(hwmgr);
288*b843c749SSergey Zigachev 	return psm_fini_power_state_table(hwmgr);
289*b843c749SSergey Zigachev }
290*b843c749SSergey Zigachev 
hwmgr_suspend(struct pp_hwmgr * hwmgr)291*b843c749SSergey Zigachev int hwmgr_suspend(struct pp_hwmgr *hwmgr)
292*b843c749SSergey Zigachev {
293*b843c749SSergey Zigachev 	int ret = 0;
294*b843c749SSergey Zigachev 
295*b843c749SSergey Zigachev 	if (!hwmgr || !hwmgr->pm_en)
296*b843c749SSergey Zigachev 		return 0;
297*b843c749SSergey Zigachev 
298*b843c749SSergey Zigachev 	phm_disable_smc_firmware_ctf(hwmgr);
299*b843c749SSergey Zigachev 	ret = psm_set_boot_states(hwmgr);
300*b843c749SSergey Zigachev 	if (ret)
301*b843c749SSergey Zigachev 		return ret;
302*b843c749SSergey Zigachev 	ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
303*b843c749SSergey Zigachev 	if (ret)
304*b843c749SSergey Zigachev 		return ret;
305*b843c749SSergey Zigachev 	ret = phm_power_down_asic(hwmgr);
306*b843c749SSergey Zigachev 
307*b843c749SSergey Zigachev 	return ret;
308*b843c749SSergey Zigachev }
309*b843c749SSergey Zigachev 
hwmgr_resume(struct pp_hwmgr * hwmgr)310*b843c749SSergey Zigachev int hwmgr_resume(struct pp_hwmgr *hwmgr)
311*b843c749SSergey Zigachev {
312*b843c749SSergey Zigachev 	int ret = 0;
313*b843c749SSergey Zigachev 
314*b843c749SSergey Zigachev 	if (!hwmgr)
315*b843c749SSergey Zigachev 		return -EINVAL;
316*b843c749SSergey Zigachev 
317*b843c749SSergey Zigachev 	if (hwmgr->smumgr_funcs && hwmgr->smumgr_funcs->start_smu) {
318*b843c749SSergey Zigachev 		if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {
319*b843c749SSergey Zigachev 			pr_err("smc start failed\n");
320*b843c749SSergey Zigachev 			return -EINVAL;
321*b843c749SSergey Zigachev 		}
322*b843c749SSergey Zigachev 	}
323*b843c749SSergey Zigachev 
324*b843c749SSergey Zigachev 	if (!hwmgr->pm_en)
325*b843c749SSergey Zigachev 		return 0;
326*b843c749SSergey Zigachev 
327*b843c749SSergey Zigachev 	ret = phm_setup_asic(hwmgr);
328*b843c749SSergey Zigachev 	if (ret)
329*b843c749SSergey Zigachev 		return ret;
330*b843c749SSergey Zigachev 
331*b843c749SSergey Zigachev 	ret = phm_enable_dynamic_state_management(hwmgr);
332*b843c749SSergey Zigachev 	if (ret)
333*b843c749SSergey Zigachev 		return ret;
334*b843c749SSergey Zigachev 	ret = phm_start_thermal_controller(hwmgr);
335*b843c749SSergey Zigachev 	ret |= psm_set_performance_states(hwmgr);
336*b843c749SSergey Zigachev 	if (ret)
337*b843c749SSergey Zigachev 		return ret;
338*b843c749SSergey Zigachev 
339*b843c749SSergey Zigachev 	ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
340*b843c749SSergey Zigachev 
341*b843c749SSergey Zigachev 	return ret;
342*b843c749SSergey Zigachev }
343*b843c749SSergey Zigachev 
power_state_convert(enum amd_pm_state_type state)344*b843c749SSergey Zigachev static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type  state)
345*b843c749SSergey Zigachev {
346*b843c749SSergey Zigachev 	switch (state) {
347*b843c749SSergey Zigachev 	case POWER_STATE_TYPE_BATTERY:
348*b843c749SSergey Zigachev 		return PP_StateUILabel_Battery;
349*b843c749SSergey Zigachev 	case POWER_STATE_TYPE_BALANCED:
350*b843c749SSergey Zigachev 		return PP_StateUILabel_Balanced;
351*b843c749SSergey Zigachev 	case POWER_STATE_TYPE_PERFORMANCE:
352*b843c749SSergey Zigachev 		return PP_StateUILabel_Performance;
353*b843c749SSergey Zigachev 	default:
354*b843c749SSergey Zigachev 		return PP_StateUILabel_None;
355*b843c749SSergey Zigachev 	}
356*b843c749SSergey Zigachev }
357*b843c749SSergey Zigachev 
hwmgr_handle_task(struct pp_hwmgr * hwmgr,enum amd_pp_task task_id,enum amd_pm_state_type * user_state)358*b843c749SSergey Zigachev int hwmgr_handle_task(struct pp_hwmgr *hwmgr, enum amd_pp_task task_id,
359*b843c749SSergey Zigachev 		enum amd_pm_state_type *user_state)
360*b843c749SSergey Zigachev {
361*b843c749SSergey Zigachev 	int ret = 0;
362*b843c749SSergey Zigachev 
363*b843c749SSergey Zigachev 	if (hwmgr == NULL)
364*b843c749SSergey Zigachev 		return -EINVAL;
365*b843c749SSergey Zigachev 
366*b843c749SSergey Zigachev 	switch (task_id) {
367*b843c749SSergey Zigachev 	case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE:
368*b843c749SSergey Zigachev 		ret = phm_pre_display_configuration_changed(hwmgr);
369*b843c749SSergey Zigachev 		if (ret)
370*b843c749SSergey Zigachev 			return ret;
371*b843c749SSergey Zigachev 		ret = phm_set_cpu_power_state(hwmgr);
372*b843c749SSergey Zigachev 		if (ret)
373*b843c749SSergey Zigachev 			return ret;
374*b843c749SSergey Zigachev 		ret = psm_set_performance_states(hwmgr);
375*b843c749SSergey Zigachev 		if (ret)
376*b843c749SSergey Zigachev 			return ret;
377*b843c749SSergey Zigachev 		ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
378*b843c749SSergey Zigachev 		break;
379*b843c749SSergey Zigachev 	case AMD_PP_TASK_ENABLE_USER_STATE:
380*b843c749SSergey Zigachev 	{
381*b843c749SSergey Zigachev 		enum PP_StateUILabel requested_ui_label;
382*b843c749SSergey Zigachev 		struct pp_power_state *requested_ps = NULL;
383*b843c749SSergey Zigachev 
384*b843c749SSergey Zigachev 		if (user_state == NULL) {
385*b843c749SSergey Zigachev 			ret = -EINVAL;
386*b843c749SSergey Zigachev 			break;
387*b843c749SSergey Zigachev 		}
388*b843c749SSergey Zigachev 
389*b843c749SSergey Zigachev 		requested_ui_label = power_state_convert(*user_state);
390*b843c749SSergey Zigachev 		ret = psm_set_user_performance_state(hwmgr, requested_ui_label, &requested_ps);
391*b843c749SSergey Zigachev 		if (ret)
392*b843c749SSergey Zigachev 			return ret;
393*b843c749SSergey Zigachev 		ret = psm_adjust_power_state_dynamic(hwmgr, false, requested_ps);
394*b843c749SSergey Zigachev 		break;
395*b843c749SSergey Zigachev 	}
396*b843c749SSergey Zigachev 	case AMD_PP_TASK_COMPLETE_INIT:
397*b843c749SSergey Zigachev 	case AMD_PP_TASK_READJUST_POWER_STATE:
398*b843c749SSergey Zigachev 		ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
399*b843c749SSergey Zigachev 		break;
400*b843c749SSergey Zigachev 	default:
401*b843c749SSergey Zigachev 		break;
402*b843c749SSergey Zigachev 	}
403*b843c749SSergey Zigachev 	return ret;
404*b843c749SSergey Zigachev }
405*b843c749SSergey Zigachev 
hwmgr_init_default_caps(struct pp_hwmgr * hwmgr)406*b843c749SSergey Zigachev void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr)
407*b843c749SSergey Zigachev {
408*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
409*b843c749SSergey Zigachev 
410*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM);
411*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM);
412*b843c749SSergey Zigachev 
413*b843c749SSergey Zigachev #if defined(CONFIG_ACPI)
414*b843c749SSergey Zigachev 	if (amdgpu_acpi_is_pcie_performance_request_supported(hwmgr->adev))
415*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
416*b843c749SSergey Zigachev #endif
417*b843c749SSergey Zigachev 
418*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
419*b843c749SSergey Zigachev 		PHM_PlatformCaps_DynamicPatchPowerState);
420*b843c749SSergey Zigachev 
421*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
422*b843c749SSergey Zigachev 		PHM_PlatformCaps_EnableSMU7ThermalManagement);
423*b843c749SSergey Zigachev 
424*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
425*b843c749SSergey Zigachev 			PHM_PlatformCaps_DynamicPowerManagement);
426*b843c749SSergey Zigachev 
427*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
428*b843c749SSergey Zigachev 					PHM_PlatformCaps_SMC);
429*b843c749SSergey Zigachev 
430*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
431*b843c749SSergey Zigachev 					PHM_PlatformCaps_DynamicUVDState);
432*b843c749SSergey Zigachev 
433*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
434*b843c749SSergey Zigachev 						PHM_PlatformCaps_FanSpeedInTableIsRPM);
435*b843c749SSergey Zigachev 	return;
436*b843c749SSergey Zigachev }
437*b843c749SSergey Zigachev 
hwmgr_set_user_specify_caps(struct pp_hwmgr * hwmgr)438*b843c749SSergey Zigachev int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr)
439*b843c749SSergey Zigachev {
440*b843c749SSergey Zigachev 	if (hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK)
441*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
442*b843c749SSergey Zigachev 			PHM_PlatformCaps_SclkDeepSleep);
443*b843c749SSergey Zigachev 	else
444*b843c749SSergey Zigachev 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
445*b843c749SSergey Zigachev 			PHM_PlatformCaps_SclkDeepSleep);
446*b843c749SSergey Zigachev 
447*b843c749SSergey Zigachev 	if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
448*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
449*b843c749SSergey Zigachev 			    PHM_PlatformCaps_PowerContainment);
450*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
451*b843c749SSergey Zigachev 			PHM_PlatformCaps_CAC);
452*b843c749SSergey Zigachev 	} else {
453*b843c749SSergey Zigachev 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
454*b843c749SSergey Zigachev 			    PHM_PlatformCaps_PowerContainment);
455*b843c749SSergey Zigachev 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
456*b843c749SSergey Zigachev 			PHM_PlatformCaps_CAC);
457*b843c749SSergey Zigachev 	}
458*b843c749SSergey Zigachev 
459*b843c749SSergey Zigachev 	if (hwmgr->feature_mask & PP_OVERDRIVE_MASK)
460*b843c749SSergey Zigachev 		hwmgr->od_enabled = true;
461*b843c749SSergey Zigachev 
462*b843c749SSergey Zigachev 	return 0;
463*b843c749SSergey Zigachev }
464*b843c749SSergey Zigachev 
polaris_set_asic_special_caps(struct pp_hwmgr * hwmgr)465*b843c749SSergey Zigachev int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
466*b843c749SSergey Zigachev {
467*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
468*b843c749SSergey Zigachev 						PHM_PlatformCaps_EVV);
469*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
470*b843c749SSergey Zigachev 						PHM_PlatformCaps_SQRamping);
471*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
472*b843c749SSergey Zigachev 						PHM_PlatformCaps_RegulatorHot);
473*b843c749SSergey Zigachev 
474*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
475*b843c749SSergey Zigachev 					PHM_PlatformCaps_AutomaticDCTransition);
476*b843c749SSergey Zigachev 
477*b843c749SSergey Zigachev 	if (hwmgr->chip_id != CHIP_POLARIS10)
478*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
479*b843c749SSergey Zigachev 					PHM_PlatformCaps_SPLLShutdownSupport);
480*b843c749SSergey Zigachev 
481*b843c749SSergey Zigachev 	if (hwmgr->chip_id != CHIP_POLARIS11) {
482*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
483*b843c749SSergey Zigachev 							PHM_PlatformCaps_DBRamping);
484*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
485*b843c749SSergey Zigachev 							PHM_PlatformCaps_TDRamping);
486*b843c749SSergey Zigachev 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
487*b843c749SSergey Zigachev 							PHM_PlatformCaps_TCPRamping);
488*b843c749SSergey Zigachev 	}
489*b843c749SSergey Zigachev 	return 0;
490*b843c749SSergey Zigachev }
491*b843c749SSergey Zigachev 
fiji_set_asic_special_caps(struct pp_hwmgr * hwmgr)492*b843c749SSergey Zigachev int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr)
493*b843c749SSergey Zigachev {
494*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
495*b843c749SSergey Zigachev 						PHM_PlatformCaps_EVV);
496*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
497*b843c749SSergey Zigachev 			PHM_PlatformCaps_SQRamping);
498*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
499*b843c749SSergey Zigachev 			PHM_PlatformCaps_DBRamping);
500*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
501*b843c749SSergey Zigachev 			PHM_PlatformCaps_TDRamping);
502*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
503*b843c749SSergey Zigachev 			PHM_PlatformCaps_TCPRamping);
504*b843c749SSergey Zigachev 	return 0;
505*b843c749SSergey Zigachev }
506*b843c749SSergey Zigachev 
tonga_set_asic_special_caps(struct pp_hwmgr * hwmgr)507*b843c749SSergey Zigachev int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr)
508*b843c749SSergey Zigachev {
509*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
510*b843c749SSergey Zigachev 						PHM_PlatformCaps_EVV);
511*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
512*b843c749SSergey Zigachev 			PHM_PlatformCaps_SQRamping);
513*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
514*b843c749SSergey Zigachev 			PHM_PlatformCaps_DBRamping);
515*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
516*b843c749SSergey Zigachev 			PHM_PlatformCaps_TDRamping);
517*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
518*b843c749SSergey Zigachev 			PHM_PlatformCaps_TCPRamping);
519*b843c749SSergey Zigachev 
520*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
521*b843c749SSergey Zigachev 		      PHM_PlatformCaps_UVDPowerGating);
522*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
523*b843c749SSergey Zigachev 		      PHM_PlatformCaps_VCEPowerGating);
524*b843c749SSergey Zigachev 	return 0;
525*b843c749SSergey Zigachev }
526*b843c749SSergey Zigachev 
topaz_set_asic_special_caps(struct pp_hwmgr * hwmgr)527*b843c749SSergey Zigachev int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr)
528*b843c749SSergey Zigachev {
529*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
530*b843c749SSergey Zigachev 						PHM_PlatformCaps_EVV);
531*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
532*b843c749SSergey Zigachev 			PHM_PlatformCaps_SQRamping);
533*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
534*b843c749SSergey Zigachev 			PHM_PlatformCaps_DBRamping);
535*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
536*b843c749SSergey Zigachev 			PHM_PlatformCaps_TDRamping);
537*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
538*b843c749SSergey Zigachev 			PHM_PlatformCaps_TCPRamping);
539*b843c749SSergey Zigachev 	return 0;
540*b843c749SSergey Zigachev }
541*b843c749SSergey Zigachev 
ci_set_asic_special_caps(struct pp_hwmgr * hwmgr)542*b843c749SSergey Zigachev int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr)
543*b843c749SSergey Zigachev {
544*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
545*b843c749SSergey Zigachev 			PHM_PlatformCaps_SQRamping);
546*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
547*b843c749SSergey Zigachev 			PHM_PlatformCaps_DBRamping);
548*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
549*b843c749SSergey Zigachev 			PHM_PlatformCaps_TDRamping);
550*b843c749SSergey Zigachev 	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
551*b843c749SSergey Zigachev 			PHM_PlatformCaps_TCPRamping);
552*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
553*b843c749SSergey Zigachev 			PHM_PlatformCaps_MemorySpreadSpectrumSupport);
554*b843c749SSergey Zigachev 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
555*b843c749SSergey Zigachev 			PHM_PlatformCaps_EngineSpreadSpectrumSupport);
556*b843c749SSergey Zigachev 	return 0;
557*b843c749SSergey Zigachev }
558