1f46a221bSXiaojian Du /*
2f46a221bSXiaojian Du  * Copyright 2020 Advanced Micro Devices, Inc.
3f46a221bSXiaojian Du  *
4f46a221bSXiaojian Du  * Permission is hereby granted, free of charge, to any person obtaining a
5f46a221bSXiaojian Du  * copy of this software and associated documentation files (the "Software"),
6f46a221bSXiaojian Du  * to deal in the Software without restriction, including without limitation
7f46a221bSXiaojian Du  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f46a221bSXiaojian Du  * and/or sell copies of the Software, and to permit persons to whom the
9f46a221bSXiaojian Du  * Software is furnished to do so, subject to the following conditions:
10f46a221bSXiaojian Du  *
11f46a221bSXiaojian Du  * The above copyright notice and this permission notice shall be included in
12f46a221bSXiaojian Du  * all copies or substantial portions of the Software.
13f46a221bSXiaojian Du  *
14f46a221bSXiaojian Du  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f46a221bSXiaojian Du  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f46a221bSXiaojian Du  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17f46a221bSXiaojian Du  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18f46a221bSXiaojian Du  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19f46a221bSXiaojian Du  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20f46a221bSXiaojian Du  * OTHER DEALINGS IN THE SOFTWARE.
21f46a221bSXiaojian Du  *
22f46a221bSXiaojian Du  */
23f46a221bSXiaojian Du 
24f46a221bSXiaojian Du #define SWSMU_CODE_LAYER_L2
25f46a221bSXiaojian Du 
26f46a221bSXiaojian Du #include "amdgpu.h"
27f46a221bSXiaojian Du #include "amdgpu_smu.h"
28f46a221bSXiaojian Du #include "smu_v11_0.h"
29f46a221bSXiaojian Du #include "smu11_driver_if_vangogh.h"
30f46a221bSXiaojian Du #include "vangogh_ppt.h"
31f46a221bSXiaojian Du #include "smu_v11_5_ppsmc.h"
32f46a221bSXiaojian Du #include "smu_v11_5_pmfw.h"
33f46a221bSXiaojian Du #include "smu_cmn.h"
34eefdf047SJinzhou Su #include "soc15_common.h"
35eefdf047SJinzhou Su #include "asic_reg/gc/gc_10_3_0_offset.h"
36eefdf047SJinzhou Su #include "asic_reg/gc/gc_10_3_0_sh_mask.h"
37517cb957SHuang Rui #include <asm/processor.h>
38f46a221bSXiaojian Du 
39f46a221bSXiaojian Du /*
40f46a221bSXiaojian Du  * DO NOT use these for err/warn/info/debug messages.
41f46a221bSXiaojian Du  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
42f46a221bSXiaojian Du  * They are more MGPU friendly.
43f46a221bSXiaojian Du  */
44f46a221bSXiaojian Du #undef pr_err
45f46a221bSXiaojian Du #undef pr_warn
46f46a221bSXiaojian Du #undef pr_info
47f46a221bSXiaojian Du #undef pr_debug
48f46a221bSXiaojian Du 
49f46a221bSXiaojian Du #define FEATURE_MASK(feature) (1ULL << feature)
50f46a221bSXiaojian Du #define SMC_DPM_FEATURE ( \
51f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
52f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_VCN_DPM_BIT)	 | \
53f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_FCLK_DPM_BIT)	 | \
54f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT)	 | \
55f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)	 | \
56f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_LCLK_DPM_BIT)	 | \
57f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT)	 | \
58f46a221bSXiaojian Du 	FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
59271ab489SXiaojian Du 	FEATURE_MASK(FEATURE_GFX_DPM_BIT))
60f46a221bSXiaojian Du 
61f46a221bSXiaojian Du static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
62271ab489SXiaojian Du 	MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,			0),
63271ab489SXiaojian Du 	MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,		0),
64271ab489SXiaojian Du 	MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,	0),
65271ab489SXiaojian Du 	MSG_MAP(EnableGfxOff,                   PPSMC_MSG_EnableGfxOff,			0),
66b58ce1feSJinzhou Su 	MSG_MAP(AllowGfxOff,                    PPSMC_MSG_AllowGfxOff,          0),
67b58ce1feSJinzhou Su 	MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisallowGfxOff,		0),
68271ab489SXiaojian Du 	MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile,	0),
69271ab489SXiaojian Du 	MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile,		0),
70271ab489SXiaojian Du 	MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn,			0),
71271ab489SXiaojian Du 	MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn,			0),
72a0f55287SXiaomeng Hou 	MSG_MAP(RlcPowerNotify,                 PPSMC_MSG_RlcPowerNotify,		0),
73271ab489SXiaojian Du 	MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn,		0),
74271ab489SXiaojian Du 	MSG_MAP(SetSoftMinGfxclk,               PPSMC_MSG_SetSoftMinGfxclk,		0),
75271ab489SXiaojian Du 	MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify,		0),
76271ab489SXiaojian Du 	MSG_MAP(SetHardMinIspiclkByFreq,        PPSMC_MSG_SetHardMinIspiclkByFreq,	0),
77271ab489SXiaojian Du 	MSG_MAP(SetHardMinIspxclkByFreq,        PPSMC_MSG_SetHardMinIspxclkByFreq,	0),
78271ab489SXiaojian Du 	MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh,	0),
79271ab489SXiaojian Du 	MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow,		0),
80271ab489SXiaojian Du 	MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,	0),
81271ab489SXiaojian Du 	MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,	0),
82271ab489SXiaojian Du 	MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset,		0),
83271ab489SXiaojian Du 	MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,	0),
84271ab489SXiaojian Du 	MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq,	0),
85271ab489SXiaojian Du 	MSG_MAP(SetSoftMinFclk,                 PPSMC_MSG_SetSoftMinFclk,		0),
86271ab489SXiaojian Du 	MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn,		0),
87271ab489SXiaojian Du 	MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode,		0),
88271ab489SXiaojian Du 	MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency,	0),
89271ab489SXiaojian Du 	MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency,		0),
90271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk,		0),
91271ab489SXiaojian Du 	MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk,		0),
92271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq,	0),
93271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq,		0),
94271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn,			0),
95271ab489SXiaojian Du 	MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage,	0),
96271ab489SXiaojian Du 	MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg,			0),
97271ab489SXiaojian Du 	MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg,				0),
98271ab489SXiaojian Du 	MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq,		0),
99271ab489SXiaojian Du 	MSG_MAP(SetSoftMinSocclkByFreq,         PPSMC_MSG_SetSoftMinSocclkByFreq,	0),
100271ab489SXiaojian Du 	MSG_MAP(PowerUpCvip,                    PPSMC_MSG_PowerUpCvip,				0),
101271ab489SXiaojian Du 	MSG_MAP(PowerDownCvip,                  PPSMC_MSG_PowerDownCvip,			0),
102271ab489SXiaojian Du 	MSG_MAP(GetPptLimit,                        PPSMC_MSG_GetPptLimit,			0),
103271ab489SXiaojian Du 	MSG_MAP(GetThermalLimit,                    PPSMC_MSG_GetThermalLimit,		0),
104271ab489SXiaojian Du 	MSG_MAP(GetCurrentTemperature,              PPSMC_MSG_GetCurrentTemperature, 0),
105271ab489SXiaojian Du 	MSG_MAP(GetCurrentPower,                    PPSMC_MSG_GetCurrentPower,		 0),
106271ab489SXiaojian Du 	MSG_MAP(GetCurrentVoltage,                  PPSMC_MSG_GetCurrentVoltage,	 0),
107271ab489SXiaojian Du 	MSG_MAP(GetCurrentCurrent,                  PPSMC_MSG_GetCurrentCurrent,	 0),
108271ab489SXiaojian Du 	MSG_MAP(GetAverageCpuActivity,              PPSMC_MSG_GetAverageCpuActivity, 0),
109271ab489SXiaojian Du 	MSG_MAP(GetAverageGfxActivity,              PPSMC_MSG_GetAverageGfxActivity, 0),
110271ab489SXiaojian Du 	MSG_MAP(GetAveragePower,                    PPSMC_MSG_GetAveragePower,		 0),
111271ab489SXiaojian Du 	MSG_MAP(GetAverageTemperature,              PPSMC_MSG_GetAverageTemperature, 0),
112271ab489SXiaojian Du 	MSG_MAP(SetAveragePowerTimeConstant,        PPSMC_MSG_SetAveragePowerTimeConstant,			0),
113271ab489SXiaojian Du 	MSG_MAP(SetAverageActivityTimeConstant,     PPSMC_MSG_SetAverageActivityTimeConstant,		0),
114271ab489SXiaojian Du 	MSG_MAP(SetAverageTemperatureTimeConstant,  PPSMC_MSG_SetAverageTemperatureTimeConstant,	0),
115271ab489SXiaojian Du 	MSG_MAP(SetMitigationEndHysteresis,         PPSMC_MSG_SetMitigationEndHysteresis,			0),
116271ab489SXiaojian Du 	MSG_MAP(GetCurrentFreq,                     PPSMC_MSG_GetCurrentFreq,						0),
117271ab489SXiaojian Du 	MSG_MAP(SetReducedPptLimit,                 PPSMC_MSG_SetReducedPptLimit,					0),
118271ab489SXiaojian Du 	MSG_MAP(SetReducedThermalLimit,             PPSMC_MSG_SetReducedThermalLimit,				0),
119271ab489SXiaojian Du 	MSG_MAP(DramLogSetDramAddr,                 PPSMC_MSG_DramLogSetDramAddr,					0),
120271ab489SXiaojian Du 	MSG_MAP(StartDramLogging,                   PPSMC_MSG_StartDramLogging,						0),
121271ab489SXiaojian Du 	MSG_MAP(StopDramLogging,                    PPSMC_MSG_StopDramLogging,						0),
122271ab489SXiaojian Du 	MSG_MAP(SetSoftMinCclk,                     PPSMC_MSG_SetSoftMinCclk,						0),
123271ab489SXiaojian Du 	MSG_MAP(SetSoftMaxCclk,                     PPSMC_MSG_SetSoftMaxCclk,						0),
124eefdf047SJinzhou Su 	MSG_MAP(RequestActiveWgp,                   PPSMC_MSG_RequestActiveWgp,                     0),
125ae07970aSXiaomeng Hou 	MSG_MAP(SetFastPPTLimit,                    PPSMC_MSG_SetFastPPTLimit,						0),
126ae07970aSXiaomeng Hou 	MSG_MAP(SetSlowPPTLimit,                    PPSMC_MSG_SetSlowPPTLimit,						0),
127ae07970aSXiaomeng Hou 	MSG_MAP(GetFastPPTLimit,                    PPSMC_MSG_GetFastPPTLimit,						0),
128ae07970aSXiaomeng Hou 	MSG_MAP(GetSlowPPTLimit,                    PPSMC_MSG_GetSlowPPTLimit,						0),
129f46a221bSXiaojian Du };
130f46a221bSXiaojian Du 
131f46a221bSXiaojian Du static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = {
132f46a221bSXiaojian Du 	FEA_MAP(PPT),
133f46a221bSXiaojian Du 	FEA_MAP(TDC),
134f46a221bSXiaojian Du 	FEA_MAP(THERMAL),
135f46a221bSXiaojian Du 	FEA_MAP(DS_GFXCLK),
136f46a221bSXiaojian Du 	FEA_MAP(DS_SOCCLK),
137f46a221bSXiaojian Du 	FEA_MAP(DS_LCLK),
138f46a221bSXiaojian Du 	FEA_MAP(DS_FCLK),
139f46a221bSXiaojian Du 	FEA_MAP(DS_MP1CLK),
140f46a221bSXiaojian Du 	FEA_MAP(DS_MP0CLK),
141f46a221bSXiaojian Du 	FEA_MAP(ATHUB_PG),
142f46a221bSXiaojian Du 	FEA_MAP(CCLK_DPM),
143f46a221bSXiaojian Du 	FEA_MAP(FAN_CONTROLLER),
144f46a221bSXiaojian Du 	FEA_MAP(ULV),
145f46a221bSXiaojian Du 	FEA_MAP(VCN_DPM),
146f46a221bSXiaojian Du 	FEA_MAP(LCLK_DPM),
147f46a221bSXiaojian Du 	FEA_MAP(SHUBCLK_DPM),
148f46a221bSXiaojian Du 	FEA_MAP(DCFCLK_DPM),
149f46a221bSXiaojian Du 	FEA_MAP(DS_DCFCLK),
150f46a221bSXiaojian Du 	FEA_MAP(S0I2),
151f46a221bSXiaojian Du 	FEA_MAP(SMU_LOW_POWER),
152f46a221bSXiaojian Du 	FEA_MAP(GFX_DEM),
153f46a221bSXiaojian Du 	FEA_MAP(PSI),
154f46a221bSXiaojian Du 	FEA_MAP(PROCHOT),
155f46a221bSXiaojian Du 	FEA_MAP(CPUOFF),
156f46a221bSXiaojian Du 	FEA_MAP(STAPM),
157f46a221bSXiaojian Du 	FEA_MAP(S0I3),
158f46a221bSXiaojian Du 	FEA_MAP(DF_CSTATES),
159f46a221bSXiaojian Du 	FEA_MAP(PERF_LIMIT),
160f46a221bSXiaojian Du 	FEA_MAP(CORE_DLDO),
161f46a221bSXiaojian Du 	FEA_MAP(RSMU_LOW_POWER),
162f46a221bSXiaojian Du 	FEA_MAP(SMN_LOW_POWER),
163f46a221bSXiaojian Du 	FEA_MAP(THM_LOW_POWER),
164f46a221bSXiaojian Du 	FEA_MAP(SMUIO_LOW_POWER),
165f46a221bSXiaojian Du 	FEA_MAP(MP1_LOW_POWER),
166f46a221bSXiaojian Du 	FEA_MAP(DS_VCN),
167f46a221bSXiaojian Du 	FEA_MAP(CPPC),
168f46a221bSXiaojian Du 	FEA_MAP(OS_CSTATES),
169f46a221bSXiaojian Du 	FEA_MAP(ISP_DPM),
170f46a221bSXiaojian Du 	FEA_MAP(A55_DPM),
171f46a221bSXiaojian Du 	FEA_MAP(CVIP_DSP_DPM),
172f46a221bSXiaojian Du 	FEA_MAP(MSMU_LOW_POWER),
17354800b58SXiaojian Du 	FEA_MAP_REVERSE(SOCCLK),
17454800b58SXiaojian Du 	FEA_MAP_REVERSE(FCLK),
17554800b58SXiaojian Du 	FEA_MAP_HALF_REVERSE(GFX),
176f46a221bSXiaojian Du };
177f46a221bSXiaojian Du 
178f46a221bSXiaojian Du static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = {
179f46a221bSXiaojian Du 	TAB_MAP_VALID(WATERMARKS),
180f46a221bSXiaojian Du 	TAB_MAP_VALID(SMU_METRICS),
181f46a221bSXiaojian Du 	TAB_MAP_VALID(CUSTOM_DPM),
182f46a221bSXiaojian Du 	TAB_MAP_VALID(DPMCLOCKS),
183f46a221bSXiaojian Du };
184f46a221bSXiaojian Du 
185f727ebebSXiaojian Du static struct cmn2asic_mapping vangogh_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
186f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
187f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
188f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
189f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
190f727ebebSXiaojian Du 	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
191f727ebebSXiaojian Du };
192f727ebebSXiaojian Du 
193f46a221bSXiaojian Du static int vangogh_tables_init(struct smu_context *smu)
194f46a221bSXiaojian Du {
195f46a221bSXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
196f46a221bSXiaojian Du 	struct smu_table *tables = smu_table->tables;
197f46a221bSXiaojian Du 
198f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
199f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
200f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
201f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
202f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
203f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
204f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
205f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
206f46a221bSXiaojian Du 	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
207f46a221bSXiaojian Du 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
208f46a221bSXiaojian Du 	smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
209f46a221bSXiaojian Du 	if (!smu_table->metrics_table)
210f46a221bSXiaojian Du 		goto err0_out;
211f46a221bSXiaojian Du 	smu_table->metrics_time = 0;
212f46a221bSXiaojian Du 
213f46a221bSXiaojian Du 	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0);
214f46a221bSXiaojian Du 	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
215f46a221bSXiaojian Du 	if (!smu_table->gpu_metrics_table)
216f46a221bSXiaojian Du 		goto err1_out;
217f46a221bSXiaojian Du 
218f46a221bSXiaojian Du 	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
219f46a221bSXiaojian Du 	if (!smu_table->watermarks_table)
220f46a221bSXiaojian Du 		goto err2_out;
221f46a221bSXiaojian Du 
222c98ee897SXiaojian Du 	smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
223c98ee897SXiaojian Du 	if (!smu_table->clocks_table)
224c98ee897SXiaojian Du 		goto err3_out;
225c98ee897SXiaojian Du 
226f46a221bSXiaojian Du 	return 0;
227f46a221bSXiaojian Du 
228c98ee897SXiaojian Du err3_out:
229c98ee897SXiaojian Du 	kfree(smu_table->clocks_table);
230f46a221bSXiaojian Du err2_out:
231f46a221bSXiaojian Du 	kfree(smu_table->gpu_metrics_table);
232f46a221bSXiaojian Du err1_out:
233f46a221bSXiaojian Du 	kfree(smu_table->metrics_table);
234f46a221bSXiaojian Du err0_out:
235f46a221bSXiaojian Du 	return -ENOMEM;
236f46a221bSXiaojian Du }
237f46a221bSXiaojian Du 
238271ab489SXiaojian Du static int vangogh_get_smu_metrics_data(struct smu_context *smu,
239271ab489SXiaojian Du 				       MetricsMember_t member,
240271ab489SXiaojian Du 				       uint32_t *value)
241271ab489SXiaojian Du {
242271ab489SXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
243271ab489SXiaojian Du 
244271ab489SXiaojian Du 	SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
245271ab489SXiaojian Du 	int ret = 0;
246271ab489SXiaojian Du 
247271ab489SXiaojian Du 	mutex_lock(&smu->metrics_lock);
248271ab489SXiaojian Du 
249271ab489SXiaojian Du 	ret = smu_cmn_get_metrics_table_locked(smu,
250271ab489SXiaojian Du 					       NULL,
251271ab489SXiaojian Du 					       false);
252271ab489SXiaojian Du 	if (ret) {
253271ab489SXiaojian Du 		mutex_unlock(&smu->metrics_lock);
254271ab489SXiaojian Du 		return ret;
255271ab489SXiaojian Du 	}
256271ab489SXiaojian Du 
257271ab489SXiaojian Du 	switch (member) {
258271ab489SXiaojian Du 	case METRICS_AVERAGE_GFXCLK:
259271ab489SXiaojian Du 		*value = metrics->GfxclkFrequency;
260271ab489SXiaojian Du 		break;
261271ab489SXiaojian Du 	case METRICS_AVERAGE_SOCCLK:
262271ab489SXiaojian Du 		*value = metrics->SocclkFrequency;
263271ab489SXiaojian Du 		break;
264f02c7336SXiaojian Du 	case METRICS_AVERAGE_VCLK:
265f02c7336SXiaojian Du 		*value = metrics->VclkFrequency;
266f02c7336SXiaojian Du 		break;
267f02c7336SXiaojian Du 	case METRICS_AVERAGE_DCLK:
268f02c7336SXiaojian Du 		*value = metrics->DclkFrequency;
269f02c7336SXiaojian Du 		break;
270271ab489SXiaojian Du 	case METRICS_AVERAGE_UCLK:
271271ab489SXiaojian Du 		*value = metrics->MemclkFrequency;
272271ab489SXiaojian Du 		break;
273271ab489SXiaojian Du 	case METRICS_AVERAGE_GFXACTIVITY:
274271ab489SXiaojian Du 		*value = metrics->GfxActivity / 100;
275271ab489SXiaojian Du 		break;
276271ab489SXiaojian Du 	case METRICS_AVERAGE_VCNACTIVITY:
277271ab489SXiaojian Du 		*value = metrics->UvdActivity;
278271ab489SXiaojian Du 		break;
279271ab489SXiaojian Du 	case METRICS_AVERAGE_SOCKETPOWER:
28023289a22SXiaojian Du 		*value = (metrics->CurrentSocketPower << 8) /
28123289a22SXiaojian Du 		1000 ;
282271ab489SXiaojian Du 		break;
283271ab489SXiaojian Du 	case METRICS_TEMPERATURE_EDGE:
284271ab489SXiaojian Du 		*value = metrics->GfxTemperature / 100 *
285271ab489SXiaojian Du 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
286271ab489SXiaojian Du 		break;
287271ab489SXiaojian Du 	case METRICS_TEMPERATURE_HOTSPOT:
288271ab489SXiaojian Du 		*value = metrics->SocTemperature / 100 *
289271ab489SXiaojian Du 		SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
290271ab489SXiaojian Du 		break;
291271ab489SXiaojian Du 	case METRICS_THROTTLER_STATUS:
292271ab489SXiaojian Du 		*value = metrics->ThrottlerStatus;
293271ab489SXiaojian Du 		break;
2942139d12bSAlex Deucher 	case METRICS_VOLTAGE_VDDGFX:
2952139d12bSAlex Deucher 		*value = metrics->Voltage[2];
2962139d12bSAlex Deucher 		break;
2972139d12bSAlex Deucher 	case METRICS_VOLTAGE_VDDSOC:
2982139d12bSAlex Deucher 		*value = metrics->Voltage[1];
2992139d12bSAlex Deucher 		break;
300517cb957SHuang Rui 	case METRICS_AVERAGE_CPUCLK:
301517cb957SHuang Rui 		memcpy(value, &metrics->CoreFrequency[0],
3024aef0ebcSHuang Rui 		       smu->cpu_core_num * sizeof(uint16_t));
303517cb957SHuang Rui 		break;
304271ab489SXiaojian Du 	default:
305271ab489SXiaojian Du 		*value = UINT_MAX;
306271ab489SXiaojian Du 		break;
307271ab489SXiaojian Du 	}
308271ab489SXiaojian Du 
309271ab489SXiaojian Du 	mutex_unlock(&smu->metrics_lock);
310271ab489SXiaojian Du 
311271ab489SXiaojian Du 	return ret;
312271ab489SXiaojian Du }
313271ab489SXiaojian Du 
314f46a221bSXiaojian Du static int vangogh_allocate_dpm_context(struct smu_context *smu)
315f46a221bSXiaojian Du {
316f46a221bSXiaojian Du 	struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
317f46a221bSXiaojian Du 
318f46a221bSXiaojian Du 	smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
319f46a221bSXiaojian Du 				       GFP_KERNEL);
320f46a221bSXiaojian Du 	if (!smu_dpm->dpm_context)
321f46a221bSXiaojian Du 		return -ENOMEM;
322f46a221bSXiaojian Du 
323f46a221bSXiaojian Du 	smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
324f46a221bSXiaojian Du 
325f46a221bSXiaojian Du 	return 0;
326f46a221bSXiaojian Du }
327f46a221bSXiaojian Du 
328f46a221bSXiaojian Du static int vangogh_init_smc_tables(struct smu_context *smu)
329f46a221bSXiaojian Du {
330f46a221bSXiaojian Du 	int ret = 0;
331f46a221bSXiaojian Du 
332f46a221bSXiaojian Du 	ret = vangogh_tables_init(smu);
333f46a221bSXiaojian Du 	if (ret)
334f46a221bSXiaojian Du 		return ret;
335f46a221bSXiaojian Du 
336f46a221bSXiaojian Du 	ret = vangogh_allocate_dpm_context(smu);
337f46a221bSXiaojian Du 	if (ret)
338f46a221bSXiaojian Du 		return ret;
339f46a221bSXiaojian Du 
3404aef0ebcSHuang Rui #ifdef CONFIG_X86
3414aef0ebcSHuang Rui 	/* AMD x86 APU only */
3424aef0ebcSHuang Rui 	smu->cpu_core_num = boot_cpu_data.x86_max_cores;
3434aef0ebcSHuang Rui #else
3444aef0ebcSHuang Rui 	smu->cpu_core_num = 4;
3454aef0ebcSHuang Rui #endif
3464aef0ebcSHuang Rui 
347f46a221bSXiaojian Du 	return smu_v11_0_init_smc_tables(smu);
348f46a221bSXiaojian Du }
349f46a221bSXiaojian Du 
350f46a221bSXiaojian Du static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
351f46a221bSXiaojian Du {
352f46a221bSXiaojian Du 	int ret = 0;
353f46a221bSXiaojian Du 
354f46a221bSXiaojian Du 	if (enable) {
355f46a221bSXiaojian Du 		/* vcn dpm on is a prerequisite for vcn power gate messages */
356f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL);
357f46a221bSXiaojian Du 		if (ret)
358f46a221bSXiaojian Du 			return ret;
359f46a221bSXiaojian Du 	} else {
360f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL);
361f46a221bSXiaojian Du 		if (ret)
362f46a221bSXiaojian Du 			return ret;
363f46a221bSXiaojian Du 	}
364f46a221bSXiaojian Du 
365f46a221bSXiaojian Du 	return ret;
366f46a221bSXiaojian Du }
367f46a221bSXiaojian Du 
368f46a221bSXiaojian Du static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
369f46a221bSXiaojian Du {
370f46a221bSXiaojian Du 	int ret = 0;
371f46a221bSXiaojian Du 
372f46a221bSXiaojian Du 	if (enable) {
373f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL);
374f46a221bSXiaojian Du 		if (ret)
375f46a221bSXiaojian Du 			return ret;
376f46a221bSXiaojian Du 	} else {
377f46a221bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL);
378f46a221bSXiaojian Du 		if (ret)
379f46a221bSXiaojian Du 			return ret;
380f46a221bSXiaojian Du 	}
381f46a221bSXiaojian Du 
382f46a221bSXiaojian Du 	return ret;
383f46a221bSXiaojian Du }
384f46a221bSXiaojian Du 
385f46a221bSXiaojian Du static bool vangogh_is_dpm_running(struct smu_context *smu)
386f46a221bSXiaojian Du {
387271ab489SXiaojian Du 	int ret = 0;
388271ab489SXiaojian Du 	uint32_t feature_mask[2];
389271ab489SXiaojian Du 	uint64_t feature_enabled;
390f46a221bSXiaojian Du 
391271ab489SXiaojian Du 	ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2);
392271ab489SXiaojian Du 
393271ab489SXiaojian Du 	if (ret)
394f46a221bSXiaojian Du 		return false;
395f46a221bSXiaojian Du 
396271ab489SXiaojian Du 	feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
397271ab489SXiaojian Du 				((uint64_t)feature_mask[1] << 32));
398271ab489SXiaojian Du 
399271ab489SXiaojian Du 	return !!(feature_enabled & SMC_DPM_FEATURE);
400271ab489SXiaojian Du }
401271ab489SXiaojian Du 
402ae7b32e7SXiaojian Du static int vangogh_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type,
403ae7b32e7SXiaojian Du 						uint32_t dpm_level, uint32_t *freq)
404ae7b32e7SXiaojian Du {
405ae7b32e7SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
406ae7b32e7SXiaojian Du 
407ae7b32e7SXiaojian Du 	if (!clk_table || clk_type >= SMU_CLK_COUNT)
408ae7b32e7SXiaojian Du 		return -EINVAL;
409ae7b32e7SXiaojian Du 
410ae7b32e7SXiaojian Du 	switch (clk_type) {
411ae7b32e7SXiaojian Du 	case SMU_SOCCLK:
412ae7b32e7SXiaojian Du 		if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
413ae7b32e7SXiaojian Du 			return -EINVAL;
414ae7b32e7SXiaojian Du 		*freq = clk_table->SocClocks[dpm_level];
415ae7b32e7SXiaojian Du 		break;
416f02c7336SXiaojian Du 	case SMU_VCLK:
417f02c7336SXiaojian Du 		if (dpm_level >= clk_table->VcnClkLevelsEnabled)
418f02c7336SXiaojian Du 			return -EINVAL;
419f02c7336SXiaojian Du 		*freq = clk_table->VcnClocks[dpm_level].vclk;
420f02c7336SXiaojian Du 		break;
421f02c7336SXiaojian Du 	case SMU_DCLK:
422f02c7336SXiaojian Du 		if (dpm_level >= clk_table->VcnClkLevelsEnabled)
423f02c7336SXiaojian Du 			return -EINVAL;
424f02c7336SXiaojian Du 		*freq = clk_table->VcnClocks[dpm_level].dclk;
425f02c7336SXiaojian Du 		break;
426ae7b32e7SXiaojian Du 	case SMU_UCLK:
427ae7b32e7SXiaojian Du 	case SMU_MCLK:
428ae7b32e7SXiaojian Du 		if (dpm_level >= clk_table->NumDfPstatesEnabled)
429ae7b32e7SXiaojian Du 			return -EINVAL;
430ae7b32e7SXiaojian Du 		*freq = clk_table->DfPstateTable[dpm_level].memclk;
431ae7b32e7SXiaojian Du 
432ae7b32e7SXiaojian Du 		break;
433ae7b32e7SXiaojian Du 	case SMU_FCLK:
434ae7b32e7SXiaojian Du 		if (dpm_level >= clk_table->NumDfPstatesEnabled)
435ae7b32e7SXiaojian Du 			return -EINVAL;
436ae7b32e7SXiaojian Du 		*freq = clk_table->DfPstateTable[dpm_level].fclk;
437ae7b32e7SXiaojian Du 		break;
438ae7b32e7SXiaojian Du 	default:
439ae7b32e7SXiaojian Du 		return -EINVAL;
440ae7b32e7SXiaojian Du 	}
441ae7b32e7SXiaojian Du 
442ae7b32e7SXiaojian Du 	return 0;
443ae7b32e7SXiaojian Du }
444ae7b32e7SXiaojian Du 
445c98ee897SXiaojian Du static int vangogh_print_fine_grain_clk(struct smu_context *smu,
446c98ee897SXiaojian Du 			enum smu_clk_type clk_type, char *buf)
447c98ee897SXiaojian Du {
448ae7b32e7SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
449ae7b32e7SXiaojian Du 	SmuMetrics_t metrics;
450d7379efaSXiaojian Du 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
451ae7b32e7SXiaojian Du 	int i, size = 0, ret = 0;
452ae7b32e7SXiaojian Du 	uint32_t cur_value = 0, value = 0, count = 0;
453ae7b32e7SXiaojian Du 	bool cur_value_match_level = false;
454ae7b32e7SXiaojian Du 
455ae7b32e7SXiaojian Du 	memset(&metrics, 0, sizeof(metrics));
456ae7b32e7SXiaojian Du 
457ae7b32e7SXiaojian Du 	ret = smu_cmn_get_metrics_table(smu, &metrics, false);
458ae7b32e7SXiaojian Du 	if (ret)
459ae7b32e7SXiaojian Du 		return ret;
460c98ee897SXiaojian Du 
461c98ee897SXiaojian Du 	switch (clk_type) {
462c98ee897SXiaojian Du 	case SMU_OD_SCLK:
463d7379efaSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
464c98ee897SXiaojian Du 			size = sprintf(buf, "%s:\n", "OD_SCLK");
465c98ee897SXiaojian Du 			size += sprintf(buf + size, "0: %10uMhz\n",
466c98ee897SXiaojian Du 			(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
467c98ee897SXiaojian Du 			size += sprintf(buf + size, "1: %10uMhz\n",
468c98ee897SXiaojian Du 			(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
469c98ee897SXiaojian Du 		}
470c98ee897SXiaojian Du 		break;
4710d90d0ddSHuang Rui 	case SMU_OD_CCLK:
472d7379efaSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
4730d90d0ddSHuang Rui 			size = sprintf(buf, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);
4740d90d0ddSHuang Rui 			size += sprintf(buf + size, "0: %10uMhz\n",
4750d90d0ddSHuang Rui 			(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);
4760d90d0ddSHuang Rui 			size += sprintf(buf + size, "1: %10uMhz\n",
4770d90d0ddSHuang Rui 			(smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq);
4780d90d0ddSHuang Rui 		}
4790d90d0ddSHuang Rui 		break;
480c98ee897SXiaojian Du 	case SMU_OD_RANGE:
481d7379efaSXiaojian Du 		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
482c98ee897SXiaojian Du 			size = sprintf(buf, "%s:\n", "OD_RANGE");
483c98ee897SXiaojian Du 			size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
484c98ee897SXiaojian Du 				smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
4850d90d0ddSHuang Rui 			size += sprintf(buf + size, "CCLK: %7uMhz %10uMhz\n",
4860d90d0ddSHuang Rui 				smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq);
487c98ee897SXiaojian Du 		}
488c98ee897SXiaojian Du 		break;
489ae7b32e7SXiaojian Du 	case SMU_SOCCLK:
490ae7b32e7SXiaojian Du 		/* the level 3 ~ 6 of socclk use the same frequency for vangogh */
491ae7b32e7SXiaojian Du 		count = clk_table->NumSocClkLevelsEnabled;
492ae7b32e7SXiaojian Du 		cur_value = metrics.SocclkFrequency;
493ae7b32e7SXiaojian Du 		break;
494f02c7336SXiaojian Du 	case SMU_VCLK:
495f02c7336SXiaojian Du 		count = clk_table->VcnClkLevelsEnabled;
496f02c7336SXiaojian Du 		cur_value = metrics.VclkFrequency;
497f02c7336SXiaojian Du 		break;
498f02c7336SXiaojian Du 	case SMU_DCLK:
499f02c7336SXiaojian Du 		count = clk_table->VcnClkLevelsEnabled;
500f02c7336SXiaojian Du 		cur_value = metrics.DclkFrequency;
501f02c7336SXiaojian Du 		break;
502ae7b32e7SXiaojian Du 	case SMU_MCLK:
503ae7b32e7SXiaojian Du 		count = clk_table->NumDfPstatesEnabled;
504ae7b32e7SXiaojian Du 		cur_value = metrics.MemclkFrequency;
505ae7b32e7SXiaojian Du 		break;
506ae7b32e7SXiaojian Du 	case SMU_FCLK:
507ae7b32e7SXiaojian Du 		count = clk_table->NumDfPstatesEnabled;
508ae7b32e7SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetFclkFrequency, 0, &cur_value);
509ae7b32e7SXiaojian Du 		if (ret)
510ae7b32e7SXiaojian Du 			return ret;
511ae7b32e7SXiaojian Du 		break;
512ae7b32e7SXiaojian Du 	default:
513ae7b32e7SXiaojian Du 		break;
514ae7b32e7SXiaojian Du 	}
515ae7b32e7SXiaojian Du 
516ae7b32e7SXiaojian Du 	switch (clk_type) {
517ae7b32e7SXiaojian Du 	case SMU_SOCCLK:
518f02c7336SXiaojian Du 	case SMU_VCLK:
519f02c7336SXiaojian Du 	case SMU_DCLK:
520ae7b32e7SXiaojian Du 	case SMU_MCLK:
521ae7b32e7SXiaojian Du 	case SMU_FCLK:
522ae7b32e7SXiaojian Du 		for (i = 0; i < count; i++) {
523ae7b32e7SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value);
524ae7b32e7SXiaojian Du 			if (ret)
525ae7b32e7SXiaojian Du 				return ret;
526ae7b32e7SXiaojian Du 			if (!value)
527ae7b32e7SXiaojian Du 				continue;
528ae7b32e7SXiaojian Du 			size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
529ae7b32e7SXiaojian Du 					cur_value == value ? "*" : "");
530ae7b32e7SXiaojian Du 			if (cur_value == value)
531ae7b32e7SXiaojian Du 				cur_value_match_level = true;
532ae7b32e7SXiaojian Du 		}
533ae7b32e7SXiaojian Du 
534ae7b32e7SXiaojian Du 		if (!cur_value_match_level)
535ae7b32e7SXiaojian Du 			size += sprintf(buf + size, "   %uMhz *\n", cur_value);
536ae7b32e7SXiaojian Du 		break;
537c98ee897SXiaojian Du 	default:
538c98ee897SXiaojian Du 		break;
539c98ee897SXiaojian Du 	}
540c98ee897SXiaojian Du 
541c98ee897SXiaojian Du 	return size;
542c98ee897SXiaojian Du }
543c98ee897SXiaojian Du 
544d0e4e112SXiaojian Du static int vangogh_get_profiling_clk_mask(struct smu_context *smu,
545d0e4e112SXiaojian Du 					 enum amd_dpm_forced_level level,
546d0e4e112SXiaojian Du 					 uint32_t *vclk_mask,
547d0e4e112SXiaojian Du 					 uint32_t *dclk_mask,
548d0e4e112SXiaojian Du 					 uint32_t *mclk_mask,
549d0e4e112SXiaojian Du 					 uint32_t *fclk_mask,
550d0e4e112SXiaojian Du 					 uint32_t *soc_mask)
551d0e4e112SXiaojian Du {
552d0e4e112SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
553d0e4e112SXiaojian Du 
554307f049bSXiaojian Du 	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
555d0e4e112SXiaojian Du 		if (mclk_mask)
556d0e4e112SXiaojian Du 			*mclk_mask = clk_table->NumDfPstatesEnabled - 1;
557307f049bSXiaojian Du 
558d0e4e112SXiaojian Du 		if (fclk_mask)
559d0e4e112SXiaojian Du 			*fclk_mask = clk_table->NumDfPstatesEnabled - 1;
560307f049bSXiaojian Du 
561307f049bSXiaojian Du 		if (soc_mask)
562307f049bSXiaojian Du 			*soc_mask = 0;
563d0e4e112SXiaojian Du 	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
564d0e4e112SXiaojian Du 		if (mclk_mask)
565d0e4e112SXiaojian Du 			*mclk_mask = 0;
566307f049bSXiaojian Du 
567d0e4e112SXiaojian Du 		if (fclk_mask)
568d0e4e112SXiaojian Du 			*fclk_mask = 0;
569d0e4e112SXiaojian Du 
570d0e4e112SXiaojian Du 		if (soc_mask)
571307f049bSXiaojian Du 			*soc_mask = 1;
572307f049bSXiaojian Du 
573307f049bSXiaojian Du 		if (vclk_mask)
574307f049bSXiaojian Du 			*vclk_mask = 1;
575307f049bSXiaojian Du 
576307f049bSXiaojian Du 		if (dclk_mask)
577307f049bSXiaojian Du 			*dclk_mask = 1;
578307f049bSXiaojian Du 	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) {
579307f049bSXiaojian Du 		if (mclk_mask)
580307f049bSXiaojian Du 			*mclk_mask = 0;
581307f049bSXiaojian Du 
582307f049bSXiaojian Du 		if (fclk_mask)
583307f049bSXiaojian Du 			*fclk_mask = 0;
584307f049bSXiaojian Du 
585307f049bSXiaojian Du 		if (soc_mask)
586307f049bSXiaojian Du 			*soc_mask = 1;
587307f049bSXiaojian Du 
588307f049bSXiaojian Du 		if (vclk_mask)
589307f049bSXiaojian Du 			*vclk_mask = 1;
590307f049bSXiaojian Du 
591307f049bSXiaojian Du 		if (dclk_mask)
592307f049bSXiaojian Du 			*dclk_mask = 1;
593d0e4e112SXiaojian Du 	}
594d0e4e112SXiaojian Du 
595d0e4e112SXiaojian Du 	return 0;
596d0e4e112SXiaojian Du }
597d0e4e112SXiaojian Du 
5988f8150faSSouptick Joarder static bool vangogh_clk_dpm_is_enabled(struct smu_context *smu,
599d0e4e112SXiaojian Du 				enum smu_clk_type clk_type)
600d0e4e112SXiaojian Du {
601d0e4e112SXiaojian Du 	enum smu_feature_mask feature_id = 0;
602d0e4e112SXiaojian Du 
603d0e4e112SXiaojian Du 	switch (clk_type) {
604d0e4e112SXiaojian Du 	case SMU_MCLK:
605d0e4e112SXiaojian Du 	case SMU_UCLK:
606d0e4e112SXiaojian Du 	case SMU_FCLK:
607d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_DPM_FCLK_BIT;
608d0e4e112SXiaojian Du 		break;
609d0e4e112SXiaojian Du 	case SMU_GFXCLK:
610d0e4e112SXiaojian Du 	case SMU_SCLK:
611d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
612d0e4e112SXiaojian Du 		break;
613d0e4e112SXiaojian Du 	case SMU_SOCCLK:
614d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
615d0e4e112SXiaojian Du 		break;
616d0e4e112SXiaojian Du 	case SMU_VCLK:
617d0e4e112SXiaojian Du 	case SMU_DCLK:
618d0e4e112SXiaojian Du 		feature_id = SMU_FEATURE_VCN_DPM_BIT;
619d0e4e112SXiaojian Du 		break;
620d0e4e112SXiaojian Du 	default:
621d0e4e112SXiaojian Du 		return true;
622d0e4e112SXiaojian Du 	}
623d0e4e112SXiaojian Du 
624d0e4e112SXiaojian Du 	if (!smu_cmn_feature_is_enabled(smu, feature_id))
625d0e4e112SXiaojian Du 		return false;
626d0e4e112SXiaojian Du 
627d0e4e112SXiaojian Du 	return true;
628d0e4e112SXiaojian Du }
629d0e4e112SXiaojian Du 
630d0e4e112SXiaojian Du static int vangogh_get_dpm_ultimate_freq(struct smu_context *smu,
631d0e4e112SXiaojian Du 					enum smu_clk_type clk_type,
632d0e4e112SXiaojian Du 					uint32_t *min,
633d0e4e112SXiaojian Du 					uint32_t *max)
634d0e4e112SXiaojian Du {
635d0e4e112SXiaojian Du 	int ret = 0;
636d0e4e112SXiaojian Du 	uint32_t soc_mask;
637d0e4e112SXiaojian Du 	uint32_t vclk_mask;
638d0e4e112SXiaojian Du 	uint32_t dclk_mask;
639d0e4e112SXiaojian Du 	uint32_t mclk_mask;
640d0e4e112SXiaojian Du 	uint32_t fclk_mask;
641d0e4e112SXiaojian Du 	uint32_t clock_limit;
642d0e4e112SXiaojian Du 
643d0e4e112SXiaojian Du 	if (!vangogh_clk_dpm_is_enabled(smu, clk_type)) {
644d0e4e112SXiaojian Du 		switch (clk_type) {
645d0e4e112SXiaojian Du 		case SMU_MCLK:
646d0e4e112SXiaojian Du 		case SMU_UCLK:
647d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.uclk;
648d0e4e112SXiaojian Du 			break;
649d0e4e112SXiaojian Du 		case SMU_FCLK:
650d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.fclk;
651d0e4e112SXiaojian Du 			break;
652d0e4e112SXiaojian Du 		case SMU_GFXCLK:
653d0e4e112SXiaojian Du 		case SMU_SCLK:
654d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.gfxclk;
655d0e4e112SXiaojian Du 			break;
656d0e4e112SXiaojian Du 		case SMU_SOCCLK:
657d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.socclk;
658d0e4e112SXiaojian Du 			break;
659d0e4e112SXiaojian Du 		case SMU_VCLK:
660d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.vclk;
661d0e4e112SXiaojian Du 			break;
662d0e4e112SXiaojian Du 		case SMU_DCLK:
663d0e4e112SXiaojian Du 			clock_limit = smu->smu_table.boot_values.dclk;
664d0e4e112SXiaojian Du 			break;
665d0e4e112SXiaojian Du 		default:
666d0e4e112SXiaojian Du 			clock_limit = 0;
667d0e4e112SXiaojian Du 			break;
668d0e4e112SXiaojian Du 		}
669d0e4e112SXiaojian Du 
670d0e4e112SXiaojian Du 		/* clock in Mhz unit */
671d0e4e112SXiaojian Du 		if (min)
672d0e4e112SXiaojian Du 			*min = clock_limit / 100;
673d0e4e112SXiaojian Du 		if (max)
674d0e4e112SXiaojian Du 			*max = clock_limit / 100;
675d0e4e112SXiaojian Du 
676d0e4e112SXiaojian Du 		return 0;
677d0e4e112SXiaojian Du 	}
678d0e4e112SXiaojian Du 	if (max) {
679d0e4e112SXiaojian Du 		ret = vangogh_get_profiling_clk_mask(smu,
680d0e4e112SXiaojian Du 							AMD_DPM_FORCED_LEVEL_PROFILE_PEAK,
681d0e4e112SXiaojian Du 							&vclk_mask,
682d0e4e112SXiaojian Du 							&dclk_mask,
683d0e4e112SXiaojian Du 							&mclk_mask,
684d0e4e112SXiaojian Du 							&fclk_mask,
685d0e4e112SXiaojian Du 							&soc_mask);
686d0e4e112SXiaojian Du 		if (ret)
687d0e4e112SXiaojian Du 			goto failed;
688d0e4e112SXiaojian Du 
689d0e4e112SXiaojian Du 		switch (clk_type) {
690d0e4e112SXiaojian Du 		case SMU_UCLK:
691d0e4e112SXiaojian Du 		case SMU_MCLK:
692d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, max);
693d0e4e112SXiaojian Du 			if (ret)
694d0e4e112SXiaojian Du 				goto failed;
695d0e4e112SXiaojian Du 			break;
696d0e4e112SXiaojian Du 		case SMU_SOCCLK:
697d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, max);
698d0e4e112SXiaojian Du 			if (ret)
699d0e4e112SXiaojian Du 				goto failed;
700d0e4e112SXiaojian Du 			break;
701d0e4e112SXiaojian Du 		case SMU_FCLK:
702d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, max);
703d0e4e112SXiaojian Du 			if (ret)
704d0e4e112SXiaojian Du 				goto failed;
705d0e4e112SXiaojian Du 			break;
706d0e4e112SXiaojian Du 		case SMU_VCLK:
707d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, max);
708d0e4e112SXiaojian Du 			if (ret)
709d0e4e112SXiaojian Du 				goto failed;
710d0e4e112SXiaojian Du 			break;
711d0e4e112SXiaojian Du 		case SMU_DCLK:
712d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, max);
713d0e4e112SXiaojian Du 			if (ret)
714d0e4e112SXiaojian Du 				goto failed;
715d0e4e112SXiaojian Du 			break;
716d0e4e112SXiaojian Du 		default:
717d0e4e112SXiaojian Du 			ret = -EINVAL;
718d0e4e112SXiaojian Du 			goto failed;
719d0e4e112SXiaojian Du 		}
720d0e4e112SXiaojian Du 	}
721d0e4e112SXiaojian Du 	if (min) {
722d0e4e112SXiaojian Du 		switch (clk_type) {
723d0e4e112SXiaojian Du 		case SMU_UCLK:
724d0e4e112SXiaojian Du 		case SMU_MCLK:
725d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, mclk_mask, min);
726d0e4e112SXiaojian Du 			if (ret)
727d0e4e112SXiaojian Du 				goto failed;
728d0e4e112SXiaojian Du 			break;
729d0e4e112SXiaojian Du 		case SMU_SOCCLK:
730d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, soc_mask, min);
731d0e4e112SXiaojian Du 			if (ret)
732d0e4e112SXiaojian Du 				goto failed;
733d0e4e112SXiaojian Du 			break;
734d0e4e112SXiaojian Du 		case SMU_FCLK:
735d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, fclk_mask, min);
736d0e4e112SXiaojian Du 			if (ret)
737d0e4e112SXiaojian Du 				goto failed;
738d0e4e112SXiaojian Du 			break;
739d0e4e112SXiaojian Du 		case SMU_VCLK:
740d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, vclk_mask, min);
741d0e4e112SXiaojian Du 			if (ret)
742d0e4e112SXiaojian Du 				goto failed;
743d0e4e112SXiaojian Du 			break;
744d0e4e112SXiaojian Du 		case SMU_DCLK:
745d0e4e112SXiaojian Du 			ret = vangogh_get_dpm_clk_limited(smu, clk_type, dclk_mask, min);
746d0e4e112SXiaojian Du 			if (ret)
747d0e4e112SXiaojian Du 				goto failed;
748d0e4e112SXiaojian Du 			break;
749d0e4e112SXiaojian Du 		default:
750d0e4e112SXiaojian Du 			ret = -EINVAL;
751d0e4e112SXiaojian Du 			goto failed;
752d0e4e112SXiaojian Du 		}
753d0e4e112SXiaojian Du 	}
754d0e4e112SXiaojian Du failed:
755d0e4e112SXiaojian Du 	return ret;
756d0e4e112SXiaojian Du }
757d0e4e112SXiaojian Du 
758307f049bSXiaojian Du static int vangogh_get_power_profile_mode(struct smu_context *smu,
759307f049bSXiaojian Du 					   char *buf)
760307f049bSXiaojian Du {
761307f049bSXiaojian Du 	static const char *profile_name[] = {
7622a38ca99SColin Ian King 					"BOOTUP_DEFAULT",
763f727ebebSXiaojian Du 					"3D_FULL_SCREEN",
764f727ebebSXiaojian Du 					"POWER_SAVING",
765307f049bSXiaojian Du 					"VIDEO",
766307f049bSXiaojian Du 					"VR",
767307f049bSXiaojian Du 					"COMPUTE",
768307f049bSXiaojian Du 					"CUSTOM"};
769307f049bSXiaojian Du 	uint32_t i, size = 0;
770307f049bSXiaojian Du 	int16_t workload_type = 0;
771307f049bSXiaojian Du 
772307f049bSXiaojian Du 	if (!buf)
773307f049bSXiaojian Du 		return -EINVAL;
774307f049bSXiaojian Du 
775307f049bSXiaojian Du 	for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
776307f049bSXiaojian Du 		/*
777307f049bSXiaojian Du 		 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
778307f049bSXiaojian Du 		 * Not all profile modes are supported on vangogh.
779307f049bSXiaojian Du 		 */
780307f049bSXiaojian Du 		workload_type = smu_cmn_to_asic_specific_index(smu,
781307f049bSXiaojian Du 							       CMN2ASIC_MAPPING_WORKLOAD,
782307f049bSXiaojian Du 							       i);
783307f049bSXiaojian Du 
784307f049bSXiaojian Du 		if (workload_type < 0)
785307f049bSXiaojian Du 			continue;
786307f049bSXiaojian Du 
787307f049bSXiaojian Du 		size += sprintf(buf + size, "%2d %14s%s\n",
788307f049bSXiaojian Du 			i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
789307f049bSXiaojian Du 	}
790307f049bSXiaojian Du 
791307f049bSXiaojian Du 	return size;
792307f049bSXiaojian Du }
793307f049bSXiaojian Du 
794d0e4e112SXiaojian Du static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
795d0e4e112SXiaojian Du {
796d0e4e112SXiaojian Du 	int workload_type, ret;
797d0e4e112SXiaojian Du 	uint32_t profile_mode = input[size];
798d0e4e112SXiaojian Du 
799d0e4e112SXiaojian Du 	if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
800d0e4e112SXiaojian Du 		dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
801d0e4e112SXiaojian Du 		return -EINVAL;
802d0e4e112SXiaojian Du 	}
803d0e4e112SXiaojian Du 
804f727ebebSXiaojian Du 	if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
805f727ebebSXiaojian Du 			profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
806f727ebebSXiaojian Du 		return 0;
807f727ebebSXiaojian Du 
808d0e4e112SXiaojian Du 	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
809d0e4e112SXiaojian Du 	workload_type = smu_cmn_to_asic_specific_index(smu,
810d0e4e112SXiaojian Du 						       CMN2ASIC_MAPPING_WORKLOAD,
811d0e4e112SXiaojian Du 						       profile_mode);
812d0e4e112SXiaojian Du 	if (workload_type < 0) {
813d0e4e112SXiaojian Du 		dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n",
814d0e4e112SXiaojian Du 					profile_mode);
815d0e4e112SXiaojian Du 		return -EINVAL;
816d0e4e112SXiaojian Du 	}
817d0e4e112SXiaojian Du 
818d0e4e112SXiaojian Du 	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
819d0e4e112SXiaojian Du 				    1 << workload_type,
820d0e4e112SXiaojian Du 				    NULL);
821d0e4e112SXiaojian Du 	if (ret) {
822d0e4e112SXiaojian Du 		dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
823d0e4e112SXiaojian Du 					workload_type);
824d0e4e112SXiaojian Du 		return ret;
825d0e4e112SXiaojian Du 	}
826d0e4e112SXiaojian Du 
827d0e4e112SXiaojian Du 	smu->power_profile_mode = profile_mode;
828d0e4e112SXiaojian Du 
829d0e4e112SXiaojian Du 	return 0;
830d0e4e112SXiaojian Du }
831d0e4e112SXiaojian Du 
832dd9e0b21SXiaojian Du static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,
833dd9e0b21SXiaojian Du 					  enum smu_clk_type clk_type,
834dd9e0b21SXiaojian Du 					  uint32_t min,
835dd9e0b21SXiaojian Du 					  uint32_t max)
836dd9e0b21SXiaojian Du {
837dd9e0b21SXiaojian Du 	int ret = 0;
838dd9e0b21SXiaojian Du 
839dd9e0b21SXiaojian Du 	if (!vangogh_clk_dpm_is_enabled(smu, clk_type))
840dd9e0b21SXiaojian Du 		return 0;
841dd9e0b21SXiaojian Du 
842dd9e0b21SXiaojian Du 	switch (clk_type) {
843dd9e0b21SXiaojian Du 	case SMU_GFXCLK:
844dd9e0b21SXiaojian Du 	case SMU_SCLK:
845dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
846dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinGfxClk,
847dd9e0b21SXiaojian Du 							min, NULL);
848dd9e0b21SXiaojian Du 		if (ret)
849dd9e0b21SXiaojian Du 			return ret;
850dd9e0b21SXiaojian Du 
851dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
852dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxGfxClk,
853dd9e0b21SXiaojian Du 							max, NULL);
854dd9e0b21SXiaojian Du 		if (ret)
855dd9e0b21SXiaojian Du 			return ret;
856dd9e0b21SXiaojian Du 		break;
857dd9e0b21SXiaojian Du 	case SMU_FCLK:
858dd9e0b21SXiaojian Du 	case SMU_MCLK:
859dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
860dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinFclkByFreq,
861dd9e0b21SXiaojian Du 							min, NULL);
862dd9e0b21SXiaojian Du 		if (ret)
863dd9e0b21SXiaojian Du 			return ret;
864dd9e0b21SXiaojian Du 
865dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
866dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxFclkByFreq,
867dd9e0b21SXiaojian Du 							max, NULL);
868dd9e0b21SXiaojian Du 		if (ret)
869dd9e0b21SXiaojian Du 			return ret;
870dd9e0b21SXiaojian Du 		break;
871dd9e0b21SXiaojian Du 	case SMU_SOCCLK:
872dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
873dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinSocclkByFreq,
874dd9e0b21SXiaojian Du 							min, NULL);
875dd9e0b21SXiaojian Du 		if (ret)
876dd9e0b21SXiaojian Du 			return ret;
877dd9e0b21SXiaojian Du 
878dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
879dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxSocclkByFreq,
880dd9e0b21SXiaojian Du 							max, NULL);
881dd9e0b21SXiaojian Du 		if (ret)
882dd9e0b21SXiaojian Du 			return ret;
883dd9e0b21SXiaojian Du 		break;
884dd9e0b21SXiaojian Du 	case SMU_VCLK:
885dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
886dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinVcn,
887dd9e0b21SXiaojian Du 							min << 16, NULL);
888dd9e0b21SXiaojian Du 		if (ret)
889dd9e0b21SXiaojian Du 			return ret;
890dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
891dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxVcn,
892dd9e0b21SXiaojian Du 							max << 16, NULL);
893dd9e0b21SXiaojian Du 		if (ret)
894dd9e0b21SXiaojian Du 			return ret;
895dd9e0b21SXiaojian Du 		break;
896dd9e0b21SXiaojian Du 	case SMU_DCLK:
897dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
898dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinVcn,
899dd9e0b21SXiaojian Du 							min, NULL);
900dd9e0b21SXiaojian Du 		if (ret)
901dd9e0b21SXiaojian Du 			return ret;
902dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
903dd9e0b21SXiaojian Du 							SMU_MSG_SetSoftMaxVcn,
904dd9e0b21SXiaojian Du 							max, NULL);
905dd9e0b21SXiaojian Du 		if (ret)
906dd9e0b21SXiaojian Du 			return ret;
907dd9e0b21SXiaojian Du 		break;
908dd9e0b21SXiaojian Du 	default:
909dd9e0b21SXiaojian Du 		return -EINVAL;
910dd9e0b21SXiaojian Du 	}
911dd9e0b21SXiaojian Du 
912dd9e0b21SXiaojian Du 	return ret;
913dd9e0b21SXiaojian Du }
914dd9e0b21SXiaojian Du 
915dd9e0b21SXiaojian Du static int vangogh_force_clk_levels(struct smu_context *smu,
916dd9e0b21SXiaojian Du 				   enum smu_clk_type clk_type, uint32_t mask)
917dd9e0b21SXiaojian Du {
918dd9e0b21SXiaojian Du 	uint32_t soft_min_level = 0, soft_max_level = 0;
919dd9e0b21SXiaojian Du 	uint32_t min_freq = 0, max_freq = 0;
920dd9e0b21SXiaojian Du 	int ret = 0 ;
921dd9e0b21SXiaojian Du 
922dd9e0b21SXiaojian Du 	soft_min_level = mask ? (ffs(mask) - 1) : 0;
923dd9e0b21SXiaojian Du 	soft_max_level = mask ? (fls(mask) - 1) : 0;
924dd9e0b21SXiaojian Du 
925dd9e0b21SXiaojian Du 	switch (clk_type) {
926dd9e0b21SXiaojian Du 	case SMU_SOCCLK:
927dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu, clk_type,
928dd9e0b21SXiaojian Du 						soft_min_level, &min_freq);
929dd9e0b21SXiaojian Du 		if (ret)
930dd9e0b21SXiaojian Du 			return ret;
931dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu, clk_type,
932dd9e0b21SXiaojian Du 						soft_max_level, &max_freq);
933dd9e0b21SXiaojian Du 		if (ret)
934dd9e0b21SXiaojian Du 			return ret;
935dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
936dd9e0b21SXiaojian Du 								SMU_MSG_SetSoftMaxSocclkByFreq,
937dd9e0b21SXiaojian Du 								max_freq, NULL);
938dd9e0b21SXiaojian Du 		if (ret)
939dd9e0b21SXiaojian Du 			return ret;
940dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
941dd9e0b21SXiaojian Du 								SMU_MSG_SetHardMinSocclkByFreq,
942dd9e0b21SXiaojian Du 								min_freq, NULL);
943dd9e0b21SXiaojian Du 		if (ret)
944dd9e0b21SXiaojian Du 			return ret;
945dd9e0b21SXiaojian Du 		break;
946dd9e0b21SXiaojian Du 	case SMU_MCLK:
947dd9e0b21SXiaojian Du 	case SMU_FCLK:
948dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
949dd9e0b21SXiaojian Du 							clk_type, soft_min_level, &min_freq);
950dd9e0b21SXiaojian Du 		if (ret)
951dd9e0b21SXiaojian Du 			return ret;
952dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
953dd9e0b21SXiaojian Du 							clk_type, soft_max_level, &max_freq);
954dd9e0b21SXiaojian Du 		if (ret)
955dd9e0b21SXiaojian Du 			return ret;
956dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
957dd9e0b21SXiaojian Du 								SMU_MSG_SetSoftMaxFclkByFreq,
958dd9e0b21SXiaojian Du 								max_freq, NULL);
959dd9e0b21SXiaojian Du 		if (ret)
960dd9e0b21SXiaojian Du 			return ret;
961dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
962dd9e0b21SXiaojian Du 								SMU_MSG_SetHardMinFclkByFreq,
963dd9e0b21SXiaojian Du 								min_freq, NULL);
964dd9e0b21SXiaojian Du 		if (ret)
965dd9e0b21SXiaojian Du 			return ret;
966dd9e0b21SXiaojian Du 		break;
967dd9e0b21SXiaojian Du 	case SMU_VCLK:
968dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
969dd9e0b21SXiaojian Du 							clk_type, soft_min_level, &min_freq);
970dd9e0b21SXiaojian Du 		if (ret)
971dd9e0b21SXiaojian Du 			return ret;
972307f049bSXiaojian Du 
973dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
974dd9e0b21SXiaojian Du 							clk_type, soft_max_level, &max_freq);
975dd9e0b21SXiaojian Du 		if (ret)
976dd9e0b21SXiaojian Du 			return ret;
977307f049bSXiaojian Du 
978307f049bSXiaojian Du 
979dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
980dd9e0b21SXiaojian Du 								SMU_MSG_SetHardMinVcn,
981dd9e0b21SXiaojian Du 								min_freq << 16, NULL);
982dd9e0b21SXiaojian Du 		if (ret)
983dd9e0b21SXiaojian Du 			return ret;
984307f049bSXiaojian Du 
985307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
986307f049bSXiaojian Du 								SMU_MSG_SetSoftMaxVcn,
987307f049bSXiaojian Du 								max_freq << 16, NULL);
988307f049bSXiaojian Du 		if (ret)
989307f049bSXiaojian Du 			return ret;
990307f049bSXiaojian Du 
991dd9e0b21SXiaojian Du 		break;
992dd9e0b21SXiaojian Du 	case SMU_DCLK:
993dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
994dd9e0b21SXiaojian Du 							clk_type, soft_min_level, &min_freq);
995dd9e0b21SXiaojian Du 		if (ret)
996dd9e0b21SXiaojian Du 			return ret;
997307f049bSXiaojian Du 
998dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_clk_limited(smu,
999dd9e0b21SXiaojian Du 							clk_type, soft_max_level, &max_freq);
1000dd9e0b21SXiaojian Du 		if (ret)
1001dd9e0b21SXiaojian Du 			return ret;
1002307f049bSXiaojian Du 
1003dd9e0b21SXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1004dd9e0b21SXiaojian Du 							SMU_MSG_SetHardMinVcn,
1005dd9e0b21SXiaojian Du 							min_freq, NULL);
1006dd9e0b21SXiaojian Du 		if (ret)
1007dd9e0b21SXiaojian Du 			return ret;
1008307f049bSXiaojian Du 
1009307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1010307f049bSXiaojian Du 							SMU_MSG_SetSoftMaxVcn,
1011307f049bSXiaojian Du 							max_freq, NULL);
1012307f049bSXiaojian Du 		if (ret)
1013307f049bSXiaojian Du 			return ret;
1014307f049bSXiaojian Du 
1015dd9e0b21SXiaojian Du 		break;
1016dd9e0b21SXiaojian Du 	default:
1017dd9e0b21SXiaojian Du 		break;
1018dd9e0b21SXiaojian Du 	}
1019dd9e0b21SXiaojian Du 
1020dd9e0b21SXiaojian Du 	return ret;
1021dd9e0b21SXiaojian Du }
1022dd9e0b21SXiaojian Du 
1023dd9e0b21SXiaojian Du static int vangogh_force_dpm_limit_value(struct smu_context *smu, bool highest)
1024dd9e0b21SXiaojian Du {
1025dd9e0b21SXiaojian Du 	int ret = 0, i = 0;
1026dd9e0b21SXiaojian Du 	uint32_t min_freq, max_freq, force_freq;
1027dd9e0b21SXiaojian Du 	enum smu_clk_type clk_type;
1028dd9e0b21SXiaojian Du 
1029dd9e0b21SXiaojian Du 	enum smu_clk_type clks[] = {
1030dd9e0b21SXiaojian Du 		SMU_SOCCLK,
1031dd9e0b21SXiaojian Du 		SMU_VCLK,
1032dd9e0b21SXiaojian Du 		SMU_DCLK,
1033dd9e0b21SXiaojian Du 		SMU_MCLK,
1034dd9e0b21SXiaojian Du 		SMU_FCLK,
1035dd9e0b21SXiaojian Du 	};
1036dd9e0b21SXiaojian Du 
1037dd9e0b21SXiaojian Du 	for (i = 0; i < ARRAY_SIZE(clks); i++) {
1038dd9e0b21SXiaojian Du 		clk_type = clks[i];
1039dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
1040dd9e0b21SXiaojian Du 		if (ret)
1041dd9e0b21SXiaojian Du 			return ret;
1042dd9e0b21SXiaojian Du 
1043dd9e0b21SXiaojian Du 		force_freq = highest ? max_freq : min_freq;
1044dd9e0b21SXiaojian Du 		ret = vangogh_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq);
1045dd9e0b21SXiaojian Du 		if (ret)
1046dd9e0b21SXiaojian Du 			return ret;
1047dd9e0b21SXiaojian Du 	}
1048dd9e0b21SXiaojian Du 
1049dd9e0b21SXiaojian Du 	return ret;
1050dd9e0b21SXiaojian Du }
1051dd9e0b21SXiaojian Du 
1052dd9e0b21SXiaojian Du static int vangogh_unforce_dpm_levels(struct smu_context *smu)
1053dd9e0b21SXiaojian Du {
1054dd9e0b21SXiaojian Du 	int ret = 0, i = 0;
1055dd9e0b21SXiaojian Du 	uint32_t min_freq, max_freq;
1056dd9e0b21SXiaojian Du 	enum smu_clk_type clk_type;
1057dd9e0b21SXiaojian Du 
1058dd9e0b21SXiaojian Du 	struct clk_feature_map {
1059dd9e0b21SXiaojian Du 		enum smu_clk_type clk_type;
1060dd9e0b21SXiaojian Du 		uint32_t	feature;
1061dd9e0b21SXiaojian Du 	} clk_feature_map[] = {
1062dd9e0b21SXiaojian Du 		{SMU_MCLK,   SMU_FEATURE_DPM_FCLK_BIT},
1063dd9e0b21SXiaojian Du 		{SMU_FCLK, SMU_FEATURE_DPM_FCLK_BIT},
1064dd9e0b21SXiaojian Du 		{SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT},
1065b0eec124SXiaojian Du 		{SMU_VCLK, SMU_FEATURE_VCN_DPM_BIT},
1066b0eec124SXiaojian Du 		{SMU_DCLK, SMU_FEATURE_VCN_DPM_BIT},
1067dd9e0b21SXiaojian Du 	};
1068dd9e0b21SXiaojian Du 
1069dd9e0b21SXiaojian Du 	for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) {
1070dd9e0b21SXiaojian Du 
1071dd9e0b21SXiaojian Du 		if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature))
1072dd9e0b21SXiaojian Du 		    continue;
1073dd9e0b21SXiaojian Du 
1074dd9e0b21SXiaojian Du 		clk_type = clk_feature_map[i].clk_type;
1075dd9e0b21SXiaojian Du 
1076dd9e0b21SXiaojian Du 		ret = vangogh_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
1077dd9e0b21SXiaojian Du 
1078dd9e0b21SXiaojian Du 		if (ret)
1079dd9e0b21SXiaojian Du 			return ret;
1080dd9e0b21SXiaojian Du 
1081dd9e0b21SXiaojian Du 		ret = vangogh_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
1082dd9e0b21SXiaojian Du 
1083dd9e0b21SXiaojian Du 		if (ret)
1084dd9e0b21SXiaojian Du 			return ret;
1085dd9e0b21SXiaojian Du 	}
1086dd9e0b21SXiaojian Du 
1087dd9e0b21SXiaojian Du 	return ret;
1088dd9e0b21SXiaojian Du }
1089dd9e0b21SXiaojian Du 
1090dd9e0b21SXiaojian Du static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
1091dd9e0b21SXiaojian Du {
1092dd9e0b21SXiaojian Du 	int ret = 0;
1093dd9e0b21SXiaojian Du 	uint32_t socclk_freq = 0, fclk_freq = 0;
1094307f049bSXiaojian Du 	uint32_t vclk_freq = 0, dclk_freq = 0;
1095dd9e0b21SXiaojian Du 
1096dd9e0b21SXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_freq);
1097dd9e0b21SXiaojian Du 	if (ret)
1098dd9e0b21SXiaojian Du 		return ret;
1099dd9e0b21SXiaojian Du 
1100dd9e0b21SXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_FCLK, fclk_freq, fclk_freq);
1101dd9e0b21SXiaojian Du 	if (ret)
1102dd9e0b21SXiaojian Du 		return ret;
1103dd9e0b21SXiaojian Du 
1104dd9e0b21SXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_freq);
1105dd9e0b21SXiaojian Du 	if (ret)
1106dd9e0b21SXiaojian Du 		return ret;
1107dd9e0b21SXiaojian Du 
1108dd9e0b21SXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk_freq, socclk_freq);
1109dd9e0b21SXiaojian Du 	if (ret)
1110dd9e0b21SXiaojian Du 		return ret;
1111dd9e0b21SXiaojian Du 
1112307f049bSXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_freq);
1113307f049bSXiaojian Du 	if (ret)
1114307f049bSXiaojian Du 		return ret;
1115307f049bSXiaojian Du 
1116307f049bSXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_VCLK, vclk_freq, vclk_freq);
1117307f049bSXiaojian Du 	if (ret)
1118307f049bSXiaojian Du 		return ret;
1119307f049bSXiaojian Du 
1120307f049bSXiaojian Du 	ret = vangogh_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_freq);
1121307f049bSXiaojian Du 	if (ret)
1122307f049bSXiaojian Du 		return ret;
1123307f049bSXiaojian Du 
1124307f049bSXiaojian Du 	ret = vangogh_set_soft_freq_limited_range(smu, SMU_DCLK, dclk_freq, dclk_freq);
1125307f049bSXiaojian Du 	if (ret)
1126307f049bSXiaojian Du 		return ret;
1127307f049bSXiaojian Du 
1128dd9e0b21SXiaojian Du 	return ret;
1129dd9e0b21SXiaojian Du }
1130dd9e0b21SXiaojian Du 
1131ea173d15SXiaojian Du static int vangogh_set_performance_level(struct smu_context *smu,
1132ea173d15SXiaojian Du 					enum amd_dpm_forced_level level)
1133ea173d15SXiaojian Du {
1134ea173d15SXiaojian Du 	int ret = 0;
1135ea173d15SXiaojian Du 	uint32_t soc_mask, mclk_mask, fclk_mask;
1136307f049bSXiaojian Du 	uint32_t vclk_mask = 0, dclk_mask = 0;
1137ea173d15SXiaojian Du 
1138ea173d15SXiaojian Du 	switch (level) {
1139ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_HIGH:
1140d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1141d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1142d7379efaSXiaojian Du 
1143d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1144d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1145d7379efaSXiaojian Du 
1146ea173d15SXiaojian Du 		ret = vangogh_force_dpm_limit_value(smu, true);
1147ea173d15SXiaojian Du 		break;
1148ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_LOW:
1149d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1150d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1151d7379efaSXiaojian Du 
1152d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1153d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1154d7379efaSXiaojian Du 
1155ea173d15SXiaojian Du 		ret = vangogh_force_dpm_limit_value(smu, false);
1156ea173d15SXiaojian Du 		break;
1157ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_AUTO:
1158d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1159d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1160d7379efaSXiaojian Du 
1161d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1162d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1163d7379efaSXiaojian Du 
1164ea173d15SXiaojian Du 		ret = vangogh_unforce_dpm_levels(smu);
1165ea173d15SXiaojian Du 		break;
1166ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1167d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1168d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1169d7379efaSXiaojian Du 
1170d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1171d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1172d7379efaSXiaojian Du 
1173307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1174307f049bSXiaojian Du 					SMU_MSG_SetHardMinGfxClk,
1175307f049bSXiaojian Du 					VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL);
1176307f049bSXiaojian Du 		if (ret)
1177307f049bSXiaojian Du 			return ret;
1178307f049bSXiaojian Du 
1179307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu,
1180307f049bSXiaojian Du 					SMU_MSG_SetSoftMaxGfxClk,
1181307f049bSXiaojian Du 					VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL);
1182307f049bSXiaojian Du 		if (ret)
1183307f049bSXiaojian Du 			return ret;
1184307f049bSXiaojian Du 
1185307f049bSXiaojian Du 		ret = vangogh_get_profiling_clk_mask(smu, level,
1186307f049bSXiaojian Du 							&vclk_mask,
1187307f049bSXiaojian Du 							&dclk_mask,
1188307f049bSXiaojian Du 							&mclk_mask,
1189307f049bSXiaojian Du 							&fclk_mask,
1190307f049bSXiaojian Du 							&soc_mask);
1191307f049bSXiaojian Du 		if (ret)
1192307f049bSXiaojian Du 			return ret;
1193307f049bSXiaojian Du 
1194307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
1195307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
1196307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
1197307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_VCLK, 1 << vclk_mask);
1198307f049bSXiaojian Du 		vangogh_force_clk_levels(smu, SMU_DCLK, 1 << dclk_mask);
1199307f049bSXiaojian Du 
1200ea173d15SXiaojian Du 		break;
1201ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1202d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1203d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1204d7379efaSXiaojian Du 
1205d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1206d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1207d7379efaSXiaojian Du 
1208307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn,
1209307f049bSXiaojian Du 								VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL);
1210307f049bSXiaojian Du 		if (ret)
1211307f049bSXiaojian Du 			return ret;
1212307f049bSXiaojian Du 
1213307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn,
1214307f049bSXiaojian Du 								VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL);
1215307f049bSXiaojian Du 		if (ret)
1216307f049bSXiaojian Du 			return ret;
1217ea173d15SXiaojian Du 		break;
1218ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1219d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1220d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1221d7379efaSXiaojian Du 
1222d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1223d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1224d7379efaSXiaojian Du 
1225ea173d15SXiaojian Du 		ret = vangogh_get_profiling_clk_mask(smu, level,
1226ea173d15SXiaojian Du 							NULL,
1227ea173d15SXiaojian Du 							NULL,
1228ea173d15SXiaojian Du 							&mclk_mask,
1229ea173d15SXiaojian Du 							&fclk_mask,
1230307f049bSXiaojian Du 							NULL);
1231ea173d15SXiaojian Du 		if (ret)
1232ea173d15SXiaojian Du 			return ret;
1233307f049bSXiaojian Du 
1234ea173d15SXiaojian Du 		vangogh_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
1235ea173d15SXiaojian Du 		vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask);
1236ea173d15SXiaojian Du 		break;
1237ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1238d7379efaSXiaojian Du 		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1239d7379efaSXiaojian Du 		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1240d7379efaSXiaojian Du 
1241d7379efaSXiaojian Du 		smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
1242d7379efaSXiaojian Du 		smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1243d7379efaSXiaojian Du 
1244307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
1245307f049bSXiaojian Du 				VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL);
1246307f049bSXiaojian Du 		if (ret)
1247307f049bSXiaojian Du 			return ret;
1248307f049bSXiaojian Du 
1249307f049bSXiaojian Du 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
1250307f049bSXiaojian Du 				VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL);
1251307f049bSXiaojian Du 		if (ret)
1252307f049bSXiaojian Du 			return ret;
1253307f049bSXiaojian Du 
1254ea173d15SXiaojian Du 		ret = vangogh_set_peak_clock_by_device(smu);
1255ea173d15SXiaojian Du 		break;
1256ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_MANUAL:
1257ea173d15SXiaojian Du 	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1258ea173d15SXiaojian Du 	default:
1259ea173d15SXiaojian Du 		break;
1260ea173d15SXiaojian Du 	}
1261ea173d15SXiaojian Du 	return ret;
1262ea173d15SXiaojian Du }
1263ea173d15SXiaojian Du 
1264271ab489SXiaojian Du static int vangogh_read_sensor(struct smu_context *smu,
1265271ab489SXiaojian Du 				 enum amd_pp_sensors sensor,
1266271ab489SXiaojian Du 				 void *data, uint32_t *size)
1267271ab489SXiaojian Du {
1268271ab489SXiaojian Du 	int ret = 0;
1269271ab489SXiaojian Du 
1270271ab489SXiaojian Du 	if (!data || !size)
1271271ab489SXiaojian Du 		return -EINVAL;
1272271ab489SXiaojian Du 
1273271ab489SXiaojian Du 	mutex_lock(&smu->sensor_lock);
1274271ab489SXiaojian Du 	switch (sensor) {
1275271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GPU_LOAD:
12766cc24d8dSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
12776cc24d8dSAlex Deucher 						   METRICS_AVERAGE_GFXACTIVITY,
12786cc24d8dSAlex Deucher 						   (uint32_t *)data);
1279271ab489SXiaojian Du 		*size = 4;
1280271ab489SXiaojian Du 		break;
1281271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GPU_POWER:
12826cc24d8dSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
12836cc24d8dSAlex Deucher 						   METRICS_AVERAGE_SOCKETPOWER,
12846cc24d8dSAlex Deucher 						   (uint32_t *)data);
1285271ab489SXiaojian Du 		*size = 4;
1286271ab489SXiaojian Du 		break;
1287271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_EDGE_TEMP:
12886cc24d8dSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
12896cc24d8dSAlex Deucher 						   METRICS_TEMPERATURE_EDGE,
12906cc24d8dSAlex Deucher 						   (uint32_t *)data);
12916cc24d8dSAlex Deucher 		*size = 4;
12926cc24d8dSAlex Deucher 		break;
1293271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
12946cc24d8dSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
12956cc24d8dSAlex Deucher 						   METRICS_TEMPERATURE_HOTSPOT,
12966cc24d8dSAlex Deucher 						   (uint32_t *)data);
1297271ab489SXiaojian Du 		*size = 4;
1298271ab489SXiaojian Du 		break;
1299271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GFX_MCLK:
13006cc24d8dSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
13016cc24d8dSAlex Deucher 						   METRICS_AVERAGE_UCLK,
13026cc24d8dSAlex Deucher 						   (uint32_t *)data);
1303271ab489SXiaojian Du 		*(uint32_t *)data *= 100;
1304271ab489SXiaojian Du 		*size = 4;
1305271ab489SXiaojian Du 		break;
1306271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_GFX_SCLK:
13076cc24d8dSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
13086cc24d8dSAlex Deucher 						   METRICS_AVERAGE_GFXCLK,
13096cc24d8dSAlex Deucher 						   (uint32_t *)data);
1310271ab489SXiaojian Du 		*(uint32_t *)data *= 100;
1311271ab489SXiaojian Du 		*size = 4;
1312271ab489SXiaojian Du 		break;
1313271ab489SXiaojian Du 	case AMDGPU_PP_SENSOR_VDDGFX:
13142139d12bSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
13152139d12bSAlex Deucher 						   METRICS_VOLTAGE_VDDGFX,
13162139d12bSAlex Deucher 						   (uint32_t *)data);
13172139d12bSAlex Deucher 		*size = 4;
13182139d12bSAlex Deucher 		break;
13192139d12bSAlex Deucher 	case AMDGPU_PP_SENSOR_VDDNB:
13202139d12bSAlex Deucher 		ret = vangogh_get_smu_metrics_data(smu,
13212139d12bSAlex Deucher 						   METRICS_VOLTAGE_VDDSOC,
13222139d12bSAlex Deucher 						   (uint32_t *)data);
1323271ab489SXiaojian Du 		*size = 4;
1324271ab489SXiaojian Du 		break;
1325517cb957SHuang Rui 	case AMDGPU_PP_SENSOR_CPU_CLK:
1326517cb957SHuang Rui 		ret = vangogh_get_smu_metrics_data(smu,
1327517cb957SHuang Rui 						   METRICS_AVERAGE_CPUCLK,
1328517cb957SHuang Rui 						   (uint32_t *)data);
13294aef0ebcSHuang Rui 		*size = smu->cpu_core_num * sizeof(uint16_t);
1330517cb957SHuang Rui 		break;
1331271ab489SXiaojian Du 	default:
1332271ab489SXiaojian Du 		ret = -EOPNOTSUPP;
1333271ab489SXiaojian Du 		break;
1334271ab489SXiaojian Du 	}
1335271ab489SXiaojian Du 	mutex_unlock(&smu->sensor_lock);
1336271ab489SXiaojian Du 
1337271ab489SXiaojian Du 	return ret;
1338271ab489SXiaojian Du }
1339271ab489SXiaojian Du 
1340271ab489SXiaojian Du static int vangogh_set_watermarks_table(struct smu_context *smu,
1341271ab489SXiaojian Du 				       struct pp_smu_wm_range_sets *clock_ranges)
1342271ab489SXiaojian Du {
1343271ab489SXiaojian Du 	int i;
1344271ab489SXiaojian Du 	int ret = 0;
1345271ab489SXiaojian Du 	Watermarks_t *table = smu->smu_table.watermarks_table;
1346271ab489SXiaojian Du 
1347271ab489SXiaojian Du 	if (!table || !clock_ranges)
1348271ab489SXiaojian Du 		return -EINVAL;
1349271ab489SXiaojian Du 
1350271ab489SXiaojian Du 	if (clock_ranges) {
1351271ab489SXiaojian Du 		if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
1352271ab489SXiaojian Du 			clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
1353271ab489SXiaojian Du 			return -EINVAL;
1354271ab489SXiaojian Du 
1355271ab489SXiaojian Du 		for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
1356271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MinClock =
1357271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
1358271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MaxClock =
1359271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
1360271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MinMclk =
1361271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
1362271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
1363271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
1364271ab489SXiaojian Du 
1365271ab489SXiaojian Du 			table->WatermarkRow[WM_DCFCLK][i].WmSetting =
1366271ab489SXiaojian Du 				clock_ranges->reader_wm_sets[i].wm_inst;
1367271ab489SXiaojian Du 		}
1368271ab489SXiaojian Du 
1369271ab489SXiaojian Du 		for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
1370271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MinClock =
1371271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
1372271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MaxClock =
1373271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
1374271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MinMclk =
1375271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
1376271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
1377271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
1378271ab489SXiaojian Du 
1379271ab489SXiaojian Du 			table->WatermarkRow[WM_SOCCLK][i].WmSetting =
1380271ab489SXiaojian Du 				clock_ranges->writer_wm_sets[i].wm_inst;
1381271ab489SXiaojian Du 		}
1382271ab489SXiaojian Du 
1383271ab489SXiaojian Du 		smu->watermarks_bitmap |= WATERMARKS_EXIST;
1384271ab489SXiaojian Du 	}
1385271ab489SXiaojian Du 
1386271ab489SXiaojian Du 	/* pass data to smu controller */
1387271ab489SXiaojian Du 	if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1388271ab489SXiaojian Du 	     !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1389271ab489SXiaojian Du 		ret = smu_cmn_write_watermarks_table(smu);
1390271ab489SXiaojian Du 		if (ret) {
1391271ab489SXiaojian Du 			dev_err(smu->adev->dev, "Failed to update WMTABLE!");
1392271ab489SXiaojian Du 			return ret;
1393271ab489SXiaojian Du 		}
1394271ab489SXiaojian Du 		smu->watermarks_bitmap |= WATERMARKS_LOADED;
1395271ab489SXiaojian Du 	}
1396271ab489SXiaojian Du 
1397271ab489SXiaojian Du 	return 0;
1398f46a221bSXiaojian Du }
1399f46a221bSXiaojian Du 
1400fd253334SXiaojian Du static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
1401fd253334SXiaojian Du 				      void **table)
1402fd253334SXiaojian Du {
1403fd253334SXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
1404fd253334SXiaojian Du 	struct gpu_metrics_v2_0 *gpu_metrics =
1405fd253334SXiaojian Du 		(struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table;
1406fd253334SXiaojian Du 	SmuMetrics_t metrics;
1407fd253334SXiaojian Du 	int ret = 0;
1408fd253334SXiaojian Du 
1409fd253334SXiaojian Du 	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1410fd253334SXiaojian Du 	if (ret)
1411fd253334SXiaojian Du 		return ret;
1412fd253334SXiaojian Du 
1413de4b7cd8SKevin Wang 	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 0);
1414fd253334SXiaojian Du 
1415fd253334SXiaojian Du 	gpu_metrics->temperature_gfx = metrics.GfxTemperature;
1416fd253334SXiaojian Du 	gpu_metrics->temperature_soc = metrics.SocTemperature;
1417fd253334SXiaojian Du 	memcpy(&gpu_metrics->temperature_core[0],
1418fd253334SXiaojian Du 		&metrics.CoreTemperature[0],
1419fd253334SXiaojian Du 		sizeof(uint16_t) * 8);
1420fd253334SXiaojian Du 	gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
1421fd253334SXiaojian Du 	gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
1422fd253334SXiaojian Du 
1423fd253334SXiaojian Du 	gpu_metrics->average_gfx_activity = metrics.GfxActivity;
1424fd253334SXiaojian Du 	gpu_metrics->average_mm_activity = metrics.UvdActivity;
1425fd253334SXiaojian Du 
1426fd253334SXiaojian Du 	gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
1427fd253334SXiaojian Du 	gpu_metrics->average_cpu_power = metrics.Power[0];
1428fd253334SXiaojian Du 	gpu_metrics->average_soc_power = metrics.Power[1];
1429c9021a6eSXiaojian Du 	gpu_metrics->average_gfx_power = metrics.Power[2];
1430fd253334SXiaojian Du 	memcpy(&gpu_metrics->average_core_power[0],
1431fd253334SXiaojian Du 		&metrics.CorePower[0],
1432fd253334SXiaojian Du 		sizeof(uint16_t) * 8);
1433fd253334SXiaojian Du 
1434fd253334SXiaojian Du 	gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
1435fd253334SXiaojian Du 	gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
1436c9021a6eSXiaojian Du 	gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
1437fd253334SXiaojian Du 	gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
1438fd253334SXiaojian Du 	gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
1439c9021a6eSXiaojian Du 	gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
1440fd253334SXiaojian Du 
1441fd253334SXiaojian Du 	memcpy(&gpu_metrics->current_coreclk[0],
1442fd253334SXiaojian Du 		&metrics.CoreFrequency[0],
1443fd253334SXiaojian Du 		sizeof(uint16_t) * 8);
1444fd253334SXiaojian Du 	gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
1445fd253334SXiaojian Du 	gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1];
1446fd253334SXiaojian Du 
1447fd253334SXiaojian Du 	gpu_metrics->throttle_status = metrics.ThrottlerStatus;
1448fd253334SXiaojian Du 
1449de4b7cd8SKevin Wang 	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1450de4b7cd8SKevin Wang 
1451fd253334SXiaojian Du 	*table = (void *)gpu_metrics;
1452fd253334SXiaojian Du 
1453fd253334SXiaojian Du 	return sizeof(struct gpu_metrics_v2_0);
1454fd253334SXiaojian Du }
1455fd253334SXiaojian Du 
1456c98ee897SXiaojian Du static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
1457c98ee897SXiaojian Du 					long input[], uint32_t size)
1458c98ee897SXiaojian Du {
1459c98ee897SXiaojian Du 	int ret = 0;
14600d90d0ddSHuang Rui 	int i;
1461d7379efaSXiaojian Du 	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
1462c98ee897SXiaojian Du 
1463d7379efaSXiaojian Du 	if (!(smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)) {
1464d7ef887fSXiaojian Du 		dev_warn(smu->adev->dev,
1465*ce7c670dSColin Ian King 			"pp_od_clk_voltage is not accessible if power_dpm_force_performance_level is not in manual mode!\n");
1466c98ee897SXiaojian Du 		return -EINVAL;
1467c98ee897SXiaojian Du 	}
1468c98ee897SXiaojian Du 
1469c98ee897SXiaojian Du 	switch (type) {
14700d90d0ddSHuang Rui 	case PP_OD_EDIT_CCLK_VDDC_TABLE:
14710d90d0ddSHuang Rui 		if (size != 3) {
14720d90d0ddSHuang Rui 			dev_err(smu->adev->dev, "Input parameter number not correct (should be 4 for processor)\n");
14730d90d0ddSHuang Rui 			return -EINVAL;
14740d90d0ddSHuang Rui 		}
14754aef0ebcSHuang Rui 		if (input[0] >= smu->cpu_core_num) {
14760d90d0ddSHuang Rui 			dev_err(smu->adev->dev, "core index is overflow, should be less than %d\n",
14774aef0ebcSHuang Rui 				smu->cpu_core_num);
14780d90d0ddSHuang Rui 		}
14790d90d0ddSHuang Rui 		smu->cpu_core_id_select = input[0];
14800d90d0ddSHuang Rui 		if (input[1] == 0) {
14810d90d0ddSHuang Rui 			if (input[2] < smu->cpu_default_soft_min_freq) {
14820d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "Fine grain setting minimum cclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
14830d90d0ddSHuang Rui 					input[2], smu->cpu_default_soft_min_freq);
14840d90d0ddSHuang Rui 				return -EINVAL;
14850d90d0ddSHuang Rui 			}
14860d90d0ddSHuang Rui 			smu->cpu_actual_soft_min_freq = input[2];
14870d90d0ddSHuang Rui 		} else if (input[1] == 1) {
14880d90d0ddSHuang Rui 			if (input[2] > smu->cpu_default_soft_max_freq) {
14890d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "Fine grain setting maximum cclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
14900d90d0ddSHuang Rui 					input[2], smu->cpu_default_soft_max_freq);
14910d90d0ddSHuang Rui 				return -EINVAL;
14920d90d0ddSHuang Rui 			}
14930d90d0ddSHuang Rui 			smu->cpu_actual_soft_max_freq = input[2];
14940d90d0ddSHuang Rui 		} else {
14950d90d0ddSHuang Rui 			return -EINVAL;
14960d90d0ddSHuang Rui 		}
14970d90d0ddSHuang Rui 		break;
1498c98ee897SXiaojian Du 	case PP_OD_EDIT_SCLK_VDDC_TABLE:
1499c98ee897SXiaojian Du 		if (size != 2) {
1500c98ee897SXiaojian Du 			dev_err(smu->adev->dev, "Input parameter number not correct\n");
1501c98ee897SXiaojian Du 			return -EINVAL;
1502c98ee897SXiaojian Du 		}
1503c98ee897SXiaojian Du 
1504c98ee897SXiaojian Du 		if (input[0] == 0) {
1505c98ee897SXiaojian Du 			if (input[1] < smu->gfx_default_hard_min_freq) {
1506307f049bSXiaojian Du 				dev_warn(smu->adev->dev,
1507307f049bSXiaojian Du 					"Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
1508c98ee897SXiaojian Du 					input[1], smu->gfx_default_hard_min_freq);
1509c98ee897SXiaojian Du 				return -EINVAL;
1510c98ee897SXiaojian Du 			}
1511c98ee897SXiaojian Du 			smu->gfx_actual_hard_min_freq = input[1];
1512c98ee897SXiaojian Du 		} else if (input[0] == 1) {
1513c98ee897SXiaojian Du 			if (input[1] > smu->gfx_default_soft_max_freq) {
1514307f049bSXiaojian Du 				dev_warn(smu->adev->dev,
1515307f049bSXiaojian Du 					"Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
1516c98ee897SXiaojian Du 					input[1], smu->gfx_default_soft_max_freq);
1517c98ee897SXiaojian Du 				return -EINVAL;
1518c98ee897SXiaojian Du 			}
1519c98ee897SXiaojian Du 			smu->gfx_actual_soft_max_freq = input[1];
1520c98ee897SXiaojian Du 		} else {
1521c98ee897SXiaojian Du 			return -EINVAL;
1522c98ee897SXiaojian Du 		}
1523c98ee897SXiaojian Du 		break;
1524c98ee897SXiaojian Du 	case PP_OD_RESTORE_DEFAULT_TABLE:
1525c98ee897SXiaojian Du 		if (size != 0) {
1526c98ee897SXiaojian Du 			dev_err(smu->adev->dev, "Input parameter number not correct\n");
1527c98ee897SXiaojian Du 			return -EINVAL;
1528c98ee897SXiaojian Du 		} else {
1529c98ee897SXiaojian Du 			smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1530c98ee897SXiaojian Du 			smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
15310d90d0ddSHuang Rui 			smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq;
15320d90d0ddSHuang Rui 			smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq;
1533c98ee897SXiaojian Du 
1534c98ee897SXiaojian Du 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
1535c98ee897SXiaojian Du 									smu->gfx_actual_hard_min_freq, NULL);
1536c98ee897SXiaojian Du 			if (ret) {
1537c98ee897SXiaojian Du 				dev_err(smu->adev->dev, "Restore the default hard min sclk failed!");
1538c98ee897SXiaojian Du 				return ret;
1539c98ee897SXiaojian Du 			}
1540c98ee897SXiaojian Du 
1541c98ee897SXiaojian Du 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
1542c98ee897SXiaojian Du 									smu->gfx_actual_soft_max_freq, NULL);
1543c98ee897SXiaojian Du 			if (ret) {
1544c98ee897SXiaojian Du 				dev_err(smu->adev->dev, "Restore the default soft max sclk failed!");
1545c98ee897SXiaojian Du 				return ret;
1546c98ee897SXiaojian Du 			}
15470d90d0ddSHuang Rui 
15480d90d0ddSHuang Rui 			if (smu->adev->pm.fw_version < 0x43f1b00) {
15490d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "CPUSoftMax/CPUSoftMin are not supported, please update SBIOS!\n");
15500d90d0ddSHuang Rui 				break;
15510d90d0ddSHuang Rui 			}
15520d90d0ddSHuang Rui 
15534aef0ebcSHuang Rui 			for (i = 0; i < smu->cpu_core_num; i++) {
15540d90d0ddSHuang Rui 				ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk,
15550d90d0ddSHuang Rui 								      (i << 20) | smu->cpu_actual_soft_min_freq,
15560d90d0ddSHuang Rui 								      NULL);
15570d90d0ddSHuang Rui 				if (ret) {
15580d90d0ddSHuang Rui 					dev_err(smu->adev->dev, "Set hard min cclk failed!");
15590d90d0ddSHuang Rui 					return ret;
15600d90d0ddSHuang Rui 				}
15610d90d0ddSHuang Rui 
15620d90d0ddSHuang Rui 				ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk,
15630d90d0ddSHuang Rui 								      (i << 20) | smu->cpu_actual_soft_max_freq,
15640d90d0ddSHuang Rui 								      NULL);
15650d90d0ddSHuang Rui 				if (ret) {
15660d90d0ddSHuang Rui 					dev_err(smu->adev->dev, "Set soft max cclk failed!");
15670d90d0ddSHuang Rui 					return ret;
15680d90d0ddSHuang Rui 				}
15690d90d0ddSHuang Rui 			}
1570c98ee897SXiaojian Du 		}
1571c98ee897SXiaojian Du 		break;
1572c98ee897SXiaojian Du 	case PP_OD_COMMIT_DPM_TABLE:
1573c98ee897SXiaojian Du 		if (size != 0) {
1574c98ee897SXiaojian Du 			dev_err(smu->adev->dev, "Input parameter number not correct\n");
1575c98ee897SXiaojian Du 			return -EINVAL;
1576c98ee897SXiaojian Du 		} else {
1577c98ee897SXiaojian Du 			if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
1578307f049bSXiaojian Du 				dev_err(smu->adev->dev,
1579307f049bSXiaojian Du 					"The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
1580307f049bSXiaojian Du 					smu->gfx_actual_hard_min_freq,
1581307f049bSXiaojian Du 					smu->gfx_actual_soft_max_freq);
1582c98ee897SXiaojian Du 				return -EINVAL;
1583c98ee897SXiaojian Du 			}
1584c98ee897SXiaojian Du 
1585c98ee897SXiaojian Du 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
1586c98ee897SXiaojian Du 									smu->gfx_actual_hard_min_freq, NULL);
1587c98ee897SXiaojian Du 			if (ret) {
1588c98ee897SXiaojian Du 				dev_err(smu->adev->dev, "Set hard min sclk failed!");
1589c98ee897SXiaojian Du 				return ret;
1590c98ee897SXiaojian Du 			}
1591c98ee897SXiaojian Du 
1592c98ee897SXiaojian Du 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
1593c98ee897SXiaojian Du 									smu->gfx_actual_soft_max_freq, NULL);
1594c98ee897SXiaojian Du 			if (ret) {
1595c98ee897SXiaojian Du 				dev_err(smu->adev->dev, "Set soft max sclk failed!");
1596c98ee897SXiaojian Du 				return ret;
1597c98ee897SXiaojian Du 			}
15980d90d0ddSHuang Rui 
15990d90d0ddSHuang Rui 			if (smu->adev->pm.fw_version < 0x43f1b00) {
16000d90d0ddSHuang Rui 				dev_warn(smu->adev->dev, "CPUSoftMax/CPUSoftMin are not supported, please update SBIOS!\n");
16010d90d0ddSHuang Rui 				break;
16020d90d0ddSHuang Rui 			}
16030d90d0ddSHuang Rui 
16040d90d0ddSHuang Rui 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk,
16050d90d0ddSHuang Rui 							      ((smu->cpu_core_id_select << 20)
16060d90d0ddSHuang Rui 							       | smu->cpu_actual_soft_min_freq),
16070d90d0ddSHuang Rui 							      NULL);
16080d90d0ddSHuang Rui 			if (ret) {
16090d90d0ddSHuang Rui 				dev_err(smu->adev->dev, "Set hard min cclk failed!");
16100d90d0ddSHuang Rui 				return ret;
16110d90d0ddSHuang Rui 			}
16120d90d0ddSHuang Rui 
16130d90d0ddSHuang Rui 			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk,
16140d90d0ddSHuang Rui 							      ((smu->cpu_core_id_select << 20)
16150d90d0ddSHuang Rui 							       | smu->cpu_actual_soft_max_freq),
16160d90d0ddSHuang Rui 							      NULL);
16170d90d0ddSHuang Rui 			if (ret) {
16180d90d0ddSHuang Rui 				dev_err(smu->adev->dev, "Set soft max cclk failed!");
16190d90d0ddSHuang Rui 				return ret;
16200d90d0ddSHuang Rui 			}
1621c98ee897SXiaojian Du 		}
1622c98ee897SXiaojian Du 		break;
1623c98ee897SXiaojian Du 	default:
1624c98ee897SXiaojian Du 		return -ENOSYS;
1625c98ee897SXiaojian Du 	}
1626c98ee897SXiaojian Du 
1627c98ee897SXiaojian Du 	return ret;
1628c98ee897SXiaojian Du }
1629c98ee897SXiaojian Du 
1630fce8a4acSJinzhou Su static int vangogh_set_default_dpm_tables(struct smu_context *smu)
1631c98ee897SXiaojian Du {
1632c98ee897SXiaojian Du 	struct smu_table_context *smu_table = &smu->smu_table;
1633c98ee897SXiaojian Du 
1634c98ee897SXiaojian Du 	return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
1635c98ee897SXiaojian Du }
1636c98ee897SXiaojian Du 
1637c98ee897SXiaojian Du static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
1638c98ee897SXiaojian Du {
1639c98ee897SXiaojian Du 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
1640c98ee897SXiaojian Du 
1641c98ee897SXiaojian Du 	smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
1642c98ee897SXiaojian Du 	smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
1643c98ee897SXiaojian Du 	smu->gfx_actual_hard_min_freq = 0;
1644c98ee897SXiaojian Du 	smu->gfx_actual_soft_max_freq = 0;
1645c98ee897SXiaojian Du 
16460d90d0ddSHuang Rui 	smu->cpu_default_soft_min_freq = 1400;
16470d90d0ddSHuang Rui 	smu->cpu_default_soft_max_freq = 3500;
16480d90d0ddSHuang Rui 	smu->cpu_actual_soft_min_freq = 0;
16490d90d0ddSHuang Rui 	smu->cpu_actual_soft_max_freq = 0;
16500d90d0ddSHuang Rui 
1651c98ee897SXiaojian Du 	return 0;
1652c98ee897SXiaojian Du }
1653c98ee897SXiaojian Du 
1654ae7b32e7SXiaojian Du static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
1655ae7b32e7SXiaojian Du {
1656ae7b32e7SXiaojian Du 	DpmClocks_t *table = smu->smu_table.clocks_table;
1657ae7b32e7SXiaojian Du 	int i;
1658ae7b32e7SXiaojian Du 
1659ae7b32e7SXiaojian Du 	if (!clock_table || !table)
1660ae7b32e7SXiaojian Du 		return -EINVAL;
1661ae7b32e7SXiaojian Du 
1662ae7b32e7SXiaojian Du 	for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
1663ae7b32e7SXiaojian Du 		clock_table->SocClocks[i].Freq = table->SocClocks[i];
1664ae7b32e7SXiaojian Du 		clock_table->SocClocks[i].Vol = table->SocVoltage[i];
1665ae7b32e7SXiaojian Du 	}
1666ae7b32e7SXiaojian Du 
1667ae7b32e7SXiaojian Du 	for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
1668ae7b32e7SXiaojian Du 		clock_table->FClocks[i].Freq = table->DfPstateTable[i].fclk;
1669ae7b32e7SXiaojian Du 		clock_table->FClocks[i].Vol = table->DfPstateTable[i].voltage;
1670ae7b32e7SXiaojian Du 	}
1671ae7b32e7SXiaojian Du 
1672ae7b32e7SXiaojian Du 	for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
1673ae7b32e7SXiaojian Du 		clock_table->MemClocks[i].Freq = table->DfPstateTable[i].memclk;
1674ae7b32e7SXiaojian Du 		clock_table->MemClocks[i].Vol = table->DfPstateTable[i].voltage;
1675ae7b32e7SXiaojian Du 	}
1676ae7b32e7SXiaojian Du 
1677ae7b32e7SXiaojian Du 	return 0;
1678ae7b32e7SXiaojian Du }
1679ae7b32e7SXiaojian Du 
1680ae7b32e7SXiaojian Du 
1681a0f55287SXiaomeng Hou static int vangogh_system_features_control(struct smu_context *smu, bool en)
1682a0f55287SXiaomeng Hou {
16839e3a6ab7SXiaomeng Hou 	struct amdgpu_device *adev = smu->adev;
1684aedebd40SHuang Rui 	struct smu_feature *feature = &smu->smu_feature;
1685aedebd40SHuang Rui 	uint32_t feature_mask[2];
1686aedebd40SHuang Rui 	int ret = 0;
16879e3a6ab7SXiaomeng Hou 
16889e3a6ab7SXiaomeng Hou 	if (adev->pm.fw_version >= 0x43f1700)
1689aedebd40SHuang Rui 		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify,
1690a0f55287SXiaomeng Hou 						      en ? RLC_STATUS_NORMAL : RLC_STATUS_OFF, NULL);
1691aedebd40SHuang Rui 
1692aedebd40SHuang Rui 	bitmap_zero(feature->enabled, feature->feature_num);
1693aedebd40SHuang Rui 	bitmap_zero(feature->supported, feature->feature_num);
1694aedebd40SHuang Rui 
1695aedebd40SHuang Rui 	if (!en)
1696aedebd40SHuang Rui 		return ret;
1697aedebd40SHuang Rui 
1698aedebd40SHuang Rui 	ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2);
1699aedebd40SHuang Rui 	if (ret)
1700aedebd40SHuang Rui 		return ret;
1701aedebd40SHuang Rui 
1702aedebd40SHuang Rui 	bitmap_copy(feature->enabled, (unsigned long *)&feature_mask,
1703aedebd40SHuang Rui 		    feature->feature_num);
1704aedebd40SHuang Rui 	bitmap_copy(feature->supported, (unsigned long *)&feature_mask,
1705aedebd40SHuang Rui 		    feature->feature_num);
1706aedebd40SHuang Rui 
17079e3a6ab7SXiaomeng Hou 	return 0;
1708a0f55287SXiaomeng Hou }
1709a0f55287SXiaomeng Hou 
1710eefdf047SJinzhou Su static int vangogh_post_smu_init(struct smu_context *smu)
1711eefdf047SJinzhou Su {
1712eefdf047SJinzhou Su 	struct amdgpu_device *adev = smu->adev;
1713eefdf047SJinzhou Su 	uint32_t tmp;
17143313ef18SJinzhou Su 	int ret = 0;
1715eefdf047SJinzhou Su 	uint8_t aon_bits = 0;
1716eefdf047SJinzhou Su 	/* Two CUs in one WGP */
1717eefdf047SJinzhou Su 	uint32_t req_active_wgps = adev->gfx.cu_info.number/2;
1718eefdf047SJinzhou Su 	uint32_t total_cu = adev->gfx.config.max_cu_per_sh *
1719eefdf047SJinzhou Su 		adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
1720eefdf047SJinzhou Su 
17213313ef18SJinzhou Su 	/* allow message will be sent after enable message on Vangogh*/
1722bb377febSJinzhou Su 	if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
1723bb377febSJinzhou Su 			(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
17243313ef18SJinzhou Su 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
17253313ef18SJinzhou Su 		if (ret) {
17263313ef18SJinzhou Su 			dev_err(adev->dev, "Failed to Enable GfxOff!\n");
17273313ef18SJinzhou Su 			return ret;
17283313ef18SJinzhou Su 		}
1729bb377febSJinzhou Su 	} else {
1730bb377febSJinzhou Su 		adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
1731bb377febSJinzhou Su 		dev_info(adev->dev, "If GFX DPM or power gate disabled, disable GFXOFF\n");
1732bb377febSJinzhou Su 	}
17333313ef18SJinzhou Su 
1734eefdf047SJinzhou Su 	/* if all CUs are active, no need to power off any WGPs */
1735eefdf047SJinzhou Su 	if (total_cu == adev->gfx.cu_info.number)
1736eefdf047SJinzhou Su 		return 0;
1737eefdf047SJinzhou Su 
1738eefdf047SJinzhou Su 	/*
1739eefdf047SJinzhou Su 	 * Calculate the total bits number of always on WGPs for all SA/SEs in
1740eefdf047SJinzhou Su 	 * RLC_PG_ALWAYS_ON_WGP_MASK.
1741eefdf047SJinzhou Su 	 */
1742eefdf047SJinzhou Su 	tmp = RREG32_KIQ(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_ALWAYS_ON_WGP_MASK));
1743eefdf047SJinzhou Su 	tmp &= RLC_PG_ALWAYS_ON_WGP_MASK__AON_WGP_MASK_MASK;
1744eefdf047SJinzhou Su 
1745eefdf047SJinzhou Su 	aon_bits = hweight32(tmp) * adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
1746eefdf047SJinzhou Su 
1747eefdf047SJinzhou Su 	/* Do not request any WGPs less than set in the AON_WGP_MASK */
1748eefdf047SJinzhou Su 	if (aon_bits > req_active_wgps) {
1749eefdf047SJinzhou Su 		dev_info(adev->dev, "Number of always on WGPs greater than active WGPs: WGP power save not requested.\n");
1750eefdf047SJinzhou Su 		return 0;
1751eefdf047SJinzhou Su 	} else {
1752eefdf047SJinzhou Su 		return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestActiveWgp, req_active_wgps, NULL);
1753eefdf047SJinzhou Su 	}
1754eefdf047SJinzhou Su }
1755eefdf047SJinzhou Su 
175674353883SHuang Rui static int vangogh_mode_reset(struct smu_context *smu, int type)
175774353883SHuang Rui {
175874353883SHuang Rui 	int ret = 0, index = 0;
175974353883SHuang Rui 
176074353883SHuang Rui 	index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG,
176174353883SHuang Rui 					       SMU_MSG_GfxDeviceDriverReset);
176274353883SHuang Rui 	if (index < 0)
176374353883SHuang Rui 		return index == -EACCES ? 0 : index;
176474353883SHuang Rui 
176574353883SHuang Rui 	mutex_lock(&smu->message_lock);
176674353883SHuang Rui 
176774353883SHuang Rui 	ret = smu_cmn_send_msg_without_waiting(smu, (uint16_t)index, type);
176874353883SHuang Rui 
176974353883SHuang Rui 	mutex_unlock(&smu->message_lock);
177074353883SHuang Rui 
177174353883SHuang Rui 	mdelay(10);
177274353883SHuang Rui 
177374353883SHuang Rui 	return ret;
177474353883SHuang Rui }
177574353883SHuang Rui 
177620e157c7SAlex Deucher static int vangogh_mode2_reset(struct smu_context *smu)
177720e157c7SAlex Deucher {
177874353883SHuang Rui 	return vangogh_mode_reset(smu, SMU_RESET_MODE_2);
177920e157c7SAlex Deucher }
178020e157c7SAlex Deucher 
1781ae07970aSXiaomeng Hou static int vangogh_get_power_limit(struct smu_context *smu)
1782ae07970aSXiaomeng Hou {
1783ae07970aSXiaomeng Hou 	struct smu_11_5_power_context *power_context =
1784ae07970aSXiaomeng Hou 								smu->smu_power.power_context;
1785ae07970aSXiaomeng Hou 	uint32_t ppt_limit;
1786ae07970aSXiaomeng Hou 	int ret = 0;
1787ae07970aSXiaomeng Hou 
1788ae07970aSXiaomeng Hou 	if (smu->adev->pm.fw_version < 0x43f1e00)
1789ae07970aSXiaomeng Hou 		return ret;
1790ae07970aSXiaomeng Hou 
1791ae07970aSXiaomeng Hou 	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSlowPPTLimit, &ppt_limit);
1792ae07970aSXiaomeng Hou 	if (ret) {
1793ae07970aSXiaomeng Hou 		dev_err(smu->adev->dev, "Get slow PPT limit failed!\n");
1794ae07970aSXiaomeng Hou 		return ret;
1795ae07970aSXiaomeng Hou 	}
1796ae07970aSXiaomeng Hou 	/* convert from milliwatt to watt */
1797ae07970aSXiaomeng Hou 	smu->current_power_limit = ppt_limit / 1000;
1798ae07970aSXiaomeng Hou 	smu->max_power_limit = 29;
1799ae07970aSXiaomeng Hou 
1800ae07970aSXiaomeng Hou 	ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetFastPPTLimit, &ppt_limit);
1801ae07970aSXiaomeng Hou 	if (ret) {
1802ae07970aSXiaomeng Hou 		dev_err(smu->adev->dev, "Get fast PPT limit failed!\n");
1803ae07970aSXiaomeng Hou 		return ret;
1804ae07970aSXiaomeng Hou 	}
1805ae07970aSXiaomeng Hou 	/* convert from milliwatt to watt */
1806ae07970aSXiaomeng Hou 	power_context->current_fast_ppt_limit = ppt_limit / 1000;
1807ae07970aSXiaomeng Hou 	power_context->max_fast_ppt_limit = 30;
1808ae07970aSXiaomeng Hou 
1809ae07970aSXiaomeng Hou 	return ret;
1810ae07970aSXiaomeng Hou }
1811ae07970aSXiaomeng Hou 
1812ae07970aSXiaomeng Hou static int vangogh_get_ppt_limit(struct smu_context *smu,
1813ae07970aSXiaomeng Hou 								uint32_t *ppt_limit,
1814ae07970aSXiaomeng Hou 								enum smu_ppt_limit_type type,
1815ae07970aSXiaomeng Hou 								enum smu_ppt_limit_level level)
1816ae07970aSXiaomeng Hou {
1817ae07970aSXiaomeng Hou 	struct smu_11_5_power_context *power_context =
1818ae07970aSXiaomeng Hou 							smu->smu_power.power_context;
1819ae07970aSXiaomeng Hou 
1820ae07970aSXiaomeng Hou 	if (!power_context)
1821ae07970aSXiaomeng Hou 		return -EOPNOTSUPP;
1822ae07970aSXiaomeng Hou 
1823ae07970aSXiaomeng Hou 	if (type == SMU_FAST_PPT_LIMIT) {
1824ae07970aSXiaomeng Hou 		switch (level) {
1825ae07970aSXiaomeng Hou 		case SMU_PPT_LIMIT_MAX:
1826ae07970aSXiaomeng Hou 			*ppt_limit = power_context->max_fast_ppt_limit;
1827ae07970aSXiaomeng Hou 			break;
1828ae07970aSXiaomeng Hou 		case SMU_PPT_LIMIT_CURRENT:
1829ae07970aSXiaomeng Hou 			*ppt_limit = power_context->current_fast_ppt_limit;
1830ae07970aSXiaomeng Hou 			break;
1831ae07970aSXiaomeng Hou 		default:
1832ae07970aSXiaomeng Hou 			break;
1833ae07970aSXiaomeng Hou 		}
1834ae07970aSXiaomeng Hou 	}
1835ae07970aSXiaomeng Hou 
1836ae07970aSXiaomeng Hou 	return 0;
1837ae07970aSXiaomeng Hou }
1838ae07970aSXiaomeng Hou 
1839ae07970aSXiaomeng Hou static int vangogh_set_power_limit(struct smu_context *smu, uint32_t ppt_limit)
1840ae07970aSXiaomeng Hou {
1841ae07970aSXiaomeng Hou 	struct smu_11_5_power_context *power_context =
1842ae07970aSXiaomeng Hou 							smu->smu_power.power_context;
1843ae07970aSXiaomeng Hou 	uint32_t limit_type = ppt_limit >> 24;
1844ae07970aSXiaomeng Hou 	int ret = 0;
1845ae07970aSXiaomeng Hou 
1846ae07970aSXiaomeng Hou 	if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
1847ae07970aSXiaomeng Hou 		dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
1848ae07970aSXiaomeng Hou 		return -EOPNOTSUPP;
1849ae07970aSXiaomeng Hou 	}
1850ae07970aSXiaomeng Hou 
1851ae07970aSXiaomeng Hou 	switch (limit_type) {
1852ae07970aSXiaomeng Hou 	case SMU_DEFAULT_PPT_LIMIT:
1853ae07970aSXiaomeng Hou 		ret = smu_cmn_send_smc_msg_with_param(smu,
1854ae07970aSXiaomeng Hou 				SMU_MSG_SetSlowPPTLimit,
1855ae07970aSXiaomeng Hou 				ppt_limit * 1000, /* convert from watt to milliwatt */
1856ae07970aSXiaomeng Hou 				NULL);
1857ae07970aSXiaomeng Hou 		if (ret)
1858ae07970aSXiaomeng Hou 			return ret;
1859ae07970aSXiaomeng Hou 
1860ae07970aSXiaomeng Hou 		smu->current_power_limit = ppt_limit;
1861ae07970aSXiaomeng Hou 		break;
1862ae07970aSXiaomeng Hou 	case SMU_FAST_PPT_LIMIT:
1863ae07970aSXiaomeng Hou 		ppt_limit &= ~(SMU_FAST_PPT_LIMIT << 24);
1864ae07970aSXiaomeng Hou 		if (ppt_limit > power_context->max_fast_ppt_limit) {
1865ae07970aSXiaomeng Hou 			dev_err(smu->adev->dev,
1866ae07970aSXiaomeng Hou 				"New power limit (%d) is over the max allowed %d\n",
1867ae07970aSXiaomeng Hou 				ppt_limit, power_context->max_fast_ppt_limit);
1868ae07970aSXiaomeng Hou 			return ret;
1869ae07970aSXiaomeng Hou 		}
1870ae07970aSXiaomeng Hou 
1871ae07970aSXiaomeng Hou 		ret = smu_cmn_send_smc_msg_with_param(smu,
1872ae07970aSXiaomeng Hou 				SMU_MSG_SetFastPPTLimit,
1873ae07970aSXiaomeng Hou 				ppt_limit * 1000, /* convert from watt to milliwatt */
1874ae07970aSXiaomeng Hou 				NULL);
1875ae07970aSXiaomeng Hou 		if (ret)
1876ae07970aSXiaomeng Hou 			return ret;
1877ae07970aSXiaomeng Hou 
1878ae07970aSXiaomeng Hou 		power_context->current_fast_ppt_limit = ppt_limit;
1879ae07970aSXiaomeng Hou 		break;
1880ae07970aSXiaomeng Hou 	default:
1881ae07970aSXiaomeng Hou 		return -EINVAL;
1882ae07970aSXiaomeng Hou 	}
1883ae07970aSXiaomeng Hou 
1884ae07970aSXiaomeng Hou 	return ret;
1885ae07970aSXiaomeng Hou }
1886ae07970aSXiaomeng Hou 
1887f46a221bSXiaojian Du static const struct pptable_funcs vangogh_ppt_funcs = {
1888271ab489SXiaojian Du 
1889f46a221bSXiaojian Du 	.check_fw_status = smu_v11_0_check_fw_status,
1890f46a221bSXiaojian Du 	.check_fw_version = smu_v11_0_check_fw_version,
1891f46a221bSXiaojian Du 	.init_smc_tables = vangogh_init_smc_tables,
1892f46a221bSXiaojian Du 	.fini_smc_tables = smu_v11_0_fini_smc_tables,
1893f46a221bSXiaojian Du 	.init_power = smu_v11_0_init_power,
1894f46a221bSXiaojian Du 	.fini_power = smu_v11_0_fini_power,
1895f46a221bSXiaojian Du 	.register_irq_handler = smu_v11_0_register_irq_handler,
1896f46a221bSXiaojian Du 	.notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
1897f46a221bSXiaojian Du 	.send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
1898f46a221bSXiaojian Du 	.send_smc_msg = smu_cmn_send_smc_msg,
1899271ab489SXiaojian Du 	.dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable,
1900271ab489SXiaojian Du 	.dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable,
1901f46a221bSXiaojian Du 	.is_dpm_running = vangogh_is_dpm_running,
1902271ab489SXiaojian Du 	.read_sensor = vangogh_read_sensor,
1903271ab489SXiaojian Du 	.get_enabled_mask = smu_cmn_get_enabled_32_bits_mask,
1904f46a221bSXiaojian Du 	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
1905271ab489SXiaojian Du 	.set_watermarks_table = vangogh_set_watermarks_table,
1906271ab489SXiaojian Du 	.set_driver_table_location = smu_v11_0_set_driver_table_location,
1907f46a221bSXiaojian Du 	.interrupt_work = smu_v11_0_interrupt_work,
1908fd253334SXiaojian Du 	.get_gpu_metrics = vangogh_get_gpu_metrics,
1909c98ee897SXiaojian Du 	.od_edit_dpm_table = vangogh_od_edit_dpm_table,
1910c98ee897SXiaojian Du 	.print_clk_levels = vangogh_print_fine_grain_clk,
1911c98ee897SXiaojian Du 	.set_default_dpm_table = vangogh_set_default_dpm_tables,
1912c98ee897SXiaojian Du 	.set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
1913a0f55287SXiaomeng Hou 	.system_features_control = vangogh_system_features_control,
1914d0e4e112SXiaojian Du 	.feature_is_enabled = smu_cmn_feature_is_enabled,
1915d0e4e112SXiaojian Du 	.set_power_profile_mode = vangogh_set_power_profile_mode,
1916307f049bSXiaojian Du 	.get_power_profile_mode = vangogh_get_power_profile_mode,
1917ae7b32e7SXiaojian Du 	.get_dpm_clock_table = vangogh_get_dpm_clock_table,
1918dd9e0b21SXiaojian Du 	.force_clk_levels = vangogh_force_clk_levels,
1919ea173d15SXiaojian Du 	.set_performance_level = vangogh_set_performance_level,
1920eefdf047SJinzhou Su 	.post_init = vangogh_post_smu_init,
192120e157c7SAlex Deucher 	.mode2_reset = vangogh_mode2_reset,
1922b58ce1feSJinzhou Su 	.gfx_off_control = smu_v11_0_gfx_off_control,
1923ae07970aSXiaomeng Hou 	.get_ppt_limit = vangogh_get_ppt_limit,
1924ae07970aSXiaomeng Hou 	.get_power_limit = vangogh_get_power_limit,
1925ae07970aSXiaomeng Hou 	.set_power_limit = vangogh_set_power_limit,
1926f46a221bSXiaojian Du };
1927f46a221bSXiaojian Du 
1928f46a221bSXiaojian Du void vangogh_set_ppt_funcs(struct smu_context *smu)
1929f46a221bSXiaojian Du {
1930f46a221bSXiaojian Du 	smu->ppt_funcs = &vangogh_ppt_funcs;
1931f46a221bSXiaojian Du 	smu->message_map = vangogh_message_map;
1932f46a221bSXiaojian Du 	smu->feature_map = vangogh_feature_mask_map;
1933f46a221bSXiaojian Du 	smu->table_map = vangogh_table_map;
1934ec3b35c8SXiaojian Du 	smu->workload_map = vangogh_workload_map;
1935f46a221bSXiaojian Du 	smu->is_apu = true;
1936f46a221bSXiaojian Du }
1937