1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "pp_debug.h"
24 #include <linux/delay.h>
25 #include <linux/fb.h>
26 #include <linux/module.h>
27 #include <linux/pci.h>
28 #include <linux/slab.h>
29 #include <asm/div64.h>
30 #if IS_ENABLED(CONFIG_X86_64)
31 #include <asm/intel-family.h>
32 #endif
33 #include <drm/amdgpu_drm.h>
34 #include "ppatomctrl.h"
35 #include "atombios.h"
36 #include "pptable_v1_0.h"
37 #include "pppcielanes.h"
38 #include "amd_pcie_helpers.h"
39 #include "hardwaremanager.h"
40 #include "process_pptables_v1_0.h"
41 #include "cgs_common.h"
42 
43 #include "smu7_common.h"
44 
45 #include "hwmgr.h"
46 #include "smu7_hwmgr.h"
47 #include "smu_ucode_xfer_vi.h"
48 #include "smu7_powertune.h"
49 #include "smu7_dyn_defaults.h"
50 #include "smu7_thermal.h"
51 #include "smu7_clockpowergating.h"
52 #include "processpptables.h"
53 #include "pp_thermal.h"
54 #include "smu7_baco.h"
55 #include "smu7_smumgr.h"
56 #include "polaris10_smumgr.h"
57 
58 #include "ivsrcid/ivsrcid_vislands30.h"
59 
60 #define MC_CG_ARB_FREQ_F0           0x0a
61 #define MC_CG_ARB_FREQ_F1           0x0b
62 #define MC_CG_ARB_FREQ_F2           0x0c
63 #define MC_CG_ARB_FREQ_F3           0x0d
64 
65 #define MC_CG_SEQ_DRAMCONF_S0       0x05
66 #define MC_CG_SEQ_DRAMCONF_S1       0x06
67 #define MC_CG_SEQ_YCLK_SUSPEND      0x04
68 #define MC_CG_SEQ_YCLK_RESUME       0x0a
69 
70 #define SMC_CG_IND_START            0xc0030000
71 #define SMC_CG_IND_END              0xc0040000
72 
73 #define MEM_FREQ_LOW_LATENCY        25000
74 #define MEM_FREQ_HIGH_LATENCY       80000
75 
76 #define MEM_LATENCY_HIGH            45
77 #define MEM_LATENCY_LOW             35
78 #define MEM_LATENCY_ERR             0xFFFF
79 
80 #define MC_SEQ_MISC0_GDDR5_SHIFT 28
81 #define MC_SEQ_MISC0_GDDR5_MASK  0xf0000000
82 #define MC_SEQ_MISC0_GDDR5_VALUE 5
83 
84 #define PCIE_BUS_CLK                10000
85 #define TCLK                        (PCIE_BUS_CLK / 10)
86 
87 static struct profile_mode_setting smu7_profiling[7] =
88 					{{0, 0, 0, 0, 0, 0, 0, 0},
89 					 {1, 0, 100, 30, 1, 0, 100, 10},
90 					 {1, 10, 0, 30, 0, 0, 0, 0},
91 					 {0, 0, 0, 0, 1, 10, 16, 31},
92 					 {1, 0, 11, 50, 1, 0, 100, 10},
93 					 {1, 0, 5, 30, 0, 0, 0, 0},
94 					 {0, 0, 0, 0, 0, 0, 0, 0},
95 					};
96 
97 #define PPSMC_MSG_SetVBITimeout_VEGAM    ((uint16_t) 0x310)
98 
99 #define ixPWR_SVI2_PLANE1_LOAD                     0xC0200280
100 #define PWR_SVI2_PLANE1_LOAD__PSI1_MASK                    0x00000020L
101 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN_MASK                 0x00000040L
102 #define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT                  0x00000005
103 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT               0x00000006
104 
105 #define STRAP_EVV_REVISION_MSB		2211
106 #define STRAP_EVV_REVISION_LSB		2208
107 
108 /** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
109 enum DPM_EVENT_SRC {
110 	DPM_EVENT_SRC_ANALOG = 0,
111 	DPM_EVENT_SRC_EXTERNAL = 1,
112 	DPM_EVENT_SRC_DIGITAL = 2,
113 	DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
114 	DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4
115 };
116 
117 #define ixDIDT_SQ_EDC_CTRL                         0x0013
118 #define ixDIDT_SQ_EDC_THRESHOLD                    0x0014
119 #define ixDIDT_SQ_EDC_STALL_PATTERN_1_2            0x0015
120 #define ixDIDT_SQ_EDC_STALL_PATTERN_3_4            0x0016
121 #define ixDIDT_SQ_EDC_STALL_PATTERN_5_6            0x0017
122 #define ixDIDT_SQ_EDC_STALL_PATTERN_7              0x0018
123 
124 #define ixDIDT_TD_EDC_CTRL                         0x0053
125 #define ixDIDT_TD_EDC_THRESHOLD                    0x0054
126 #define ixDIDT_TD_EDC_STALL_PATTERN_1_2            0x0055
127 #define ixDIDT_TD_EDC_STALL_PATTERN_3_4            0x0056
128 #define ixDIDT_TD_EDC_STALL_PATTERN_5_6            0x0057
129 #define ixDIDT_TD_EDC_STALL_PATTERN_7              0x0058
130 
131 #define ixDIDT_TCP_EDC_CTRL                        0x0073
132 #define ixDIDT_TCP_EDC_THRESHOLD                   0x0074
133 #define ixDIDT_TCP_EDC_STALL_PATTERN_1_2           0x0075
134 #define ixDIDT_TCP_EDC_STALL_PATTERN_3_4           0x0076
135 #define ixDIDT_TCP_EDC_STALL_PATTERN_5_6           0x0077
136 #define ixDIDT_TCP_EDC_STALL_PATTERN_7             0x0078
137 
138 #define ixDIDT_DB_EDC_CTRL                         0x0033
139 #define ixDIDT_DB_EDC_THRESHOLD                    0x0034
140 #define ixDIDT_DB_EDC_STALL_PATTERN_1_2            0x0035
141 #define ixDIDT_DB_EDC_STALL_PATTERN_3_4            0x0036
142 #define ixDIDT_DB_EDC_STALL_PATTERN_5_6            0x0037
143 #define ixDIDT_DB_EDC_STALL_PATTERN_7              0x0038
144 
145 uint32_t DIDTEDCConfig_P12[] = {
146     ixDIDT_SQ_EDC_STALL_PATTERN_1_2,
147     ixDIDT_SQ_EDC_STALL_PATTERN_3_4,
148     ixDIDT_SQ_EDC_STALL_PATTERN_5_6,
149     ixDIDT_SQ_EDC_STALL_PATTERN_7,
150     ixDIDT_SQ_EDC_THRESHOLD,
151     ixDIDT_SQ_EDC_CTRL,
152     ixDIDT_TD_EDC_STALL_PATTERN_1_2,
153     ixDIDT_TD_EDC_STALL_PATTERN_3_4,
154     ixDIDT_TD_EDC_STALL_PATTERN_5_6,
155     ixDIDT_TD_EDC_STALL_PATTERN_7,
156     ixDIDT_TD_EDC_THRESHOLD,
157     ixDIDT_TD_EDC_CTRL,
158     ixDIDT_TCP_EDC_STALL_PATTERN_1_2,
159     ixDIDT_TCP_EDC_STALL_PATTERN_3_4,
160     ixDIDT_TCP_EDC_STALL_PATTERN_5_6,
161     ixDIDT_TCP_EDC_STALL_PATTERN_7,
162     ixDIDT_TCP_EDC_THRESHOLD,
163     ixDIDT_TCP_EDC_CTRL,
164     ixDIDT_DB_EDC_STALL_PATTERN_1_2,
165     ixDIDT_DB_EDC_STALL_PATTERN_3_4,
166     ixDIDT_DB_EDC_STALL_PATTERN_5_6,
167     ixDIDT_DB_EDC_STALL_PATTERN_7,
168     ixDIDT_DB_EDC_THRESHOLD,
169     ixDIDT_DB_EDC_CTRL,
170     0xFFFFFFFF // End of list
171 };
172 
173 static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic);
174 static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
175 		enum pp_clock_type type, uint32_t mask);
176 static int smu7_notify_has_display(struct pp_hwmgr *hwmgr);
177 
178 static struct smu7_power_state *cast_phw_smu7_power_state(
179 				  struct pp_hw_power_state *hw_ps)
180 {
181 	PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
182 				"Invalid Powerstate Type!",
183 				 return NULL);
184 
185 	return (struct smu7_power_state *)hw_ps;
186 }
187 
188 static const struct smu7_power_state *cast_const_phw_smu7_power_state(
189 				 const struct pp_hw_power_state *hw_ps)
190 {
191 	PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
192 				"Invalid Powerstate Type!",
193 				 return NULL);
194 
195 	return (const struct smu7_power_state *)hw_ps;
196 }
197 
198 /**
199  * smu7_get_mc_microcode_version - Find the MC microcode version and store it in the HwMgr struct
200  *
201  * @hwmgr:  the address of the powerplay hardware manager.
202  * Return:   always 0
203  */
204 static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr)
205 {
206 	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
207 
208 	hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
209 
210 	return 0;
211 }
212 
213 static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
214 {
215 	uint32_t speedCntl = 0;
216 
217 	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
218 	speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE,
219 			ixPCIE_LC_SPEED_CNTL);
220 	return((uint16_t)PHM_GET_FIELD(speedCntl,
221 			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
222 }
223 
224 static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
225 {
226 	uint32_t link_width;
227 
228 	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
229 	link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
230 			PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD);
231 
232 	PP_ASSERT_WITH_CODE((7 >= link_width),
233 			"Invalid PCIe lane width!", return 0);
234 
235 	return decode_pcie_lane_width(link_width);
236 }
237 
238 /**
239  * smu7_enable_smc_voltage_controller - Enable voltage control
240  *
241  * @hwmgr:  the address of the powerplay hardware manager.
242  * Return:   always PP_Result_OK
243  */
244 static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
245 {
246 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
247 	    hwmgr->chip_id <= CHIP_VEGAM) {
248 		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
249 				CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0);
250 		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
251 				CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI0_EN, 0);
252 	}
253 
254 	if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK)
255 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable, NULL);
256 
257 	return 0;
258 }
259 
260 /**
261  * smu7_voltage_control - Checks if we want to support voltage control
262  *
263  * @hwmgr:  the address of the powerplay hardware manager.
264  */
265 static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr)
266 {
267 	const struct smu7_hwmgr *data =
268 			(const struct smu7_hwmgr *)(hwmgr->backend);
269 
270 	return (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control);
271 }
272 
273 /**
274  * smu7_enable_voltage_control - Enable voltage control
275  *
276  * @hwmgr:  the address of the powerplay hardware manager.
277  * Return:   always 0
278  */
279 static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr)
280 {
281 	/* enable voltage control */
282 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
283 			GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1);
284 
285 	return 0;
286 }
287 
288 static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_table,
289 		struct phm_clock_voltage_dependency_table *voltage_dependency_table
290 		)
291 {
292 	uint32_t i;
293 
294 	PP_ASSERT_WITH_CODE((NULL != voltage_table),
295 			"Voltage Dependency Table empty.", return -EINVAL;);
296 
297 	voltage_table->mask_low = 0;
298 	voltage_table->phase_delay = 0;
299 	voltage_table->count = voltage_dependency_table->count;
300 
301 	for (i = 0; i < voltage_dependency_table->count; i++) {
302 		voltage_table->entries[i].value =
303 			voltage_dependency_table->entries[i].v;
304 		voltage_table->entries[i].smio_low = 0;
305 	}
306 
307 	return 0;
308 }
309 
310 
311 /**
312  * smu7_construct_voltage_tables - Create Voltage Tables.
313  *
314  * @hwmgr:  the address of the powerplay hardware manager.
315  * Return:   always 0
316  */
317 static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr)
318 {
319 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
320 	struct phm_ppt_v1_information *table_info =
321 			(struct phm_ppt_v1_information *)hwmgr->pptable;
322 	int result = 0;
323 	uint32_t tmp;
324 
325 	if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
326 		result = atomctrl_get_voltage_table_v3(hwmgr,
327 				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT,
328 				&(data->mvdd_voltage_table));
329 		PP_ASSERT_WITH_CODE((0 == result),
330 				"Failed to retrieve MVDD table.",
331 				return result);
332 	} else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
333 		if (hwmgr->pp_table_version == PP_TABLE_V1)
334 			result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table),
335 					table_info->vdd_dep_on_mclk);
336 		else if (hwmgr->pp_table_version == PP_TABLE_V0)
337 			result = phm_get_svi2_voltage_table_v0(&(data->mvdd_voltage_table),
338 					hwmgr->dyn_state.mvdd_dependency_on_mclk);
339 
340 		PP_ASSERT_WITH_CODE((0 == result),
341 				"Failed to retrieve SVI2 MVDD table from dependency table.",
342 				return result;);
343 	}
344 
345 	if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
346 		result = atomctrl_get_voltage_table_v3(hwmgr,
347 				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT,
348 				&(data->vddci_voltage_table));
349 		PP_ASSERT_WITH_CODE((0 == result),
350 				"Failed to retrieve VDDCI table.",
351 				return result);
352 	} else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
353 		if (hwmgr->pp_table_version == PP_TABLE_V1)
354 			result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table),
355 					table_info->vdd_dep_on_mclk);
356 		else if (hwmgr->pp_table_version == PP_TABLE_V0)
357 			result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table),
358 					hwmgr->dyn_state.vddci_dependency_on_mclk);
359 		PP_ASSERT_WITH_CODE((0 == result),
360 				"Failed to retrieve SVI2 VDDCI table from dependency table.",
361 				return result);
362 	}
363 
364 	if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) {
365 		/* VDDGFX has only SVI2 voltage control */
366 		result = phm_get_svi2_vdd_voltage_table(&(data->vddgfx_voltage_table),
367 					table_info->vddgfx_lookup_table);
368 		PP_ASSERT_WITH_CODE((0 == result),
369 			"Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;);
370 	}
371 
372 
373 	if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) {
374 		result = atomctrl_get_voltage_table_v3(hwmgr,
375 					VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT,
376 					&data->vddc_voltage_table);
377 		PP_ASSERT_WITH_CODE((0 == result),
378 			"Failed to retrieve VDDC table.", return result;);
379 	} else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
380 
381 		if (hwmgr->pp_table_version == PP_TABLE_V0)
382 			result = phm_get_svi2_voltage_table_v0(&data->vddc_voltage_table,
383 					hwmgr->dyn_state.vddc_dependency_on_mclk);
384 		else if (hwmgr->pp_table_version == PP_TABLE_V1)
385 			result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table),
386 				table_info->vddc_lookup_table);
387 
388 		PP_ASSERT_WITH_CODE((0 == result),
389 			"Failed to retrieve SVI2 VDDC table from dependency table.", return result;);
390 	}
391 
392 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC);
393 	PP_ASSERT_WITH_CODE(
394 			(data->vddc_voltage_table.count <= tmp),
395 		"Too many voltage values for VDDC. Trimming to fit state table.",
396 			phm_trim_voltage_table_to_fit_state_table(tmp,
397 						&(data->vddc_voltage_table)));
398 
399 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX);
400 	PP_ASSERT_WITH_CODE(
401 			(data->vddgfx_voltage_table.count <= tmp),
402 		"Too many voltage values for VDDC. Trimming to fit state table.",
403 			phm_trim_voltage_table_to_fit_state_table(tmp,
404 						&(data->vddgfx_voltage_table)));
405 
406 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI);
407 	PP_ASSERT_WITH_CODE(
408 			(data->vddci_voltage_table.count <= tmp),
409 		"Too many voltage values for VDDCI. Trimming to fit state table.",
410 			phm_trim_voltage_table_to_fit_state_table(tmp,
411 					&(data->vddci_voltage_table)));
412 
413 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD);
414 	PP_ASSERT_WITH_CODE(
415 			(data->mvdd_voltage_table.count <= tmp),
416 		"Too many voltage values for MVDD. Trimming to fit state table.",
417 			phm_trim_voltage_table_to_fit_state_table(tmp,
418 						&(data->mvdd_voltage_table)));
419 
420 	return 0;
421 }
422 
423 /**
424  * smu7_program_static_screen_threshold_parameters - Programs static screed detection parameters
425  *
426  * @hwmgr:  the address of the powerplay hardware manager.
427  * Return:   always 0
428  */
429 static int smu7_program_static_screen_threshold_parameters(
430 							struct pp_hwmgr *hwmgr)
431 {
432 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
433 
434 	/* Set static screen threshold unit */
435 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
436 			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,
437 			data->static_screen_threshold_unit);
438 	/* Set static screen threshold */
439 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
440 			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
441 			data->static_screen_threshold);
442 
443 	return 0;
444 }
445 
446 /**
447  * smu7_enable_display_gap - Setup display gap for glitch free memory clock switching.
448  *
449  * @hwmgr:  the address of the powerplay hardware manager.
450  * Return:   always  0
451  */
452 static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr)
453 {
454 	uint32_t display_gap =
455 			cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
456 					ixCG_DISPLAY_GAP_CNTL);
457 
458 	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
459 			DISP_GAP, DISPLAY_GAP_IGNORE);
460 
461 	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
462 			DISP_GAP_MCHG, DISPLAY_GAP_VBLANK);
463 
464 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
465 			ixCG_DISPLAY_GAP_CNTL, display_gap);
466 
467 	return 0;
468 }
469 
470 /**
471  * smu7_program_voting_clients - Programs activity state transition voting clients
472  *
473  * @hwmgr:  the address of the powerplay hardware manager.
474  * Return:   always  0
475  */
476 static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr)
477 {
478 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
479 	int i;
480 
481 	/* Clear reset for voting clients before enabling DPM */
482 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
483 			SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0);
484 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
485 			SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0);
486 
487 	for (i = 0; i < 8; i++)
488 		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
489 					ixCG_FREQ_TRAN_VOTING_0 + i * 4,
490 					data->voting_rights_clients[i]);
491 	return 0;
492 }
493 
494 static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr)
495 {
496 	int i;
497 
498 	/* Reset voting clients before disabling DPM */
499 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
500 			SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1);
501 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
502 			SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1);
503 
504 	for (i = 0; i < 8; i++)
505 		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
506 				ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0);
507 
508 	return 0;
509 }
510 
511 /* Copy one arb setting to another and then switch the active set.
512  * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants.
513  */
514 static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
515 		uint32_t arb_src, uint32_t arb_dest)
516 {
517 	uint32_t mc_arb_dram_timing;
518 	uint32_t mc_arb_dram_timing2;
519 	uint32_t burst_time;
520 	uint32_t mc_cg_config;
521 
522 	switch (arb_src) {
523 	case MC_CG_ARB_FREQ_F0:
524 		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
525 		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
526 		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
527 		break;
528 	case MC_CG_ARB_FREQ_F1:
529 		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1);
530 		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1);
531 		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1);
532 		break;
533 	default:
534 		return -EINVAL;
535 	}
536 
537 	switch (arb_dest) {
538 	case MC_CG_ARB_FREQ_F0:
539 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
540 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
541 		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time);
542 		break;
543 	case MC_CG_ARB_FREQ_F1:
544 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
545 		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
546 		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time);
547 		break;
548 	default:
549 		return -EINVAL;
550 	}
551 
552 	mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
553 	mc_cg_config |= 0x0000000F;
554 	cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
555 	PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest);
556 
557 	return 0;
558 }
559 
560 static int smu7_reset_to_default(struct pp_hwmgr *hwmgr)
561 {
562 	return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults, NULL);
563 }
564 
565 /**
566  * smu7_initial_switch_from_arbf0_to_f1 - Initial switch from ARB F0->F1
567  *
568  * @hwmgr:  the address of the powerplay hardware manager.
569  * Return:   always 0
570  * This function is to be called from the SetPowerState table.
571  */
572 static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr)
573 {
574 	return smu7_copy_and_switch_arb_sets(hwmgr,
575 			MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
576 }
577 
578 static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr)
579 {
580 	uint32_t tmp;
581 
582 	tmp = (cgs_read_ind_register(hwmgr->device,
583 			CGS_IND_REG__SMC, ixSMC_SCRATCH9) &
584 			0x0000ff00) >> 8;
585 
586 	if (tmp == MC_CG_ARB_FREQ_F0)
587 		return 0;
588 
589 	return smu7_copy_and_switch_arb_sets(hwmgr,
590 			tmp, MC_CG_ARB_FREQ_F0);
591 }
592 
593 static uint16_t smu7_override_pcie_speed(struct pp_hwmgr *hwmgr)
594 {
595 	struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
596 	uint16_t pcie_gen = 0;
597 
598 	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4 &&
599 	    adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4)
600 		pcie_gen = 3;
601 	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 &&
602 		adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3)
603 		pcie_gen = 2;
604 	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 &&
605 		adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2)
606 		pcie_gen = 1;
607 	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 &&
608 		adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1)
609 		pcie_gen = 0;
610 
611 	return pcie_gen;
612 }
613 
614 static uint16_t smu7_override_pcie_width(struct pp_hwmgr *hwmgr)
615 {
616 	struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
617 	uint16_t pcie_width = 0;
618 
619 	if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
620 		pcie_width = 16;
621 	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
622 		pcie_width = 12;
623 	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
624 		pcie_width = 8;
625 	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
626 		pcie_width = 4;
627 	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
628 		pcie_width = 2;
629 	else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
630 		pcie_width = 1;
631 
632 	return pcie_width;
633 }
634 
635 static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
636 {
637 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
638 
639 	struct phm_ppt_v1_information *table_info =
640 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
641 	struct phm_ppt_v1_pcie_table *pcie_table = NULL;
642 
643 	uint32_t i, max_entry;
644 	uint32_t tmp;
645 
646 	PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels ||
647 			data->use_pcie_power_saving_levels), "No pcie performance levels!",
648 			return -EINVAL);
649 
650 	if (table_info != NULL)
651 		pcie_table = table_info->pcie_table;
652 
653 	if (data->use_pcie_performance_levels &&
654 			!data->use_pcie_power_saving_levels) {
655 		data->pcie_gen_power_saving = data->pcie_gen_performance;
656 		data->pcie_lane_power_saving = data->pcie_lane_performance;
657 	} else if (!data->use_pcie_performance_levels &&
658 			data->use_pcie_power_saving_levels) {
659 		data->pcie_gen_performance = data->pcie_gen_power_saving;
660 		data->pcie_lane_performance = data->pcie_lane_power_saving;
661 	}
662 	tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK);
663 	phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table,
664 					tmp,
665 					MAX_REGULAR_DPM_NUMBER);
666 
667 	if (pcie_table != NULL) {
668 		/* max_entry is used to make sure we reserve one PCIE level
669 		 * for boot level (fix for A+A PSPP issue).
670 		 * If PCIE table from PPTable have ULV entry + 8 entries,
671 		 * then ignore the last entry.*/
672 		max_entry = (tmp < pcie_table->count) ? tmp : pcie_table->count;
673 		for (i = 1; i < max_entry; i++) {
674 			phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1,
675 					get_pcie_gen_support(data->pcie_gen_cap,
676 							pcie_table->entries[i].gen_speed),
677 					get_pcie_lane_support(data->pcie_lane_cap,
678 							pcie_table->entries[i].lane_width));
679 		}
680 		data->dpm_table.pcie_speed_table.count = max_entry - 1;
681 		smum_update_smc_table(hwmgr, SMU_BIF_TABLE);
682 	} else {
683 		/* Hardcode Pcie Table */
684 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
685 				get_pcie_gen_support(data->pcie_gen_cap,
686 						PP_Min_PCIEGen),
687 				get_pcie_lane_support(data->pcie_lane_cap,
688 						PP_Max_PCIELane));
689 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
690 				get_pcie_gen_support(data->pcie_gen_cap,
691 						PP_Min_PCIEGen),
692 				get_pcie_lane_support(data->pcie_lane_cap,
693 						PP_Max_PCIELane));
694 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
695 				get_pcie_gen_support(data->pcie_gen_cap,
696 						PP_Max_PCIEGen),
697 				get_pcie_lane_support(data->pcie_lane_cap,
698 						PP_Max_PCIELane));
699 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
700 				get_pcie_gen_support(data->pcie_gen_cap,
701 						PP_Max_PCIEGen),
702 				get_pcie_lane_support(data->pcie_lane_cap,
703 						PP_Max_PCIELane));
704 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
705 				get_pcie_gen_support(data->pcie_gen_cap,
706 						PP_Max_PCIEGen),
707 				get_pcie_lane_support(data->pcie_lane_cap,
708 						PP_Max_PCIELane));
709 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
710 				get_pcie_gen_support(data->pcie_gen_cap,
711 						PP_Max_PCIEGen),
712 				get_pcie_lane_support(data->pcie_lane_cap,
713 						PP_Max_PCIELane));
714 
715 		data->dpm_table.pcie_speed_table.count = 6;
716 	}
717 	/* Populate last level for boot PCIE level, but do not increment count. */
718 	if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
719 		for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++)
720 			phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i,
721 				get_pcie_gen_support(data->pcie_gen_cap,
722 						PP_Max_PCIEGen),
723 				data->vbios_boot_state.pcie_lane_bootup_value);
724 	} else {
725 		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
726 			data->dpm_table.pcie_speed_table.count,
727 			get_pcie_gen_support(data->pcie_gen_cap,
728 					PP_Min_PCIEGen),
729 			get_pcie_lane_support(data->pcie_lane_cap,
730 					PP_Max_PCIELane));
731 
732 		if (data->pcie_dpm_key_disabled)
733 			phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
734 				data->dpm_table.pcie_speed_table.count,
735 				smu7_override_pcie_speed(hwmgr), smu7_override_pcie_width(hwmgr));
736 	}
737 	return 0;
738 }
739 
740 static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr)
741 {
742 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
743 
744 	memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table));
745 
746 	phm_reset_single_dpm_table(
747 			&data->dpm_table.sclk_table,
748 				smum_get_mac_definition(hwmgr,
749 					SMU_MAX_LEVELS_GRAPHICS),
750 					MAX_REGULAR_DPM_NUMBER);
751 	phm_reset_single_dpm_table(
752 			&data->dpm_table.mclk_table,
753 			smum_get_mac_definition(hwmgr,
754 				SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER);
755 
756 	phm_reset_single_dpm_table(
757 			&data->dpm_table.vddc_table,
758 				smum_get_mac_definition(hwmgr,
759 					SMU_MAX_LEVELS_VDDC),
760 					MAX_REGULAR_DPM_NUMBER);
761 	phm_reset_single_dpm_table(
762 			&data->dpm_table.vddci_table,
763 			smum_get_mac_definition(hwmgr,
764 				SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER);
765 
766 	phm_reset_single_dpm_table(
767 			&data->dpm_table.mvdd_table,
768 				smum_get_mac_definition(hwmgr,
769 					SMU_MAX_LEVELS_MVDD),
770 					MAX_REGULAR_DPM_NUMBER);
771 	return 0;
772 }
773 /*
774  * This function is to initialize all DPM state tables
775  * for SMU7 based on the dependency table.
776  * Dynamic state patching function will then trim these
777  * state tables to the allowed range based
778  * on the power policy or external client requests,
779  * such as UVD request, etc.
780  */
781 
782 static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr)
783 {
784 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
785 	struct phm_clock_voltage_dependency_table *allowed_vdd_sclk_table =
786 		hwmgr->dyn_state.vddc_dependency_on_sclk;
787 	struct phm_clock_voltage_dependency_table *allowed_vdd_mclk_table =
788 		hwmgr->dyn_state.vddc_dependency_on_mclk;
789 	struct phm_cac_leakage_table *std_voltage_table =
790 		hwmgr->dyn_state.cac_leakage_table;
791 	uint32_t i;
792 
793 	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL,
794 		"SCLK dependency table is missing. This table is mandatory", return -EINVAL);
795 	PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1,
796 		"SCLK dependency table has to have is missing. This table is mandatory", return -EINVAL);
797 
798 	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
799 		"MCLK dependency table is missing. This table is mandatory", return -EINVAL);
800 	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1,
801 		"VMCLK dependency table has to have is missing. This table is mandatory", return -EINVAL);
802 
803 
804 	/* Initialize Sclk DPM table based on allow Sclk values*/
805 	data->dpm_table.sclk_table.count = 0;
806 
807 	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
808 		if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value !=
809 				allowed_vdd_sclk_table->entries[i].clk) {
810 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
811 				allowed_vdd_sclk_table->entries[i].clk;
812 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0;
813 			data->dpm_table.sclk_table.count++;
814 		}
815 	}
816 
817 	PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL,
818 		"MCLK dependency table is missing. This table is mandatory", return -EINVAL);
819 	/* Initialize Mclk DPM table based on allow Mclk values */
820 	data->dpm_table.mclk_table.count = 0;
821 	for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
822 		if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value !=
823 			allowed_vdd_mclk_table->entries[i].clk) {
824 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
825 				allowed_vdd_mclk_table->entries[i].clk;
826 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0;
827 			data->dpm_table.mclk_table.count++;
828 		}
829 	}
830 
831 	/* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */
832 	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
833 		data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
834 		data->dpm_table.vddc_table.dpm_levels[i].param1 = std_voltage_table->entries[i].Leakage;
835 		/* param1 is for corresponding std voltage */
836 		data->dpm_table.vddc_table.dpm_levels[i].enabled = true;
837 	}
838 
839 	data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
840 	allowed_vdd_mclk_table = hwmgr->dyn_state.vddci_dependency_on_mclk;
841 
842 	if (NULL != allowed_vdd_mclk_table) {
843 		/* Initialize Vddci DPM table based on allow Mclk values */
844 		for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
845 			data->dpm_table.vddci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
846 			data->dpm_table.vddci_table.dpm_levels[i].enabled = true;
847 		}
848 		data->dpm_table.vddci_table.count = allowed_vdd_mclk_table->count;
849 	}
850 
851 	allowed_vdd_mclk_table = hwmgr->dyn_state.mvdd_dependency_on_mclk;
852 
853 	if (NULL != allowed_vdd_mclk_table) {
854 		/*
855 		 * Initialize MVDD DPM table based on allow Mclk
856 		 * values
857 		 */
858 		for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
859 			data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v;
860 			data->dpm_table.mvdd_table.dpm_levels[i].enabled = true;
861 		}
862 		data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
863 	}
864 
865 	return 0;
866 }
867 
868 static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr)
869 {
870 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
871 	struct phm_ppt_v1_information *table_info =
872 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
873 	uint32_t i;
874 
875 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
876 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
877 
878 	if (table_info == NULL)
879 		return -EINVAL;
880 
881 	dep_sclk_table = table_info->vdd_dep_on_sclk;
882 	dep_mclk_table = table_info->vdd_dep_on_mclk;
883 
884 	PP_ASSERT_WITH_CODE(dep_sclk_table != NULL,
885 			"SCLK dependency table is missing.",
886 			return -EINVAL);
887 	PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1,
888 			"SCLK dependency table count is 0.",
889 			return -EINVAL);
890 
891 	PP_ASSERT_WITH_CODE(dep_mclk_table != NULL,
892 			"MCLK dependency table is missing.",
893 			return -EINVAL);
894 	PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
895 			"MCLK dependency table count is 0",
896 			return -EINVAL);
897 
898 	/* Initialize Sclk DPM table based on allow Sclk values */
899 	data->dpm_table.sclk_table.count = 0;
900 	for (i = 0; i < dep_sclk_table->count; i++) {
901 		if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value !=
902 						dep_sclk_table->entries[i].clk) {
903 
904 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
905 					dep_sclk_table->entries[i].clk;
906 
907 			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled =
908 					(i == 0) ? true : false;
909 			data->dpm_table.sclk_table.count++;
910 		}
911 	}
912 	if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
913 		hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk;
914 	/* Initialize Mclk DPM table based on allow Mclk values */
915 	data->dpm_table.mclk_table.count = 0;
916 	for (i = 0; i < dep_mclk_table->count; i++) {
917 		if (i == 0 || data->dpm_table.mclk_table.dpm_levels
918 				[data->dpm_table.mclk_table.count - 1].value !=
919 						dep_mclk_table->entries[i].clk) {
920 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
921 							dep_mclk_table->entries[i].clk;
922 			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled =
923 							(i == 0) ? true : false;
924 			data->dpm_table.mclk_table.count++;
925 		}
926 	}
927 
928 	if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
929 		hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk;
930 	return 0;
931 }
932 
933 static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
934 {
935 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
936 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
937 	struct phm_ppt_v1_information *table_info =
938 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
939 	uint32_t i;
940 
941 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
942 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
943 	struct phm_odn_performance_level *entries;
944 
945 	if (table_info == NULL)
946 		return -EINVAL;
947 
948 	dep_sclk_table = table_info->vdd_dep_on_sclk;
949 	dep_mclk_table = table_info->vdd_dep_on_mclk;
950 
951 	odn_table->odn_core_clock_dpm_levels.num_of_pl =
952 						data->golden_dpm_table.sclk_table.count;
953 	entries = odn_table->odn_core_clock_dpm_levels.entries;
954 	for (i=0; i<data->golden_dpm_table.sclk_table.count; i++) {
955 		entries[i].clock = data->golden_dpm_table.sclk_table.dpm_levels[i].value;
956 		entries[i].enabled = true;
957 		entries[i].vddc = dep_sclk_table->entries[i].vddc;
958 	}
959 
960 	smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table,
961 		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk));
962 
963 	odn_table->odn_memory_clock_dpm_levels.num_of_pl =
964 						data->golden_dpm_table.mclk_table.count;
965 	entries = odn_table->odn_memory_clock_dpm_levels.entries;
966 	for (i=0; i<data->golden_dpm_table.mclk_table.count; i++) {
967 		entries[i].clock = data->golden_dpm_table.mclk_table.dpm_levels[i].value;
968 		entries[i].enabled = true;
969 		entries[i].vddc = dep_mclk_table->entries[i].vddc;
970 	}
971 
972 	smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table,
973 		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk));
974 
975 	return 0;
976 }
977 
978 static void smu7_setup_voltage_range_from_vbios(struct pp_hwmgr *hwmgr)
979 {
980 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
981 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
982 	struct phm_ppt_v1_information *table_info =
983 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
984 	uint32_t min_vddc = 0;
985 	uint32_t max_vddc = 0;
986 
987 	if (!table_info)
988 		return;
989 
990 	dep_sclk_table = table_info->vdd_dep_on_sclk;
991 
992 	atomctrl_get_voltage_range(hwmgr, &max_vddc, &min_vddc);
993 
994 	if (min_vddc == 0 || min_vddc > 2000
995 		|| min_vddc > dep_sclk_table->entries[0].vddc)
996 		min_vddc = dep_sclk_table->entries[0].vddc;
997 
998 	if (max_vddc == 0 || max_vddc > 2000
999 		|| max_vddc < dep_sclk_table->entries[dep_sclk_table->count-1].vddc)
1000 		max_vddc = dep_sclk_table->entries[dep_sclk_table->count-1].vddc;
1001 
1002 	data->odn_dpm_table.min_vddc = min_vddc;
1003 	data->odn_dpm_table.max_vddc = max_vddc;
1004 }
1005 
1006 static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
1007 {
1008 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1009 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
1010 	struct phm_ppt_v1_information *table_info =
1011 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1012 	uint32_t i;
1013 
1014 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
1015 	struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
1016 
1017 	if (table_info == NULL)
1018 		return;
1019 
1020 	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
1021 		if (odn_table->odn_core_clock_dpm_levels.entries[i].clock !=
1022 					data->dpm_table.sclk_table.dpm_levels[i].value) {
1023 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
1024 			break;
1025 		}
1026 	}
1027 
1028 	for (i = 0; i < data->dpm_table.mclk_table.count; i++) {
1029 		if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock !=
1030 					data->dpm_table.mclk_table.dpm_levels[i].value) {
1031 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
1032 			break;
1033 		}
1034 	}
1035 
1036 	dep_table = table_info->vdd_dep_on_mclk;
1037 	odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk);
1038 
1039 	for (i = 0; i < dep_table->count; i++) {
1040 		if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
1041 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK;
1042 			return;
1043 		}
1044 	}
1045 
1046 	dep_table = table_info->vdd_dep_on_sclk;
1047 	odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk);
1048 	for (i = 0; i < dep_table->count; i++) {
1049 		if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
1050 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK;
1051 			return;
1052 		}
1053 	}
1054 	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
1055 		data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC;
1056 		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK;
1057 	}
1058 }
1059 
1060 static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1061 {
1062 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1063 
1064 	smu7_reset_dpm_tables(hwmgr);
1065 
1066 	if (hwmgr->pp_table_version == PP_TABLE_V1)
1067 		smu7_setup_dpm_tables_v1(hwmgr);
1068 	else if (hwmgr->pp_table_version == PP_TABLE_V0)
1069 		smu7_setup_dpm_tables_v0(hwmgr);
1070 
1071 	smu7_setup_default_pcie_table(hwmgr);
1072 
1073 	/* save a copy of the default DPM table */
1074 	memcpy(&(data->golden_dpm_table), &(data->dpm_table),
1075 			sizeof(struct smu7_dpm_table));
1076 
1077 	/* initialize ODN table */
1078 	if (hwmgr->od_enabled) {
1079 		if (data->odn_dpm_table.max_vddc) {
1080 			smu7_check_dpm_table_updated(hwmgr);
1081 		} else {
1082 			smu7_setup_voltage_range_from_vbios(hwmgr);
1083 			smu7_odn_initial_default_setting(hwmgr);
1084 		}
1085 	}
1086 	return 0;
1087 }
1088 
1089 static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr)
1090 {
1091 
1092 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1093 			PHM_PlatformCaps_RegulatorHot))
1094 		return smum_send_msg_to_smc(hwmgr,
1095 				PPSMC_MSG_EnableVRHotGPIOInterrupt,
1096 				NULL);
1097 
1098 	return 0;
1099 }
1100 
1101 static int smu7_enable_sclk_control(struct pp_hwmgr *hwmgr)
1102 {
1103 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
1104 			SCLK_PWRMGT_OFF, 0);
1105 	return 0;
1106 }
1107 
1108 static int smu7_enable_ulv(struct pp_hwmgr *hwmgr)
1109 {
1110 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1111 
1112 	if (data->ulv_supported)
1113 		return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV, NULL);
1114 
1115 	return 0;
1116 }
1117 
1118 static int smu7_disable_ulv(struct pp_hwmgr *hwmgr)
1119 {
1120 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1121 
1122 	if (data->ulv_supported)
1123 		return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV, NULL);
1124 
1125 	return 0;
1126 }
1127 
1128 static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
1129 {
1130 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1131 			PHM_PlatformCaps_SclkDeepSleep)) {
1132 		if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON, NULL))
1133 			PP_ASSERT_WITH_CODE(false,
1134 					"Attempt to enable Master Deep Sleep switch failed!",
1135 					return -EINVAL);
1136 	} else {
1137 		if (smum_send_msg_to_smc(hwmgr,
1138 				PPSMC_MSG_MASTER_DeepSleep_OFF,
1139 				NULL)) {
1140 			PP_ASSERT_WITH_CODE(false,
1141 					"Attempt to disable Master Deep Sleep switch failed!",
1142 					return -EINVAL);
1143 		}
1144 	}
1145 
1146 	return 0;
1147 }
1148 
1149 static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
1150 {
1151 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1152 			PHM_PlatformCaps_SclkDeepSleep)) {
1153 		if (smum_send_msg_to_smc(hwmgr,
1154 				PPSMC_MSG_MASTER_DeepSleep_OFF,
1155 				NULL)) {
1156 			PP_ASSERT_WITH_CODE(false,
1157 					"Attempt to disable Master Deep Sleep switch failed!",
1158 					return -EINVAL);
1159 		}
1160 	}
1161 
1162 	return 0;
1163 }
1164 
1165 static int smu7_disable_sclk_vce_handshake(struct pp_hwmgr *hwmgr)
1166 {
1167 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1168 	uint32_t soft_register_value = 0;
1169 	uint32_t handshake_disables_offset = data->soft_regs_start
1170 				+ smum_get_offsetof(hwmgr,
1171 					SMU_SoftRegisters, HandshakeDisables);
1172 
1173 	soft_register_value = cgs_read_ind_register(hwmgr->device,
1174 				CGS_IND_REG__SMC, handshake_disables_offset);
1175 	soft_register_value |= SMU7_VCE_SCLK_HANDSHAKE_DISABLE;
1176 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1177 			handshake_disables_offset, soft_register_value);
1178 	return 0;
1179 }
1180 
1181 static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr)
1182 {
1183 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1184 	uint32_t soft_register_value = 0;
1185 	uint32_t handshake_disables_offset = data->soft_regs_start
1186 				+ smum_get_offsetof(hwmgr,
1187 					SMU_SoftRegisters, HandshakeDisables);
1188 
1189 	soft_register_value = cgs_read_ind_register(hwmgr->device,
1190 				CGS_IND_REG__SMC, handshake_disables_offset);
1191 	soft_register_value |= smum_get_mac_definition(hwmgr,
1192 					SMU_UVD_MCLK_HANDSHAKE_DISABLE);
1193 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1194 			handshake_disables_offset, soft_register_value);
1195 	return 0;
1196 }
1197 
1198 static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
1199 {
1200 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1201 
1202 	/* enable SCLK dpm */
1203 	if (!data->sclk_dpm_key_disabled) {
1204 		if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1205 		    hwmgr->chip_id <= CHIP_VEGAM)
1206 			smu7_disable_sclk_vce_handshake(hwmgr);
1207 
1208 		PP_ASSERT_WITH_CODE(
1209 		(0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable, NULL)),
1210 		"Failed to enable SCLK DPM during DPM Start Function!",
1211 		return -EINVAL);
1212 	}
1213 
1214 	/* enable MCLK dpm */
1215 	if (0 == data->mclk_dpm_key_disabled) {
1216 		if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK))
1217 			smu7_disable_handshake_uvd(hwmgr);
1218 
1219 		PP_ASSERT_WITH_CODE(
1220 				(0 == smum_send_msg_to_smc(hwmgr,
1221 						PPSMC_MSG_MCLKDPM_Enable,
1222 						NULL)),
1223 				"Failed to enable MCLK DPM during DPM Start Function!",
1224 				return -EINVAL);
1225 
1226 		if ((hwmgr->chip_family == AMDGPU_FAMILY_CI) ||
1227 		    (hwmgr->chip_id == CHIP_POLARIS10) ||
1228 		    (hwmgr->chip_id == CHIP_POLARIS11) ||
1229 		    (hwmgr->chip_id == CHIP_POLARIS12) ||
1230 		    (hwmgr->chip_id == CHIP_TONGA) ||
1231 		    (hwmgr->chip_id == CHIP_TOPAZ))
1232 			PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
1233 
1234 
1235 		if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
1236 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5);
1237 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5);
1238 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005);
1239 			udelay(10);
1240 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005);
1241 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005);
1242 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005);
1243 		} else {
1244 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5);
1245 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5);
1246 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005);
1247 			udelay(10);
1248 			if (hwmgr->chip_id == CHIP_VEGAM) {
1249 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400009);
1250 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400009);
1251 			} else {
1252 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005);
1253 				cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005);
1254 			}
1255 			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005);
1256 		}
1257 	}
1258 
1259 	return 0;
1260 }
1261 
1262 static int smu7_start_dpm(struct pp_hwmgr *hwmgr)
1263 {
1264 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1265 
1266 	/*enable general power management */
1267 
1268 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1269 			GLOBAL_PWRMGT_EN, 1);
1270 
1271 	/* enable sclk deep sleep */
1272 
1273 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
1274 			DYNAMIC_PM_EN, 1);
1275 
1276 	/* prepare for PCIE DPM */
1277 
1278 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
1279 			data->soft_regs_start +
1280 			smum_get_offsetof(hwmgr, SMU_SoftRegisters,
1281 						VoltageChangeTimeout), 0x1000);
1282 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
1283 			SWRST_COMMAND_1, RESETLC, 0x0);
1284 
1285 	if (hwmgr->chip_family == AMDGPU_FAMILY_CI)
1286 		cgs_write_register(hwmgr->device, 0x1488,
1287 			(cgs_read_register(hwmgr->device, 0x1488) & ~0x1));
1288 
1289 	if (smu7_enable_sclk_mclk_dpm(hwmgr)) {
1290 		pr_err("Failed to enable Sclk DPM and Mclk DPM!");
1291 		return -EINVAL;
1292 	}
1293 
1294 	/* enable PCIE dpm */
1295 	if (0 == data->pcie_dpm_key_disabled) {
1296 		PP_ASSERT_WITH_CODE(
1297 				(0 == smum_send_msg_to_smc(hwmgr,
1298 						PPSMC_MSG_PCIeDPM_Enable,
1299 						NULL)),
1300 				"Failed to enable pcie DPM during DPM Start Function!",
1301 				return -EINVAL);
1302 	} else {
1303 		PP_ASSERT_WITH_CODE(
1304 				(0 == smum_send_msg_to_smc(hwmgr,
1305 						PPSMC_MSG_PCIeDPM_Disable,
1306 						NULL)),
1307 				"Failed to disable pcie DPM during DPM Start Function!",
1308 				return -EINVAL);
1309 	}
1310 
1311 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1312 				PHM_PlatformCaps_Falcon_QuickTransition)) {
1313 		PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr,
1314 				PPSMC_MSG_EnableACDCGPIOInterrupt,
1315 				NULL)),
1316 				"Failed to enable AC DC GPIO Interrupt!",
1317 				);
1318 	}
1319 
1320 	return 0;
1321 }
1322 
1323 static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
1324 {
1325 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1326 
1327 	/* disable SCLK dpm */
1328 	if (!data->sclk_dpm_key_disabled) {
1329 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
1330 				"Trying to disable SCLK DPM when DPM is disabled",
1331 				return 0);
1332 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable, NULL);
1333 	}
1334 
1335 	/* disable MCLK dpm */
1336 	if (!data->mclk_dpm_key_disabled) {
1337 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
1338 				"Trying to disable MCLK DPM when DPM is disabled",
1339 				return 0);
1340 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable, NULL);
1341 	}
1342 
1343 	return 0;
1344 }
1345 
1346 static int smu7_stop_dpm(struct pp_hwmgr *hwmgr)
1347 {
1348 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1349 
1350 	/* disable general power management */
1351 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1352 			GLOBAL_PWRMGT_EN, 0);
1353 	/* disable sclk deep sleep */
1354 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
1355 			DYNAMIC_PM_EN, 0);
1356 
1357 	/* disable PCIE dpm */
1358 	if (!data->pcie_dpm_key_disabled) {
1359 		PP_ASSERT_WITH_CODE(
1360 				(smum_send_msg_to_smc(hwmgr,
1361 						PPSMC_MSG_PCIeDPM_Disable,
1362 						NULL) == 0),
1363 				"Failed to disable pcie DPM during DPM Stop Function!",
1364 				return -EINVAL);
1365 	}
1366 
1367 	smu7_disable_sclk_mclk_dpm(hwmgr);
1368 
1369 	PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
1370 			"Trying to disable voltage DPM when DPM is disabled",
1371 			return 0);
1372 
1373 	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable, NULL);
1374 
1375 	return 0;
1376 }
1377 
1378 static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources)
1379 {
1380 	bool protection;
1381 	enum DPM_EVENT_SRC src;
1382 
1383 	switch (sources) {
1384 	default:
1385 		pr_err("Unknown throttling event sources.");
1386 		fallthrough;
1387 	case 0:
1388 		protection = false;
1389 		/* src is unused */
1390 		break;
1391 	case (1 << PHM_AutoThrottleSource_Thermal):
1392 		protection = true;
1393 		src = DPM_EVENT_SRC_DIGITAL;
1394 		break;
1395 	case (1 << PHM_AutoThrottleSource_External):
1396 		protection = true;
1397 		src = DPM_EVENT_SRC_EXTERNAL;
1398 		break;
1399 	case (1 << PHM_AutoThrottleSource_External) |
1400 			(1 << PHM_AutoThrottleSource_Thermal):
1401 		protection = true;
1402 		src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL;
1403 		break;
1404 	}
1405 	/* Order matters - don't enable thermal protection for the wrong source. */
1406 	if (protection) {
1407 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL,
1408 				DPM_EVENT_SRC, src);
1409 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1410 				THERMAL_PROTECTION_DIS,
1411 				!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1412 						PHM_PlatformCaps_ThermalController));
1413 	} else
1414 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
1415 				THERMAL_PROTECTION_DIS, 1);
1416 }
1417 
1418 static int smu7_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
1419 		PHM_AutoThrottleSource source)
1420 {
1421 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1422 
1423 	if (!(data->active_auto_throttle_sources & (1 << source))) {
1424 		data->active_auto_throttle_sources |= 1 << source;
1425 		smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
1426 	}
1427 	return 0;
1428 }
1429 
1430 static int smu7_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
1431 {
1432 	return smu7_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
1433 }
1434 
1435 static int smu7_disable_auto_throttle_source(struct pp_hwmgr *hwmgr,
1436 		PHM_AutoThrottleSource source)
1437 {
1438 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1439 
1440 	if (data->active_auto_throttle_sources & (1 << source)) {
1441 		data->active_auto_throttle_sources &= ~(1 << source);
1442 		smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
1443 	}
1444 	return 0;
1445 }
1446 
1447 static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
1448 {
1449 	return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
1450 }
1451 
1452 static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
1453 {
1454 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1455 	data->pcie_performance_request = true;
1456 
1457 	return 0;
1458 }
1459 
1460 static int smu7_program_edc_didt_registers(struct pp_hwmgr *hwmgr,
1461 					   uint32_t *cac_config_regs,
1462 					   AtomCtrl_EDCLeakgeTable *edc_leakage_table)
1463 {
1464 	uint32_t data, i = 0;
1465 
1466 	while (cac_config_regs[i] != 0xFFFFFFFF) {
1467 		data = edc_leakage_table->DIDT_REG[i];
1468 		cgs_write_ind_register(hwmgr->device,
1469 				       CGS_IND_REG__DIDT,
1470 				       cac_config_regs[i],
1471 				       data);
1472 		i++;
1473 	}
1474 
1475 	return 0;
1476 }
1477 
1478 static int smu7_populate_edc_leakage_registers(struct pp_hwmgr *hwmgr)
1479 {
1480 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1481 	int ret = 0;
1482 
1483 	if (!data->disable_edc_leakage_controller &&
1484 	    data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
1485 	    data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
1486 		ret = smu7_program_edc_didt_registers(hwmgr,
1487 						      DIDTEDCConfig_P12,
1488 						      &data->edc_leakage_table);
1489 		if (ret)
1490 			return ret;
1491 
1492 		ret = smum_send_msg_to_smc(hwmgr,
1493 					   (PPSMC_Msg)PPSMC_MSG_EnableEDCController,
1494 					   NULL);
1495 	} else {
1496 		ret = smum_send_msg_to_smc(hwmgr,
1497 					   (PPSMC_Msg)PPSMC_MSG_DisableEDCController,
1498 					   NULL);
1499 	}
1500 
1501 	return ret;
1502 }
1503 
1504 static void smu7_populate_umdpstate_clocks(struct pp_hwmgr *hwmgr)
1505 {
1506 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1507 	struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table;
1508 	struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk =
1509 			hwmgr->dyn_state.vddc_dependency_on_sclk;
1510 	struct phm_ppt_v1_information *table_info =
1511 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1512 	struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk =
1513 			table_info->vdd_dep_on_sclk;
1514 	int32_t tmp_sclk, count, percentage;
1515 
1516 	if (golden_dpm_table->mclk_table.count == 1) {
1517 		percentage = 70;
1518 		hwmgr->pstate_mclk = golden_dpm_table->mclk_table.dpm_levels[0].value;
1519 	} else {
1520 		percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value /
1521 				golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
1522 		hwmgr->pstate_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value;
1523 	}
1524 
1525 	tmp_sclk = hwmgr->pstate_mclk * percentage / 100;
1526 
1527 	if (hwmgr->pp_table_version == PP_TABLE_V0) {
1528 		for (count = vddc_dependency_on_sclk->count - 1; count >= 0; count--) {
1529 			if (tmp_sclk >= vddc_dependency_on_sclk->entries[count].clk) {
1530 				hwmgr->pstate_sclk = vddc_dependency_on_sclk->entries[count].clk;
1531 				break;
1532 			}
1533 		}
1534 		if (count < 0)
1535 			hwmgr->pstate_sclk = vddc_dependency_on_sclk->entries[0].clk;
1536 
1537 		hwmgr->pstate_sclk_peak =
1538 			vddc_dependency_on_sclk->entries[vddc_dependency_on_sclk->count - 1].clk;
1539 	} else if (hwmgr->pp_table_version == PP_TABLE_V1) {
1540 		for (count = vdd_dep_on_sclk->count - 1; count >= 0; count--) {
1541 			if (tmp_sclk >= vdd_dep_on_sclk->entries[count].clk) {
1542 				hwmgr->pstate_sclk = vdd_dep_on_sclk->entries[count].clk;
1543 				break;
1544 			}
1545 		}
1546 		if (count < 0)
1547 			hwmgr->pstate_sclk = vdd_dep_on_sclk->entries[0].clk;
1548 
1549 		hwmgr->pstate_sclk_peak =
1550 			vdd_dep_on_sclk->entries[vdd_dep_on_sclk->count - 1].clk;
1551 	}
1552 
1553 	hwmgr->pstate_mclk_peak =
1554 		golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
1555 
1556 	/* make sure the output is in Mhz */
1557 	hwmgr->pstate_sclk /= 100;
1558 	hwmgr->pstate_mclk /= 100;
1559 	hwmgr->pstate_sclk_peak /= 100;
1560 	hwmgr->pstate_mclk_peak /= 100;
1561 }
1562 
1563 static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1564 {
1565 	int tmp_result = 0;
1566 	int result = 0;
1567 
1568 	if (smu7_voltage_control(hwmgr)) {
1569 		tmp_result = smu7_enable_voltage_control(hwmgr);
1570 		PP_ASSERT_WITH_CODE(tmp_result == 0,
1571 				"Failed to enable voltage control!",
1572 				result = tmp_result);
1573 
1574 		tmp_result = smu7_construct_voltage_tables(hwmgr);
1575 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1576 				"Failed to construct voltage tables!",
1577 				result = tmp_result);
1578 	}
1579 	smum_initialize_mc_reg_table(hwmgr);
1580 
1581 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1582 			PHM_PlatformCaps_EngineSpreadSpectrumSupport))
1583 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1584 				GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1);
1585 
1586 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1587 			PHM_PlatformCaps_ThermalController))
1588 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1589 				GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0);
1590 
1591 	tmp_result = smu7_program_static_screen_threshold_parameters(hwmgr);
1592 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1593 			"Failed to program static screen threshold parameters!",
1594 			result = tmp_result);
1595 
1596 	tmp_result = smu7_enable_display_gap(hwmgr);
1597 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1598 			"Failed to enable display gap!", result = tmp_result);
1599 
1600 	tmp_result = smu7_program_voting_clients(hwmgr);
1601 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1602 			"Failed to program voting clients!", result = tmp_result);
1603 
1604 	tmp_result = smum_process_firmware_header(hwmgr);
1605 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1606 			"Failed to process firmware header!", result = tmp_result);
1607 
1608 	if (hwmgr->chip_id != CHIP_VEGAM) {
1609 		tmp_result = smu7_initial_switch_from_arbf0_to_f1(hwmgr);
1610 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1611 				"Failed to initialize switch from ArbF0 to F1!",
1612 				result = tmp_result);
1613 	}
1614 
1615 	result = smu7_setup_default_dpm_tables(hwmgr);
1616 	PP_ASSERT_WITH_CODE(0 == result,
1617 			"Failed to setup default DPM tables!", return result);
1618 
1619 	tmp_result = smum_init_smc_table(hwmgr);
1620 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1621 			"Failed to initialize SMC table!", result = tmp_result);
1622 
1623 	tmp_result = smu7_enable_vrhot_gpio_interrupt(hwmgr);
1624 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1625 			"Failed to enable VR hot GPIO interrupt!", result = tmp_result);
1626 
1627 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1628 	    hwmgr->chip_id <= CHIP_VEGAM) {
1629 		tmp_result = smu7_notify_has_display(hwmgr);
1630 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1631 				"Failed to enable display setting!", result = tmp_result);
1632 	} else {
1633 		smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL);
1634 	}
1635 
1636 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
1637 	    hwmgr->chip_id <= CHIP_VEGAM) {
1638 		tmp_result = smu7_populate_edc_leakage_registers(hwmgr);
1639 		PP_ASSERT_WITH_CODE((0 == tmp_result),
1640 				"Failed to populate edc leakage registers!", result = tmp_result);
1641 	}
1642 
1643 	tmp_result = smu7_enable_sclk_control(hwmgr);
1644 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1645 			"Failed to enable SCLK control!", result = tmp_result);
1646 
1647 	tmp_result = smu7_enable_smc_voltage_controller(hwmgr);
1648 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1649 			"Failed to enable voltage control!", result = tmp_result);
1650 
1651 	tmp_result = smu7_enable_ulv(hwmgr);
1652 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1653 			"Failed to enable ULV!", result = tmp_result);
1654 
1655 	tmp_result = smu7_enable_deep_sleep_master_switch(hwmgr);
1656 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1657 			"Failed to enable deep sleep master switch!", result = tmp_result);
1658 
1659 	tmp_result = smu7_enable_didt_config(hwmgr);
1660 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1661 			"Failed to enable deep sleep master switch!", result = tmp_result);
1662 
1663 	tmp_result = smu7_start_dpm(hwmgr);
1664 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1665 			"Failed to start DPM!", result = tmp_result);
1666 
1667 	tmp_result = smu7_enable_smc_cac(hwmgr);
1668 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1669 			"Failed to enable SMC CAC!", result = tmp_result);
1670 
1671 	tmp_result = smu7_enable_power_containment(hwmgr);
1672 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1673 			"Failed to enable power containment!", result = tmp_result);
1674 
1675 	tmp_result = smu7_power_control_set_level(hwmgr);
1676 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1677 			"Failed to power control set level!", result = tmp_result);
1678 
1679 	tmp_result = smu7_enable_thermal_auto_throttle(hwmgr);
1680 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1681 			"Failed to enable thermal auto throttle!", result = tmp_result);
1682 
1683 	tmp_result = smu7_pcie_performance_request(hwmgr);
1684 	PP_ASSERT_WITH_CODE((0 == tmp_result),
1685 			"pcie performance request failed!", result = tmp_result);
1686 
1687 	smu7_populate_umdpstate_clocks(hwmgr);
1688 
1689 	return 0;
1690 }
1691 
1692 static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable)
1693 {
1694 	if (!hwmgr->avfs_supported)
1695 		return 0;
1696 
1697 	if (enable) {
1698 		if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
1699 				CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) {
1700 			PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(
1701 					hwmgr, PPSMC_MSG_EnableAvfs, NULL),
1702 					"Failed to enable AVFS!",
1703 					return -EINVAL);
1704 		}
1705 	} else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
1706 			CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) {
1707 		PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(
1708 				hwmgr, PPSMC_MSG_DisableAvfs, NULL),
1709 				"Failed to disable AVFS!",
1710 				return -EINVAL);
1711 	}
1712 
1713 	return 0;
1714 }
1715 
1716 static int smu7_update_avfs(struct pp_hwmgr *hwmgr)
1717 {
1718 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1719 
1720 	if (!hwmgr->avfs_supported)
1721 		return 0;
1722 
1723 	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
1724 		smu7_avfs_control(hwmgr, false);
1725 	} else if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
1726 		smu7_avfs_control(hwmgr, false);
1727 		smu7_avfs_control(hwmgr, true);
1728 	} else {
1729 		smu7_avfs_control(hwmgr, true);
1730 	}
1731 
1732 	return 0;
1733 }
1734 
1735 static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
1736 {
1737 	int tmp_result, result = 0;
1738 
1739 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1740 			PHM_PlatformCaps_ThermalController))
1741 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1742 				GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1);
1743 
1744 	tmp_result = smu7_disable_power_containment(hwmgr);
1745 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1746 			"Failed to disable power containment!", result = tmp_result);
1747 
1748 	tmp_result = smu7_disable_smc_cac(hwmgr);
1749 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1750 			"Failed to disable SMC CAC!", result = tmp_result);
1751 
1752 	tmp_result = smu7_disable_didt_config(hwmgr);
1753 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1754 			"Failed to disable DIDT!", result = tmp_result);
1755 
1756 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1757 			CG_SPLL_SPREAD_SPECTRUM, SSEN, 0);
1758 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
1759 			GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0);
1760 
1761 	tmp_result = smu7_disable_thermal_auto_throttle(hwmgr);
1762 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1763 			"Failed to disable thermal auto throttle!", result = tmp_result);
1764 
1765 	tmp_result = smu7_avfs_control(hwmgr, false);
1766 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1767 			"Failed to disable AVFS!", result = tmp_result);
1768 
1769 	tmp_result = smu7_stop_dpm(hwmgr);
1770 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1771 			"Failed to stop DPM!", result = tmp_result);
1772 
1773 	tmp_result = smu7_disable_deep_sleep_master_switch(hwmgr);
1774 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1775 			"Failed to disable deep sleep master switch!", result = tmp_result);
1776 
1777 	tmp_result = smu7_disable_ulv(hwmgr);
1778 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1779 			"Failed to disable ULV!", result = tmp_result);
1780 
1781 	tmp_result = smu7_clear_voting_clients(hwmgr);
1782 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1783 			"Failed to clear voting clients!", result = tmp_result);
1784 
1785 	tmp_result = smu7_reset_to_default(hwmgr);
1786 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1787 			"Failed to reset to default!", result = tmp_result);
1788 
1789 	tmp_result = smum_stop_smc(hwmgr);
1790 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1791 			"Failed to stop smc!", result = tmp_result);
1792 
1793 	tmp_result = smu7_force_switch_to_arbf0(hwmgr);
1794 	PP_ASSERT_WITH_CODE((tmp_result == 0),
1795 			"Failed to force to switch arbf0!", result = tmp_result);
1796 
1797 	return result;
1798 }
1799 
1800 static bool intel_core_rkl_chk(void)
1801 {
1802 #if IS_ENABLED(CONFIG_X86_64)
1803 	struct cpuinfo_x86 *c = &cpu_data(0);
1804 
1805 	return (c->x86 == 6 && c->x86_model == INTEL_FAM6_ROCKETLAKE);
1806 #else
1807 	return false;
1808 #endif
1809 }
1810 
1811 static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
1812 {
1813 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1814 	struct phm_ppt_v1_information *table_info =
1815 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
1816 	struct amdgpu_device *adev = hwmgr->adev;
1817 	uint8_t tmp1, tmp2;
1818 	uint16_t tmp3 = 0;
1819 
1820 	data->dll_default_on = false;
1821 	data->mclk_dpm0_activity_target = 0xa;
1822 	data->vddc_vddgfx_delta = 300;
1823 	data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT;
1824 	data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT;
1825 	data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT0;
1826 	data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT1;
1827 	data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT2;
1828 	data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT3;
1829 	data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT4;
1830 	data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT5;
1831 	data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT6;
1832 	data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT7;
1833 
1834 	data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
1835 	data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
1836 	data->pcie_dpm_key_disabled =
1837 		intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
1838 	/* need to set voltage control types before EVV patching */
1839 	data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE;
1840 	data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE;
1841 	data->mvdd_control = SMU7_VOLTAGE_CONTROL_NONE;
1842 	data->enable_tdc_limit_feature = true;
1843 	data->enable_pkg_pwr_tracking_feature = true;
1844 	data->force_pcie_gen = PP_PCIEGenInvalid;
1845 	data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false;
1846 	data->current_profile_setting.bupdate_sclk = 1;
1847 	data->current_profile_setting.sclk_up_hyst = 0;
1848 	data->current_profile_setting.sclk_down_hyst = 100;
1849 	data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT;
1850 	data->current_profile_setting.bupdate_mclk = 1;
1851 	if (hwmgr->chip_id >= CHIP_POLARIS10) {
1852 		if (adev->gmc.vram_width == 256) {
1853 			data->current_profile_setting.mclk_up_hyst = 10;
1854 			data->current_profile_setting.mclk_down_hyst = 60;
1855 			data->current_profile_setting.mclk_activity = 25;
1856 		} else if (adev->gmc.vram_width == 128) {
1857 			data->current_profile_setting.mclk_up_hyst = 5;
1858 			data->current_profile_setting.mclk_down_hyst = 16;
1859 			data->current_profile_setting.mclk_activity = 20;
1860 		} else if (adev->gmc.vram_width == 64) {
1861 			data->current_profile_setting.mclk_up_hyst = 3;
1862 			data->current_profile_setting.mclk_down_hyst = 16;
1863 			data->current_profile_setting.mclk_activity = 20;
1864 		}
1865 	} else {
1866 		data->current_profile_setting.mclk_up_hyst = 0;
1867 		data->current_profile_setting.mclk_down_hyst = 100;
1868 		data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT;
1869 	}
1870 	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
1871 	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1872 	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
1873 
1874 	if (hwmgr->chip_id  == CHIP_HAWAII) {
1875 		data->thermal_temp_setting.temperature_low = 94500;
1876 		data->thermal_temp_setting.temperature_high = 95000;
1877 		data->thermal_temp_setting.temperature_shutdown = 104000;
1878 	} else {
1879 		data->thermal_temp_setting.temperature_low = 99500;
1880 		data->thermal_temp_setting.temperature_high = 100000;
1881 		data->thermal_temp_setting.temperature_shutdown = 104000;
1882 	}
1883 
1884 	data->fast_watermark_threshold = 100;
1885 	if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1886 			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
1887 		data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1888 	else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1889 			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT))
1890 		data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO;
1891 
1892 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1893 			PHM_PlatformCaps_ControlVDDGFX)) {
1894 		if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1895 			VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) {
1896 			data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1897 		}
1898 	}
1899 
1900 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1901 			PHM_PlatformCaps_EnableMVDDControl)) {
1902 		if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1903 				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT))
1904 			data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO;
1905 		else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1906 				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2))
1907 			data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1908 	}
1909 
1910 	if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control)
1911 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1912 			PHM_PlatformCaps_ControlVDDGFX);
1913 
1914 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1915 			PHM_PlatformCaps_ControlVDDCI)) {
1916 		if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1917 				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
1918 			data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO;
1919 		else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr,
1920 				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
1921 			data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID2;
1922 	}
1923 
1924 	if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE)
1925 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1926 				PHM_PlatformCaps_EnableMVDDControl);
1927 
1928 	if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE)
1929 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1930 				PHM_PlatformCaps_ControlVDDCI);
1931 
1932 	data->vddc_phase_shed_control = 1;
1933 	if ((hwmgr->chip_id == CHIP_POLARIS12) ||
1934 	    ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) ||
1935 	    ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) ||
1936 	    ASICID_IS_P30(adev->pdev->device, adev->pdev->revision) ||
1937 	    ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
1938 		if (data->voltage_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
1939 			atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2,
1940 							&tmp3);
1941 			tmp3 = (tmp3 >> 5) & 0x3;
1942 			data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3;
1943 		}
1944 	} else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) {
1945 		data->vddc_phase_shed_control = 1;
1946 	}
1947 
1948 	if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK)
1949 		&& (table_info->cac_dtp_table->usClockStretchAmount != 0))
1950 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1951 					PHM_PlatformCaps_ClockStretcher);
1952 
1953 	data->pcie_gen_performance.max = PP_PCIEGen1;
1954 	data->pcie_gen_performance.min = PP_PCIEGen3;
1955 	data->pcie_gen_power_saving.max = PP_PCIEGen1;
1956 	data->pcie_gen_power_saving.min = PP_PCIEGen3;
1957 	data->pcie_lane_performance.max = 0;
1958 	data->pcie_lane_performance.min = 16;
1959 	data->pcie_lane_power_saving.max = 0;
1960 	data->pcie_lane_power_saving.min = 16;
1961 
1962 
1963 	if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
1964 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1965 			      PHM_PlatformCaps_UVDPowerGating);
1966 	if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
1967 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1968 			      PHM_PlatformCaps_VCEPowerGating);
1969 
1970 	data->disable_edc_leakage_controller = true;
1971 	if (((adev->asic_type == CHIP_POLARIS10) && hwmgr->is_kicker) ||
1972 	    ((adev->asic_type == CHIP_POLARIS11) && hwmgr->is_kicker) ||
1973 	    (adev->asic_type == CHIP_POLARIS12) ||
1974 	    (adev->asic_type == CHIP_VEGAM))
1975 		data->disable_edc_leakage_controller = false;
1976 
1977 	if (!atomctrl_is_asic_internal_ss_supported(hwmgr)) {
1978 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1979 			PHM_PlatformCaps_MemorySpreadSpectrumSupport);
1980 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1981 			PHM_PlatformCaps_EngineSpreadSpectrumSupport);
1982 	}
1983 
1984 	if ((adev->pdev->device == 0x699F) &&
1985 	    (adev->pdev->revision == 0xCF)) {
1986 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1987 				PHM_PlatformCaps_PowerContainment);
1988 		data->enable_tdc_limit_feature = false;
1989 		data->enable_pkg_pwr_tracking_feature = false;
1990 		data->disable_edc_leakage_controller = true;
1991 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
1992 					PHM_PlatformCaps_ClockStretcher);
1993 	}
1994 }
1995 
1996 static int smu7_calculate_ro_range(struct pp_hwmgr *hwmgr)
1997 {
1998 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
1999 	struct amdgpu_device *adev = hwmgr->adev;
2000 	uint32_t asicrev1, evv_revision, max = 0, min = 0;
2001 
2002 	atomctrl_read_efuse(hwmgr, STRAP_EVV_REVISION_LSB, STRAP_EVV_REVISION_MSB,
2003 			&evv_revision);
2004 
2005 	atomctrl_read_efuse(hwmgr, 568, 579, &asicrev1);
2006 
2007 	if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) ||
2008 	    ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
2009 		min = 1200;
2010 		max = 2500;
2011 	} else if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) ||
2012 		   ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
2013 		min = 900;
2014 		max= 2100;
2015 	} else if (hwmgr->chip_id == CHIP_POLARIS10) {
2016 		if (adev->pdev->subsystem_vendor == 0x106B) {
2017 			min = 1000;
2018 			max = 2300;
2019 		} else {
2020 			if (evv_revision == 0) {
2021 				min = 1000;
2022 				max = 2300;
2023 			} else if (evv_revision == 1) {
2024 				if (asicrev1 == 326) {
2025 					min = 1200;
2026 					max = 2500;
2027 					/* TODO: PATCH RO in VBIOS */
2028 				} else {
2029 					min = 1200;
2030 					max = 2000;
2031 				}
2032 			} else if (evv_revision == 2) {
2033 				min = 1200;
2034 				max = 2500;
2035 			}
2036 		}
2037 	} else {
2038 		min = 1100;
2039 		max = 2100;
2040 	}
2041 
2042 	data->ro_range_minimum = min;
2043 	data->ro_range_maximum = max;
2044 
2045 	/* TODO: PATCH RO in VBIOS here */
2046 
2047 	return 0;
2048 }
2049 
2050 /**
2051  * smu7_get_evv_voltages - Get Leakage VDDC based on leakage ID.
2052  *
2053  * @hwmgr:  the address of the powerplay hardware manager.
2054  * Return:   always 0
2055  */
2056 static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
2057 {
2058 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2059 	uint16_t vv_id;
2060 	uint16_t vddc = 0;
2061 	uint16_t vddgfx = 0;
2062 	uint16_t i, j;
2063 	uint32_t sclk = 0;
2064 	struct phm_ppt_v1_information *table_info =
2065 			(struct phm_ppt_v1_information *)hwmgr->pptable;
2066 	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL;
2067 
2068 	if (hwmgr->chip_id == CHIP_POLARIS10 ||
2069 	    hwmgr->chip_id == CHIP_POLARIS11 ||
2070 	    hwmgr->chip_id == CHIP_POLARIS12)
2071 		smu7_calculate_ro_range(hwmgr);
2072 
2073 	for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {
2074 		vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
2075 
2076 		if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2077 			if ((hwmgr->pp_table_version == PP_TABLE_V1)
2078 			    && !phm_get_sclk_for_voltage_evv(hwmgr,
2079 						table_info->vddgfx_lookup_table, vv_id, &sclk)) {
2080 				if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2081 							PHM_PlatformCaps_ClockStretcher)) {
2082 					sclk_table = table_info->vdd_dep_on_sclk;
2083 
2084 					for (j = 1; j < sclk_table->count; j++) {
2085 						if (sclk_table->entries[j].clk == sclk &&
2086 								sclk_table->entries[j].cks_enable == 0) {
2087 							sclk += 5000;
2088 							break;
2089 						}
2090 					}
2091 				}
2092 				if (0 == atomctrl_get_voltage_evv_on_sclk
2093 				    (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk,
2094 				     vv_id, &vddgfx)) {
2095 					/* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
2096 					PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -EINVAL);
2097 
2098 					/* the voltage should not be zero nor equal to leakage ID */
2099 					if (vddgfx != 0 && vddgfx != vv_id) {
2100 						data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
2101 						data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = vv_id;
2102 						data->vddcgfx_leakage.count++;
2103 					}
2104 				} else {
2105 					pr_info("Error retrieving EVV voltage value!\n");
2106 				}
2107 			}
2108 		} else {
2109 			if ((hwmgr->pp_table_version == PP_TABLE_V0)
2110 				|| !phm_get_sclk_for_voltage_evv(hwmgr,
2111 					table_info->vddc_lookup_table, vv_id, &sclk)) {
2112 				if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2113 						PHM_PlatformCaps_ClockStretcher)) {
2114 					if (table_info == NULL)
2115 						return -EINVAL;
2116 					sclk_table = table_info->vdd_dep_on_sclk;
2117 
2118 					for (j = 1; j < sclk_table->count; j++) {
2119 						if (sclk_table->entries[j].clk == sclk &&
2120 								sclk_table->entries[j].cks_enable == 0) {
2121 							sclk += 5000;
2122 							break;
2123 						}
2124 					}
2125 				}
2126 
2127 				if (phm_get_voltage_evv_on_sclk(hwmgr,
2128 							VOLTAGE_TYPE_VDDC,
2129 							sclk, vv_id, &vddc) == 0) {
2130 					if (vddc >= 2000 || vddc == 0)
2131 						return -EINVAL;
2132 				} else {
2133 					pr_debug("failed to retrieving EVV voltage!\n");
2134 					continue;
2135 				}
2136 
2137 				/* the voltage should not be zero nor equal to leakage ID */
2138 				if (vddc != 0 && vddc != vv_id) {
2139 					data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc);
2140 					data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
2141 					data->vddc_leakage.count++;
2142 				}
2143 			}
2144 		}
2145 	}
2146 
2147 	return 0;
2148 }
2149 
2150 /**
2151  * smu7_patch_ppt_v1_with_vdd_leakage - Change virtual leakage voltage to actual value.
2152  *
2153  * @hwmgr:  the address of the powerplay hardware manager.
2154  * @voltage: pointer to changing voltage
2155  * @leakage_table: pointer to leakage table
2156  */
2157 static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr,
2158 		uint16_t *voltage, struct smu7_leakage_voltage *leakage_table)
2159 {
2160 	uint32_t index;
2161 
2162 	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
2163 	for (index = 0; index < leakage_table->count; index++) {
2164 		/* if this voltage matches a leakage voltage ID */
2165 		/* patch with actual leakage voltage */
2166 		if (leakage_table->leakage_id[index] == *voltage) {
2167 			*voltage = leakage_table->actual_voltage[index];
2168 			break;
2169 		}
2170 	}
2171 
2172 	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
2173 		pr_info("Voltage value looks like a Leakage ID but it's not patched\n");
2174 }
2175 
2176 /**
2177  * smu7_patch_lookup_table_with_leakage - Patch voltage lookup table by EVV leakages.
2178  *
2179  * @hwmgr:  the address of the powerplay hardware manager.
2180  * @lookup_table: pointer to voltage lookup table
2181  * @leakage_table: pointer to leakage table
2182  * Return:     always 0
2183  */
2184 static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
2185 		phm_ppt_v1_voltage_lookup_table *lookup_table,
2186 		struct smu7_leakage_voltage *leakage_table)
2187 {
2188 	uint32_t i;
2189 
2190 	for (i = 0; i < lookup_table->count; i++)
2191 		smu7_patch_ppt_v1_with_vdd_leakage(hwmgr,
2192 				&lookup_table->entries[i].us_vdd, leakage_table);
2193 
2194 	return 0;
2195 }
2196 
2197 static int smu7_patch_clock_voltage_limits_with_vddc_leakage(
2198 		struct pp_hwmgr *hwmgr, struct smu7_leakage_voltage *leakage_table,
2199 		uint16_t *vddc)
2200 {
2201 	struct phm_ppt_v1_information *table_info =
2202 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2203 	smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
2204 	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
2205 			table_info->max_clock_voltage_on_dc.vddc;
2206 	return 0;
2207 }
2208 
2209 static int smu7_patch_voltage_dependency_tables_with_lookup_table(
2210 		struct pp_hwmgr *hwmgr)
2211 {
2212 	uint8_t entry_id;
2213 	uint8_t voltage_id;
2214 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2215 	struct phm_ppt_v1_information *table_info =
2216 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2217 
2218 	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
2219 			table_info->vdd_dep_on_sclk;
2220 	struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
2221 			table_info->vdd_dep_on_mclk;
2222 	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
2223 			table_info->mm_dep_table;
2224 
2225 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2226 		for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2227 			voltage_id = sclk_table->entries[entry_id].vddInd;
2228 			sclk_table->entries[entry_id].vddgfx =
2229 				table_info->vddgfx_lookup_table->entries[voltage_id].us_vdd;
2230 		}
2231 	} else {
2232 		for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2233 			voltage_id = sclk_table->entries[entry_id].vddInd;
2234 			sclk_table->entries[entry_id].vddc =
2235 				table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2236 		}
2237 	}
2238 
2239 	for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
2240 		voltage_id = mclk_table->entries[entry_id].vddInd;
2241 		mclk_table->entries[entry_id].vddc =
2242 			table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2243 	}
2244 
2245 	for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
2246 		voltage_id = mm_table->entries[entry_id].vddcInd;
2247 		mm_table->entries[entry_id].vddc =
2248 			table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
2249 	}
2250 
2251 	return 0;
2252 
2253 }
2254 
2255 static int phm_add_voltage(struct pp_hwmgr *hwmgr,
2256 			phm_ppt_v1_voltage_lookup_table *look_up_table,
2257 			phm_ppt_v1_voltage_lookup_record *record)
2258 {
2259 	uint32_t i;
2260 
2261 	PP_ASSERT_WITH_CODE((NULL != look_up_table),
2262 		"Lookup Table empty.", return -EINVAL);
2263 	PP_ASSERT_WITH_CODE((0 != look_up_table->count),
2264 		"Lookup Table empty.", return -EINVAL);
2265 
2266 	i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX);
2267 	PP_ASSERT_WITH_CODE((i >= look_up_table->count),
2268 		"Lookup Table is full.", return -EINVAL);
2269 
2270 	/* This is to avoid entering duplicate calculated records. */
2271 	for (i = 0; i < look_up_table->count; i++) {
2272 		if (look_up_table->entries[i].us_vdd == record->us_vdd) {
2273 			if (look_up_table->entries[i].us_calculated == 1)
2274 				return 0;
2275 			break;
2276 		}
2277 	}
2278 
2279 	look_up_table->entries[i].us_calculated = 1;
2280 	look_up_table->entries[i].us_vdd = record->us_vdd;
2281 	look_up_table->entries[i].us_cac_low = record->us_cac_low;
2282 	look_up_table->entries[i].us_cac_mid = record->us_cac_mid;
2283 	look_up_table->entries[i].us_cac_high = record->us_cac_high;
2284 	/* Only increment the count when we're appending, not replacing duplicate entry. */
2285 	if (i == look_up_table->count)
2286 		look_up_table->count++;
2287 
2288 	return 0;
2289 }
2290 
2291 
2292 static int smu7_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
2293 {
2294 	uint8_t entry_id;
2295 	struct phm_ppt_v1_voltage_lookup_record v_record;
2296 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2297 	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2298 
2299 	phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk;
2300 	phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk;
2301 
2302 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2303 		for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) {
2304 			if (sclk_table->entries[entry_id].vdd_offset & (1 << 15))
2305 				v_record.us_vdd = sclk_table->entries[entry_id].vddgfx +
2306 					sclk_table->entries[entry_id].vdd_offset - 0xFFFF;
2307 			else
2308 				v_record.us_vdd = sclk_table->entries[entry_id].vddgfx +
2309 					sclk_table->entries[entry_id].vdd_offset;
2310 
2311 			sclk_table->entries[entry_id].vddc =
2312 				v_record.us_cac_low = v_record.us_cac_mid =
2313 				v_record.us_cac_high = v_record.us_vdd;
2314 
2315 			phm_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record);
2316 		}
2317 
2318 		for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
2319 			if (mclk_table->entries[entry_id].vdd_offset & (1 << 15))
2320 				v_record.us_vdd = mclk_table->entries[entry_id].vddc +
2321 					mclk_table->entries[entry_id].vdd_offset - 0xFFFF;
2322 			else
2323 				v_record.us_vdd = mclk_table->entries[entry_id].vddc +
2324 					mclk_table->entries[entry_id].vdd_offset;
2325 
2326 			mclk_table->entries[entry_id].vddgfx = v_record.us_cac_low =
2327 				v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
2328 			phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
2329 		}
2330 	}
2331 	return 0;
2332 }
2333 
2334 static int smu7_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
2335 {
2336 	uint8_t entry_id;
2337 	struct phm_ppt_v1_voltage_lookup_record v_record;
2338 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2339 	struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
2340 	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table;
2341 
2342 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2343 		for (entry_id = 0; entry_id < mm_table->count; entry_id++) {
2344 			if (mm_table->entries[entry_id].vddgfx_offset & (1 << 15))
2345 				v_record.us_vdd = mm_table->entries[entry_id].vddc +
2346 					mm_table->entries[entry_id].vddgfx_offset - 0xFFFF;
2347 			else
2348 				v_record.us_vdd = mm_table->entries[entry_id].vddc +
2349 					mm_table->entries[entry_id].vddgfx_offset;
2350 
2351 			/* Add the calculated VDDGFX to the VDDGFX lookup table */
2352 			mm_table->entries[entry_id].vddgfx = v_record.us_cac_low =
2353 				v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd;
2354 			phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record);
2355 		}
2356 	}
2357 	return 0;
2358 }
2359 
2360 static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr,
2361 		struct phm_ppt_v1_voltage_lookup_table *lookup_table)
2362 {
2363 	uint32_t table_size, i, j;
2364 	table_size = lookup_table->count;
2365 
2366 	PP_ASSERT_WITH_CODE(0 != lookup_table->count,
2367 		"Lookup table is empty", return -EINVAL);
2368 
2369 	/* Sorting voltages */
2370 	for (i = 0; i < table_size - 1; i++) {
2371 		for (j = i + 1; j > 0; j--) {
2372 			if (lookup_table->entries[j].us_vdd <
2373 					lookup_table->entries[j - 1].us_vdd) {
2374 				swap(lookup_table->entries[j - 1],
2375 				     lookup_table->entries[j]);
2376 			}
2377 		}
2378 	}
2379 
2380 	return 0;
2381 }
2382 
2383 static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr)
2384 {
2385 	int result = 0;
2386 	int tmp_result;
2387 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2388 	struct phm_ppt_v1_information *table_info =
2389 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2390 
2391 	if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
2392 		tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr,
2393 			table_info->vddgfx_lookup_table, &(data->vddcgfx_leakage));
2394 		if (tmp_result != 0)
2395 			result = tmp_result;
2396 
2397 		smu7_patch_ppt_v1_with_vdd_leakage(hwmgr,
2398 			&table_info->max_clock_voltage_on_dc.vddgfx, &(data->vddcgfx_leakage));
2399 	} else {
2400 
2401 		tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr,
2402 				table_info->vddc_lookup_table, &(data->vddc_leakage));
2403 		if (tmp_result)
2404 			result = tmp_result;
2405 
2406 		tmp_result = smu7_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
2407 				&(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
2408 		if (tmp_result)
2409 			result = tmp_result;
2410 	}
2411 
2412 	tmp_result = smu7_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
2413 	if (tmp_result)
2414 		result = tmp_result;
2415 
2416 	tmp_result = smu7_calc_voltage_dependency_tables(hwmgr);
2417 	if (tmp_result)
2418 		result = tmp_result;
2419 
2420 	tmp_result = smu7_calc_mm_voltage_dependency_table(hwmgr);
2421 	if (tmp_result)
2422 		result = tmp_result;
2423 
2424 	tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddgfx_lookup_table);
2425 	if (tmp_result)
2426 		result = tmp_result;
2427 
2428 	tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
2429 	if (tmp_result)
2430 		result = tmp_result;
2431 
2432 	return result;
2433 }
2434 
2435 static int smu7_find_highest_vddc(struct pp_hwmgr *hwmgr)
2436 {
2437 	struct phm_ppt_v1_information *table_info =
2438 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2439 	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
2440 						table_info->vdd_dep_on_sclk;
2441 	struct phm_ppt_v1_voltage_lookup_table *lookup_table =
2442 						table_info->vddc_lookup_table;
2443 	uint16_t highest_voltage;
2444 	uint32_t i;
2445 
2446 	highest_voltage = allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
2447 
2448 	for (i = 0; i < lookup_table->count; i++) {
2449 		if (lookup_table->entries[i].us_vdd < ATOM_VIRTUAL_VOLTAGE_ID0 &&
2450 		    lookup_table->entries[i].us_vdd > highest_voltage)
2451 			highest_voltage = lookup_table->entries[i].us_vdd;
2452 	}
2453 
2454 	return highest_voltage;
2455 }
2456 
2457 static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr)
2458 {
2459 	struct phm_ppt_v1_information *table_info =
2460 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2461 
2462 	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
2463 						table_info->vdd_dep_on_sclk;
2464 	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
2465 						table_info->vdd_dep_on_mclk;
2466 
2467 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
2468 		"VDD dependency on SCLK table is missing.",
2469 		return -EINVAL);
2470 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
2471 		"VDD dependency on SCLK table has to have is missing.",
2472 		return -EINVAL);
2473 
2474 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
2475 		"VDD dependency on MCLK table is missing",
2476 		return -EINVAL);
2477 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
2478 		"VDD dependency on MCLK table has to have is missing.",
2479 		return -EINVAL);
2480 
2481 	table_info->max_clock_voltage_on_ac.sclk =
2482 		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
2483 	table_info->max_clock_voltage_on_ac.mclk =
2484 		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
2485 	if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
2486 		table_info->max_clock_voltage_on_ac.vddc =
2487 			smu7_find_highest_vddc(hwmgr);
2488 	else
2489 		table_info->max_clock_voltage_on_ac.vddc =
2490 			allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
2491 	table_info->max_clock_voltage_on_ac.vddci =
2492 		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
2493 
2494 	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk;
2495 	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk;
2496 	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc;
2497 	hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = table_info->max_clock_voltage_on_ac.vddci;
2498 
2499 	return 0;
2500 }
2501 
2502 static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
2503 {
2504 	struct phm_ppt_v1_information *table_info =
2505 		       (struct phm_ppt_v1_information *)(hwmgr->pptable);
2506 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
2507 	struct phm_ppt_v1_voltage_lookup_table *lookup_table;
2508 	uint32_t i;
2509 	uint32_t hw_revision, sub_vendor_id, sub_sys_id;
2510 	struct amdgpu_device *adev = hwmgr->adev;
2511 
2512 	if (table_info != NULL) {
2513 		dep_mclk_table = table_info->vdd_dep_on_mclk;
2514 		lookup_table = table_info->vddc_lookup_table;
2515 	} else
2516 		return 0;
2517 
2518 	hw_revision = adev->pdev->revision;
2519 	sub_sys_id = adev->pdev->subsystem_device;
2520 	sub_vendor_id = adev->pdev->subsystem_vendor;
2521 
2522 	if (adev->pdev->device == 0x67DF && hw_revision == 0xC7 &&
2523 	    ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) ||
2524 	     (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) ||
2525 	     (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) {
2526 
2527 		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device,
2528 					      CGS_IND_REG__SMC,
2529 					      PWR_CKS_CNTL,
2530 					      CKS_STRETCH_AMOUNT,
2531 					      0x3);
2532 
2533 		if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000)
2534 			return 0;
2535 
2536 		for (i = 0; i < lookup_table->count; i++) {
2537 			if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) {
2538 				dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i;
2539 				return 0;
2540 			}
2541 		}
2542 	}
2543 	return 0;
2544 }
2545 
2546 static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr)
2547 {
2548 	struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
2549 	uint32_t temp_reg;
2550 	struct phm_ppt_v1_information *table_info =
2551 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
2552 
2553 
2554 	if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) {
2555 		temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL);
2556 		switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) {
2557 		case 0:
2558 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1);
2559 			break;
2560 		case 1:
2561 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2);
2562 			break;
2563 		case 2:
2564 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1);
2565 			break;
2566 		case 3:
2567 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1);
2568 			break;
2569 		case 4:
2570 			temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1);
2571 			break;
2572 		default:
2573 			break;
2574 		}
2575 		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg);
2576 	}
2577 
2578 	if (table_info == NULL)
2579 		return 0;
2580 
2581 	if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 &&
2582 		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) {
2583 		hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit =
2584 			(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
2585 
2586 		hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit =
2587 			(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
2588 
2589 		hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1;
2590 
2591 		hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100;
2592 
2593 		hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit =
2594 			(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
2595 
2596 		hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1;
2597 
2598 		table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ?
2599 								(table_info->cac_dtp_table->usDefaultTargetOperatingTemp - 50) : 0;
2600 
2601 		table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
2602 		table_info->cac_dtp_table->usOperatingTempStep = 1;
2603 		table_info->cac_dtp_table->usOperatingTempHyst = 1;
2604 
2605 		hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM =
2606 			       hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
2607 
2608 		hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
2609 			       hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM;
2610 
2611 		hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit =
2612 			       table_info->cac_dtp_table->usOperatingTempMinLimit;
2613 
2614 		hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit =
2615 			       table_info->cac_dtp_table->usOperatingTempMaxLimit;
2616 
2617 		hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
2618 			       table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
2619 
2620 		hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep =
2621 			       table_info->cac_dtp_table->usOperatingTempStep;
2622 
2623 		hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
2624 			       table_info->cac_dtp_table->usTargetOperatingTemp;
2625 		if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK)
2626 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
2627 					PHM_PlatformCaps_ODFuzzyFanControlSupport);
2628 	}
2629 
2630 	return 0;
2631 }
2632 
2633 /**
2634  * smu7_patch_ppt_v0_with_vdd_leakage - Change virtual leakage voltage to actual value.
2635  *
2636  * @hwmgr:  the address of the powerplay hardware manager.
2637  * @voltage: pointer to changing voltage
2638  * @leakage_table: pointer to leakage table
2639  */
2640 static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr,
2641 		uint32_t *voltage, struct smu7_leakage_voltage *leakage_table)
2642 {
2643 	uint32_t index;
2644 
2645 	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
2646 	for (index = 0; index < leakage_table->count; index++) {
2647 		/* if this voltage matches a leakage voltage ID */
2648 		/* patch with actual leakage voltage */
2649 		if (leakage_table->leakage_id[index] == *voltage) {
2650 			*voltage = leakage_table->actual_voltage[index];
2651 			break;
2652 		}
2653 	}
2654 
2655 	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
2656 		pr_info("Voltage value looks like a Leakage ID but it's not patched\n");
2657 }
2658 
2659 
2660 static int smu7_patch_vddc(struct pp_hwmgr *hwmgr,
2661 			      struct phm_clock_voltage_dependency_table *tab)
2662 {
2663 	uint16_t i;
2664 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2665 
2666 	if (tab)
2667 		for (i = 0; i < tab->count; i++)
2668 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2669 						&data->vddc_leakage);
2670 
2671 	return 0;
2672 }
2673 
2674 static int smu7_patch_vddci(struct pp_hwmgr *hwmgr,
2675 			       struct phm_clock_voltage_dependency_table *tab)
2676 {
2677 	uint16_t i;
2678 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2679 
2680 	if (tab)
2681 		for (i = 0; i < tab->count; i++)
2682 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2683 							&data->vddci_leakage);
2684 
2685 	return 0;
2686 }
2687 
2688 static int smu7_patch_vce_vddc(struct pp_hwmgr *hwmgr,
2689 				  struct phm_vce_clock_voltage_dependency_table *tab)
2690 {
2691 	uint16_t i;
2692 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2693 
2694 	if (tab)
2695 		for (i = 0; i < tab->count; i++)
2696 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2697 							&data->vddc_leakage);
2698 
2699 	return 0;
2700 }
2701 
2702 
2703 static int smu7_patch_uvd_vddc(struct pp_hwmgr *hwmgr,
2704 				  struct phm_uvd_clock_voltage_dependency_table *tab)
2705 {
2706 	uint16_t i;
2707 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2708 
2709 	if (tab)
2710 		for (i = 0; i < tab->count; i++)
2711 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2712 							&data->vddc_leakage);
2713 
2714 	return 0;
2715 }
2716 
2717 static int smu7_patch_vddc_shed_limit(struct pp_hwmgr *hwmgr,
2718 					 struct phm_phase_shedding_limits_table *tab)
2719 {
2720 	uint16_t i;
2721 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2722 
2723 	if (tab)
2724 		for (i = 0; i < tab->count; i++)
2725 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].Voltage,
2726 							&data->vddc_leakage);
2727 
2728 	return 0;
2729 }
2730 
2731 static int smu7_patch_samu_vddc(struct pp_hwmgr *hwmgr,
2732 				   struct phm_samu_clock_voltage_dependency_table *tab)
2733 {
2734 	uint16_t i;
2735 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2736 
2737 	if (tab)
2738 		for (i = 0; i < tab->count; i++)
2739 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2740 							&data->vddc_leakage);
2741 
2742 	return 0;
2743 }
2744 
2745 static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr,
2746 				  struct phm_acp_clock_voltage_dependency_table *tab)
2747 {
2748 	uint16_t i;
2749 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2750 
2751 	if (tab)
2752 		for (i = 0; i < tab->count; i++)
2753 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v,
2754 					&data->vddc_leakage);
2755 
2756 	return 0;
2757 }
2758 
2759 static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr,
2760 				  struct phm_clock_and_voltage_limits *tab)
2761 {
2762 	uint32_t vddc, vddci;
2763 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2764 
2765 	if (tab) {
2766 		vddc = tab->vddc;
2767 		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc,
2768 						   &data->vddc_leakage);
2769 		tab->vddc = vddc;
2770 		vddci = tab->vddci;
2771 		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci,
2772 						   &data->vddci_leakage);
2773 		tab->vddci = vddci;
2774 	}
2775 
2776 	return 0;
2777 }
2778 
2779 static int smu7_patch_cac_vddc(struct pp_hwmgr *hwmgr, struct phm_cac_leakage_table *tab)
2780 {
2781 	uint32_t i;
2782 	uint32_t vddc;
2783 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2784 
2785 	if (tab) {
2786 		for (i = 0; i < tab->count; i++) {
2787 			vddc = (uint32_t)(tab->entries[i].Vddc);
2788 			smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, &data->vddc_leakage);
2789 			tab->entries[i].Vddc = (uint16_t)vddc;
2790 		}
2791 	}
2792 
2793 	return 0;
2794 }
2795 
2796 static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr)
2797 {
2798 	int tmp;
2799 
2800 	tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk);
2801 	if (tmp)
2802 		return -EINVAL;
2803 
2804 	tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk);
2805 	if (tmp)
2806 		return -EINVAL;
2807 
2808 	tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
2809 	if (tmp)
2810 		return -EINVAL;
2811 
2812 	tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk);
2813 	if (tmp)
2814 		return -EINVAL;
2815 
2816 	tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table);
2817 	if (tmp)
2818 		return -EINVAL;
2819 
2820 	tmp = smu7_patch_uvd_vddc(hwmgr, hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
2821 	if (tmp)
2822 		return -EINVAL;
2823 
2824 	tmp = smu7_patch_samu_vddc(hwmgr, hwmgr->dyn_state.samu_clock_voltage_dependency_table);
2825 	if (tmp)
2826 		return -EINVAL;
2827 
2828 	tmp = smu7_patch_acp_vddc(hwmgr, hwmgr->dyn_state.acp_clock_voltage_dependency_table);
2829 	if (tmp)
2830 		return -EINVAL;
2831 
2832 	tmp = smu7_patch_vddc_shed_limit(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table);
2833 	if (tmp)
2834 		return -EINVAL;
2835 
2836 	tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_ac);
2837 	if (tmp)
2838 		return -EINVAL;
2839 
2840 	tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_dc);
2841 	if (tmp)
2842 		return -EINVAL;
2843 
2844 	tmp = smu7_patch_cac_vddc(hwmgr, hwmgr->dyn_state.cac_leakage_table);
2845 	if (tmp)
2846 		return -EINVAL;
2847 
2848 	return 0;
2849 }
2850 
2851 
2852 static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr)
2853 {
2854 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2855 
2856 	struct phm_clock_voltage_dependency_table *allowed_sclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
2857 	struct phm_clock_voltage_dependency_table *allowed_mclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
2858 	struct phm_clock_voltage_dependency_table *allowed_mclk_vddci_table = hwmgr->dyn_state.vddci_dependency_on_mclk;
2859 
2860 	PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table != NULL,
2861 		"VDDC dependency on SCLK table is missing. This table is mandatory",
2862 		return -EINVAL);
2863 	PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table->count >= 1,
2864 		"VDDC dependency on SCLK table has to have is missing. This table is mandatory",
2865 		return -EINVAL);
2866 
2867 	PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table != NULL,
2868 		"VDDC dependency on MCLK table is missing. This table is mandatory",
2869 		return -EINVAL);
2870 	PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table->count >= 1,
2871 		"VDD dependency on MCLK table has to have is missing. This table is mandatory",
2872 		return -EINVAL);
2873 
2874 	data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[0].v;
2875 	data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
2876 
2877 	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
2878 		allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk;
2879 	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
2880 		allowed_mclk_vddc_table->entries[allowed_mclk_vddc_table->count - 1].clk;
2881 	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
2882 		allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v;
2883 
2884 	if (allowed_mclk_vddci_table != NULL && allowed_mclk_vddci_table->count >= 1) {
2885 		data->min_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[0].v;
2886 		data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v;
2887 	}
2888 
2889 	if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1)
2890 		hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v;
2891 
2892 	return 0;
2893 }
2894 
2895 static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
2896 {
2897 	kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
2898 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
2899 	kfree(hwmgr->backend);
2900 	hwmgr->backend = NULL;
2901 
2902 	return 0;
2903 }
2904 
2905 static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr)
2906 {
2907 	uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id;
2908 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2909 	int i;
2910 
2911 	if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) {
2912 		for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {
2913 			virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
2914 			if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci,
2915 								virtual_voltage_id,
2916 								efuse_voltage_id) == 0) {
2917 				if (vddc != 0 && vddc != virtual_voltage_id) {
2918 					data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
2919 					data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
2920 					data->vddc_leakage.count++;
2921 				}
2922 				if (vddci != 0 && vddci != virtual_voltage_id) {
2923 					data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci;
2924 					data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id;
2925 					data->vddci_leakage.count++;
2926 				}
2927 			}
2928 		}
2929 	}
2930 	return 0;
2931 }
2932 
2933 #define LEAKAGE_ID_MSB			463
2934 #define LEAKAGE_ID_LSB			454
2935 
2936 static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr)
2937 {
2938 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
2939 	uint32_t efuse;
2940 	uint16_t offset;
2941 	int ret = 0;
2942 
2943 	if (data->disable_edc_leakage_controller)
2944 		return 0;
2945 
2946 	ret = atomctrl_get_edc_hilo_leakage_offset_table(hwmgr,
2947 							 &data->edc_hilo_leakage_offset_from_vbios);
2948 	if (ret)
2949 		return ret;
2950 
2951 	if (data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset &&
2952 	    data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) {
2953 		atomctrl_read_efuse(hwmgr, LEAKAGE_ID_LSB, LEAKAGE_ID_MSB, &efuse);
2954 		if (efuse < data->edc_hilo_leakage_offset_from_vbios.usHiLoLeakageThreshold)
2955 			offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset;
2956 		else
2957 			offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset;
2958 
2959 		ret = atomctrl_get_edc_leakage_table(hwmgr,
2960 						     &data->edc_leakage_table,
2961 						     offset);
2962 		if (ret)
2963 			return ret;
2964 	}
2965 
2966 	return ret;
2967 }
2968 
2969 static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
2970 {
2971 	struct smu7_hwmgr *data;
2972 	int result = 0;
2973 
2974 	data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL);
2975 	if (data == NULL)
2976 		return -ENOMEM;
2977 
2978 	hwmgr->backend = data;
2979 	smu7_patch_voltage_workaround(hwmgr);
2980 	smu7_init_dpm_defaults(hwmgr);
2981 
2982 	/* Get leakage voltage based on leakage ID. */
2983 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2984 			PHM_PlatformCaps_EVV)) {
2985 		result = smu7_get_evv_voltages(hwmgr);
2986 		if (result) {
2987 			pr_info("Get EVV Voltage Failed.  Abort Driver loading!\n");
2988 			return -EINVAL;
2989 		}
2990 	} else {
2991 		smu7_get_elb_voltages(hwmgr);
2992 	}
2993 
2994 	if (hwmgr->pp_table_version == PP_TABLE_V1) {
2995 		smu7_complete_dependency_tables(hwmgr);
2996 		smu7_set_private_data_based_on_pptable_v1(hwmgr);
2997 	} else if (hwmgr->pp_table_version == PP_TABLE_V0) {
2998 		smu7_patch_dependency_tables_with_leakage(hwmgr);
2999 		smu7_set_private_data_based_on_pptable_v0(hwmgr);
3000 	}
3001 
3002 	/* Initalize Dynamic State Adjustment Rule Settings */
3003 	result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
3004 
3005 	if (0 == result) {
3006 		struct amdgpu_device *adev = hwmgr->adev;
3007 
3008 		data->is_tlu_enabled = false;
3009 
3010 		hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
3011 							SMU7_MAX_HARDWARE_POWERLEVELS;
3012 		hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
3013 		hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
3014 
3015 		data->pcie_gen_cap = adev->pm.pcie_gen_mask;
3016 		if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
3017 			data->pcie_spc_cap = 20;
3018 		else
3019 			data->pcie_spc_cap = 16;
3020 		data->pcie_lane_cap = adev->pm.pcie_mlw_mask;
3021 
3022 		hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
3023 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
3024 		hwmgr->platform_descriptor.clockStep.engineClock = 500;
3025 		hwmgr->platform_descriptor.clockStep.memoryClock = 500;
3026 		smu7_thermal_parameter_init(hwmgr);
3027 	} else {
3028 		/* Ignore return value in here, we are cleaning up a mess. */
3029 		smu7_hwmgr_backend_fini(hwmgr);
3030 	}
3031 
3032 	result = smu7_update_edc_leakage_table(hwmgr);
3033 	if (result)
3034 		return result;
3035 
3036 	return 0;
3037 }
3038 
3039 static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr)
3040 {
3041 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3042 	uint32_t level, tmp;
3043 
3044 	if (!data->pcie_dpm_key_disabled) {
3045 		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3046 			level = 0;
3047 			tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
3048 			while (tmp >>= 1)
3049 				level++;
3050 
3051 			if (level)
3052 				smum_send_msg_to_smc_with_parameter(hwmgr,
3053 						PPSMC_MSG_PCIeDPM_ForceLevel, level,
3054 						NULL);
3055 		}
3056 	}
3057 
3058 	if (!data->sclk_dpm_key_disabled) {
3059 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3060 			level = 0;
3061 			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
3062 			while (tmp >>= 1)
3063 				level++;
3064 
3065 			if (level)
3066 				smum_send_msg_to_smc_with_parameter(hwmgr,
3067 						PPSMC_MSG_SCLKDPM_SetEnabledMask,
3068 						(1 << level),
3069 						NULL);
3070 		}
3071 	}
3072 
3073 	if (!data->mclk_dpm_key_disabled) {
3074 		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3075 			level = 0;
3076 			tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
3077 			while (tmp >>= 1)
3078 				level++;
3079 
3080 			if (level)
3081 				smum_send_msg_to_smc_with_parameter(hwmgr,
3082 						PPSMC_MSG_MCLKDPM_SetEnabledMask,
3083 						(1 << level),
3084 						NULL);
3085 		}
3086 	}
3087 
3088 	return 0;
3089 }
3090 
3091 static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
3092 {
3093 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3094 
3095 	if (hwmgr->pp_table_version == PP_TABLE_V1)
3096 		phm_apply_dal_min_voltage_request(hwmgr);
3097 /* TO DO  for v0 iceland and Ci*/
3098 
3099 	if (!data->sclk_dpm_key_disabled) {
3100 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
3101 			smum_send_msg_to_smc_with_parameter(hwmgr,
3102 					PPSMC_MSG_SCLKDPM_SetEnabledMask,
3103 					data->dpm_level_enable_mask.sclk_dpm_enable_mask,
3104 					NULL);
3105 	}
3106 
3107 	if (!data->mclk_dpm_key_disabled) {
3108 		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask)
3109 			smum_send_msg_to_smc_with_parameter(hwmgr,
3110 					PPSMC_MSG_MCLKDPM_SetEnabledMask,
3111 					data->dpm_level_enable_mask.mclk_dpm_enable_mask,
3112 					NULL);
3113 	}
3114 
3115 	return 0;
3116 }
3117 
3118 static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
3119 {
3120 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3121 
3122 	if (!smum_is_dpm_running(hwmgr))
3123 		return -EINVAL;
3124 
3125 	if (!data->pcie_dpm_key_disabled) {
3126 		smum_send_msg_to_smc(hwmgr,
3127 				PPSMC_MSG_PCIeDPM_UnForceLevel,
3128 				NULL);
3129 	}
3130 
3131 	return smu7_upload_dpm_level_enable_mask(hwmgr);
3132 }
3133 
3134 static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3135 {
3136 	struct smu7_hwmgr *data =
3137 			(struct smu7_hwmgr *)(hwmgr->backend);
3138 	uint32_t level;
3139 
3140 	if (!data->sclk_dpm_key_disabled)
3141 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3142 			level = phm_get_lowest_enabled_level(hwmgr,
3143 							      data->dpm_level_enable_mask.sclk_dpm_enable_mask);
3144 			smum_send_msg_to_smc_with_parameter(hwmgr,
3145 							    PPSMC_MSG_SCLKDPM_SetEnabledMask,
3146 							    (1 << level),
3147 							    NULL);
3148 
3149 	}
3150 
3151 	if (!data->mclk_dpm_key_disabled) {
3152 		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3153 			level = phm_get_lowest_enabled_level(hwmgr,
3154 							      data->dpm_level_enable_mask.mclk_dpm_enable_mask);
3155 			smum_send_msg_to_smc_with_parameter(hwmgr,
3156 							    PPSMC_MSG_MCLKDPM_SetEnabledMask,
3157 							    (1 << level),
3158 							    NULL);
3159 		}
3160 	}
3161 
3162 	if (!data->pcie_dpm_key_disabled) {
3163 		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3164 			level = phm_get_lowest_enabled_level(hwmgr,
3165 							      data->dpm_level_enable_mask.pcie_dpm_enable_mask);
3166 			smum_send_msg_to_smc_with_parameter(hwmgr,
3167 							    PPSMC_MSG_PCIeDPM_ForceLevel,
3168 							    (level),
3169 							    NULL);
3170 		}
3171 	}
3172 
3173 	return 0;
3174 }
3175 
3176 static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
3177 				uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask)
3178 {
3179 	uint32_t percentage;
3180 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3181 	struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table;
3182 	int32_t tmp_mclk;
3183 	int32_t tmp_sclk;
3184 	int32_t count;
3185 
3186 	if (golden_dpm_table->mclk_table.count < 1)
3187 		return -EINVAL;
3188 
3189 	percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value /
3190 			golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
3191 
3192 	if (golden_dpm_table->mclk_table.count == 1) {
3193 		percentage = 70;
3194 		tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value;
3195 		*mclk_mask = golden_dpm_table->mclk_table.count - 1;
3196 	} else {
3197 		tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value;
3198 		*mclk_mask = golden_dpm_table->mclk_table.count - 2;
3199 	}
3200 
3201 	tmp_sclk = tmp_mclk * percentage / 100;
3202 
3203 	if (hwmgr->pp_table_version == PP_TABLE_V0) {
3204 		for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1;
3205 			count >= 0; count--) {
3206 			if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) {
3207 				*sclk_mask = count;
3208 				break;
3209 			}
3210 		}
3211 		if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
3212 			*sclk_mask = 0;
3213 
3214 		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3215 			*sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1;
3216 	} else if (hwmgr->pp_table_version == PP_TABLE_V1) {
3217 		struct phm_ppt_v1_information *table_info =
3218 				(struct phm_ppt_v1_information *)(hwmgr->pptable);
3219 
3220 		for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) {
3221 			if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) {
3222 				*sclk_mask = count;
3223 				break;
3224 			}
3225 		}
3226 		if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
3227 			*sclk_mask = 0;
3228 
3229 		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3230 			*sclk_mask = table_info->vdd_dep_on_sclk->count - 1;
3231 	}
3232 
3233 	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
3234 		*mclk_mask = 0;
3235 	else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3236 		*mclk_mask = golden_dpm_table->mclk_table.count - 1;
3237 
3238 	*pcie_mask = data->dpm_table.pcie_speed_table.count - 1;
3239 
3240 	return 0;
3241 }
3242 
3243 static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr,
3244 				enum amd_dpm_forced_level level)
3245 {
3246 	int ret = 0;
3247 	uint32_t sclk_mask = 0;
3248 	uint32_t mclk_mask = 0;
3249 	uint32_t pcie_mask = 0;
3250 
3251 	switch (level) {
3252 	case AMD_DPM_FORCED_LEVEL_HIGH:
3253 		ret = smu7_force_dpm_highest(hwmgr);
3254 		break;
3255 	case AMD_DPM_FORCED_LEVEL_LOW:
3256 		ret = smu7_force_dpm_lowest(hwmgr);
3257 		break;
3258 	case AMD_DPM_FORCED_LEVEL_AUTO:
3259 		ret = smu7_unforce_dpm_levels(hwmgr);
3260 		break;
3261 	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
3262 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
3263 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
3264 	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
3265 		ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask);
3266 		if (ret)
3267 			return ret;
3268 		smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
3269 		smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
3270 		smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask);
3271 		break;
3272 	case AMD_DPM_FORCED_LEVEL_MANUAL:
3273 	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
3274 	default:
3275 		break;
3276 	}
3277 
3278 	if (!ret) {
3279 		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3280 			smu7_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
3281 		else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
3282 			smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr);
3283 	}
3284 	return ret;
3285 }
3286 
3287 static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr)
3288 {
3289 	return sizeof(struct smu7_power_state);
3290 }
3291 
3292 static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr,
3293 				 uint32_t vblank_time_us)
3294 {
3295 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3296 	uint32_t switch_limit_us;
3297 
3298 	switch (hwmgr->chip_id) {
3299 	case CHIP_POLARIS10:
3300 	case CHIP_POLARIS11:
3301 	case CHIP_POLARIS12:
3302 		if (hwmgr->is_kicker || (hwmgr->chip_id == CHIP_POLARIS12))
3303 			switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
3304 		else
3305 			switch_limit_us = data->is_memory_gddr5 ? 200 : 150;
3306 		break;
3307 	case CHIP_VEGAM:
3308 		switch_limit_us = 30;
3309 		break;
3310 	default:
3311 		switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
3312 		break;
3313 	}
3314 
3315 	if (vblank_time_us < switch_limit_us)
3316 		return true;
3317 	else
3318 		return false;
3319 }
3320 
3321 static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
3322 				struct pp_power_state *request_ps,
3323 			const struct pp_power_state *current_ps)
3324 {
3325 	struct amdgpu_device *adev = hwmgr->adev;
3326 	struct smu7_power_state *smu7_ps =
3327 				cast_phw_smu7_power_state(&request_ps->hardware);
3328 	uint32_t sclk;
3329 	uint32_t mclk;
3330 	struct PP_Clocks minimum_clocks = {0};
3331 	bool disable_mclk_switching;
3332 	bool disable_mclk_switching_for_frame_lock;
3333 	bool disable_mclk_switching_for_display;
3334 	const struct phm_clock_and_voltage_limits *max_limits;
3335 	uint32_t i;
3336 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3337 	struct phm_ppt_v1_information *table_info =
3338 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
3339 	int32_t count;
3340 	int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
3341 	uint32_t latency;
3342 	bool latency_allowed = false;
3343 
3344 	data->battery_state = (PP_StateUILabel_Battery ==
3345 			request_ps->classification.ui_label);
3346 	data->mclk_ignore_signal = false;
3347 
3348 	max_limits = adev->pm.ac_power ?
3349 			&(hwmgr->dyn_state.max_clock_voltage_on_ac) :
3350 			&(hwmgr->dyn_state.max_clock_voltage_on_dc);
3351 
3352 	/* Cap clock DPM tables at DC MAX if it is in DC. */
3353 	if (!adev->pm.ac_power) {
3354 		for (i = 0; i < smu7_ps->performance_level_count; i++) {
3355 			if (smu7_ps->performance_levels[i].memory_clock > max_limits->mclk)
3356 				smu7_ps->performance_levels[i].memory_clock = max_limits->mclk;
3357 			if (smu7_ps->performance_levels[i].engine_clock > max_limits->sclk)
3358 				smu7_ps->performance_levels[i].engine_clock = max_limits->sclk;
3359 		}
3360 	}
3361 
3362 	minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock;
3363 	minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
3364 
3365 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3366 			PHM_PlatformCaps_StablePState)) {
3367 		max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
3368 		stable_pstate_sclk = (max_limits->sclk * 75) / 100;
3369 
3370 		for (count = table_info->vdd_dep_on_sclk->count - 1;
3371 				count >= 0; count--) {
3372 			if (stable_pstate_sclk >=
3373 					table_info->vdd_dep_on_sclk->entries[count].clk) {
3374 				stable_pstate_sclk =
3375 						table_info->vdd_dep_on_sclk->entries[count].clk;
3376 				break;
3377 			}
3378 		}
3379 
3380 		if (count < 0)
3381 			stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
3382 
3383 		stable_pstate_mclk = max_limits->mclk;
3384 
3385 		minimum_clocks.engineClock = stable_pstate_sclk;
3386 		minimum_clocks.memoryClock = stable_pstate_mclk;
3387 	}
3388 
3389 	disable_mclk_switching_for_frame_lock = phm_cap_enabled(
3390 				    hwmgr->platform_descriptor.platformCaps,
3391 				    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
3392 
3393 	disable_mclk_switching_for_display = ((1 < hwmgr->display_config->num_display) &&
3394 						!hwmgr->display_config->multi_monitor_in_sync) ||
3395 						(hwmgr->display_config->num_display &&
3396 						smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time));
3397 
3398 	disable_mclk_switching = disable_mclk_switching_for_frame_lock ||
3399 					 disable_mclk_switching_for_display;
3400 
3401 	if (hwmgr->display_config->num_display == 0) {
3402 		if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM)
3403 			data->mclk_ignore_signal = true;
3404 		else
3405 			disable_mclk_switching = false;
3406 	}
3407 
3408 	sclk = smu7_ps->performance_levels[0].engine_clock;
3409 	mclk = smu7_ps->performance_levels[0].memory_clock;
3410 
3411 	if (disable_mclk_switching &&
3412 	    (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
3413 	    hwmgr->chip_id <= CHIP_VEGAM)))
3414 		mclk = smu7_ps->performance_levels
3415 		[smu7_ps->performance_level_count - 1].memory_clock;
3416 
3417 	if (sclk < minimum_clocks.engineClock)
3418 		sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
3419 				max_limits->sclk : minimum_clocks.engineClock;
3420 
3421 	if (mclk < minimum_clocks.memoryClock)
3422 		mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
3423 				max_limits->mclk : minimum_clocks.memoryClock;
3424 
3425 	smu7_ps->performance_levels[0].engine_clock = sclk;
3426 	smu7_ps->performance_levels[0].memory_clock = mclk;
3427 
3428 	smu7_ps->performance_levels[1].engine_clock =
3429 		(smu7_ps->performance_levels[1].engine_clock >=
3430 				smu7_ps->performance_levels[0].engine_clock) ?
3431 						smu7_ps->performance_levels[1].engine_clock :
3432 						smu7_ps->performance_levels[0].engine_clock;
3433 
3434 	if (disable_mclk_switching) {
3435 		if (mclk < smu7_ps->performance_levels[1].memory_clock)
3436 			mclk = smu7_ps->performance_levels[1].memory_clock;
3437 
3438 		if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) {
3439 			if (disable_mclk_switching_for_display) {
3440 				/* Find the lowest MCLK frequency that is within
3441 				 * the tolerable latency defined in DAL
3442 				 */
3443 				latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3444 				for (i = 0; i < data->mclk_latency_table.count; i++) {
3445 					if (data->mclk_latency_table.entries[i].latency <= latency) {
3446 						latency_allowed = true;
3447 
3448 						if ((data->mclk_latency_table.entries[i].frequency >=
3449 								smu7_ps->performance_levels[0].memory_clock) &&
3450 						    (data->mclk_latency_table.entries[i].frequency <=
3451 								smu7_ps->performance_levels[1].memory_clock)) {
3452 							mclk = data->mclk_latency_table.entries[i].frequency;
3453 							break;
3454 						}
3455 					}
3456 				}
3457 				if ((i >= data->mclk_latency_table.count - 1) && !latency_allowed) {
3458 					data->mclk_ignore_signal = true;
3459 				} else {
3460 					data->mclk_ignore_signal = false;
3461 				}
3462 			}
3463 
3464 			if (disable_mclk_switching_for_frame_lock)
3465 				mclk = smu7_ps->performance_levels[1].memory_clock;
3466 		}
3467 
3468 		smu7_ps->performance_levels[0].memory_clock = mclk;
3469 
3470 		if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
3471 		      hwmgr->chip_id <= CHIP_VEGAM))
3472 			smu7_ps->performance_levels[1].memory_clock = mclk;
3473 	} else {
3474 		if (smu7_ps->performance_levels[1].memory_clock <
3475 				smu7_ps->performance_levels[0].memory_clock)
3476 			smu7_ps->performance_levels[1].memory_clock =
3477 					smu7_ps->performance_levels[0].memory_clock;
3478 	}
3479 
3480 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3481 			PHM_PlatformCaps_StablePState)) {
3482 		for (i = 0; i < smu7_ps->performance_level_count; i++) {
3483 			smu7_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
3484 			smu7_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
3485 			smu7_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
3486 			smu7_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
3487 		}
3488 	}
3489 	return 0;
3490 }
3491 
3492 
3493 static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
3494 {
3495 	struct pp_power_state  *ps;
3496 	struct smu7_power_state  *smu7_ps;
3497 
3498 	if (hwmgr == NULL)
3499 		return -EINVAL;
3500 
3501 	ps = hwmgr->request_ps;
3502 
3503 	if (ps == NULL)
3504 		return -EINVAL;
3505 
3506 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
3507 
3508 	if (low)
3509 		return smu7_ps->performance_levels[0].memory_clock;
3510 	else
3511 		return smu7_ps->performance_levels
3512 				[smu7_ps->performance_level_count-1].memory_clock;
3513 }
3514 
3515 static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
3516 {
3517 	struct pp_power_state  *ps;
3518 	struct smu7_power_state  *smu7_ps;
3519 
3520 	if (hwmgr == NULL)
3521 		return -EINVAL;
3522 
3523 	ps = hwmgr->request_ps;
3524 
3525 	if (ps == NULL)
3526 		return -EINVAL;
3527 
3528 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
3529 
3530 	if (low)
3531 		return smu7_ps->performance_levels[0].engine_clock;
3532 	else
3533 		return smu7_ps->performance_levels
3534 				[smu7_ps->performance_level_count-1].engine_clock;
3535 }
3536 
3537 static int smu7_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
3538 					struct pp_hw_power_state *hw_ps)
3539 {
3540 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3541 	struct smu7_power_state *ps = (struct smu7_power_state *)hw_ps;
3542 	ATOM_FIRMWARE_INFO_V2_2 *fw_info;
3543 	uint16_t size;
3544 	uint8_t frev, crev;
3545 	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
3546 
3547 	/* First retrieve the Boot clocks and VDDC from the firmware info table.
3548 	 * We assume here that fw_info is unchanged if this call fails.
3549 	 */
3550 	fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)smu_atom_get_data_table(hwmgr->adev, index,
3551 			&size, &frev, &crev);
3552 	if (!fw_info)
3553 		/* During a test, there is no firmware info table. */
3554 		return 0;
3555 
3556 	/* Patch the state. */
3557 	data->vbios_boot_state.sclk_bootup_value =
3558 			le32_to_cpu(fw_info->ulDefaultEngineClock);
3559 	data->vbios_boot_state.mclk_bootup_value =
3560 			le32_to_cpu(fw_info->ulDefaultMemoryClock);
3561 	data->vbios_boot_state.mvdd_bootup_value =
3562 			le16_to_cpu(fw_info->usBootUpMVDDCVoltage);
3563 	data->vbios_boot_state.vddc_bootup_value =
3564 			le16_to_cpu(fw_info->usBootUpVDDCVoltage);
3565 	data->vbios_boot_state.vddci_bootup_value =
3566 			le16_to_cpu(fw_info->usBootUpVDDCIVoltage);
3567 	data->vbios_boot_state.pcie_gen_bootup_value =
3568 			smu7_get_current_pcie_speed(hwmgr);
3569 
3570 	data->vbios_boot_state.pcie_lane_bootup_value =
3571 			(uint16_t)smu7_get_current_pcie_lane_number(hwmgr);
3572 
3573 	/* set boot power state */
3574 	ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
3575 	ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
3576 	ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
3577 	ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
3578 
3579 	return 0;
3580 }
3581 
3582 static int smu7_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
3583 {
3584 	int result;
3585 	unsigned long ret = 0;
3586 
3587 	if (hwmgr->pp_table_version == PP_TABLE_V0) {
3588 		result = pp_tables_get_num_of_entries(hwmgr, &ret);
3589 		return result ? 0 : ret;
3590 	} else if (hwmgr->pp_table_version == PP_TABLE_V1) {
3591 		result = get_number_of_powerplay_table_entries_v1_0(hwmgr);
3592 		return result;
3593 	}
3594 	return 0;
3595 }
3596 
3597 static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr,
3598 		void *state, struct pp_power_state *power_state,
3599 		void *pp_table, uint32_t classification_flag)
3600 {
3601 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3602 	struct smu7_power_state  *smu7_power_state =
3603 			(struct smu7_power_state *)(&(power_state->hardware));
3604 	struct smu7_performance_level *performance_level;
3605 	ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
3606 	ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
3607 			(ATOM_Tonga_POWERPLAYTABLE *)pp_table;
3608 	PPTable_Generic_SubTable_Header *sclk_dep_table =
3609 			(PPTable_Generic_SubTable_Header *)
3610 			(((unsigned long)powerplay_table) +
3611 				le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
3612 
3613 	ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
3614 			(ATOM_Tonga_MCLK_Dependency_Table *)
3615 			(((unsigned long)powerplay_table) +
3616 				le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
3617 
3618 	/* The following fields are not initialized here: id orderedList allStatesList */
3619 	power_state->classification.ui_label =
3620 			(le16_to_cpu(state_entry->usClassification) &
3621 			ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
3622 			ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
3623 	power_state->classification.flags = classification_flag;
3624 	/* NOTE: There is a classification2 flag in BIOS that is not being used right now */
3625 
3626 	power_state->classification.temporary_state = false;
3627 	power_state->classification.to_be_deleted = false;
3628 
3629 	power_state->validation.disallowOnDC =
3630 			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
3631 					ATOM_Tonga_DISALLOW_ON_DC));
3632 
3633 	power_state->pcie.lanes = 0;
3634 
3635 	power_state->display.disableFrameModulation = false;
3636 	power_state->display.limitRefreshrate = false;
3637 	power_state->display.enableVariBright =
3638 			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
3639 					ATOM_Tonga_ENABLE_VARIBRIGHT));
3640 
3641 	power_state->validation.supportedPowerLevels = 0;
3642 	power_state->uvd_clocks.VCLK = 0;
3643 	power_state->uvd_clocks.DCLK = 0;
3644 	power_state->temperatures.min = 0;
3645 	power_state->temperatures.max = 0;
3646 
3647 	performance_level = &(smu7_power_state->performance_levels
3648 			[smu7_power_state->performance_level_count++]);
3649 
3650 	PP_ASSERT_WITH_CODE(
3651 			(smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)),
3652 			"Performance levels exceeds SMC limit!",
3653 			return -EINVAL);
3654 
3655 	PP_ASSERT_WITH_CODE(
3656 			(smu7_power_state->performance_level_count <
3657 					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
3658 			"Performance levels exceeds Driver limit!",
3659 			return -EINVAL);
3660 
3661 	/* Performance levels are arranged from low to high. */
3662 	performance_level->memory_clock = mclk_dep_table->entries
3663 			[state_entry->ucMemoryClockIndexLow].ulMclk;
3664 	if (sclk_dep_table->ucRevId == 0)
3665 		performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
3666 			[state_entry->ucEngineClockIndexLow].ulSclk;
3667 	else if (sclk_dep_table->ucRevId == 1)
3668 		performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
3669 			[state_entry->ucEngineClockIndexLow].ulSclk;
3670 	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
3671 			state_entry->ucPCIEGenLow);
3672 	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
3673 			state_entry->ucPCIELaneLow);
3674 
3675 	performance_level = &(smu7_power_state->performance_levels
3676 			[smu7_power_state->performance_level_count++]);
3677 	performance_level->memory_clock = mclk_dep_table->entries
3678 			[state_entry->ucMemoryClockIndexHigh].ulMclk;
3679 
3680 	if (sclk_dep_table->ucRevId == 0)
3681 		performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
3682 			[state_entry->ucEngineClockIndexHigh].ulSclk;
3683 	else if (sclk_dep_table->ucRevId == 1)
3684 		performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
3685 			[state_entry->ucEngineClockIndexHigh].ulSclk;
3686 
3687 	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
3688 			state_entry->ucPCIEGenHigh);
3689 	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
3690 			state_entry->ucPCIELaneHigh);
3691 
3692 	return 0;
3693 }
3694 
3695 static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr,
3696 		unsigned long entry_index, struct pp_power_state *state)
3697 {
3698 	int result;
3699 	struct smu7_power_state *ps;
3700 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3701 	struct phm_ppt_v1_information *table_info =
3702 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
3703 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
3704 			table_info->vdd_dep_on_mclk;
3705 
3706 	state->hardware.magic = PHM_VIslands_Magic;
3707 
3708 	ps = (struct smu7_power_state *)(&state->hardware);
3709 
3710 	result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state,
3711 			smu7_get_pp_table_entry_callback_func_v1);
3712 
3713 	/* This is the earliest time we have all the dependency table and the VBIOS boot state
3714 	 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
3715 	 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
3716 	 */
3717 	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
3718 		if (dep_mclk_table->entries[0].clk !=
3719 				data->vbios_boot_state.mclk_bootup_value)
3720 			pr_debug("Single MCLK entry VDDCI/MCLK dependency table "
3721 					"does not match VBIOS boot MCLK level");
3722 		if (dep_mclk_table->entries[0].vddci !=
3723 				data->vbios_boot_state.vddci_bootup_value)
3724 			pr_debug("Single VDDCI entry VDDCI/MCLK dependency table "
3725 					"does not match VBIOS boot VDDCI level");
3726 	}
3727 
3728 	/* set DC compatible flag if this state supports DC */
3729 	if (!state->validation.disallowOnDC)
3730 		ps->dc_compatible = true;
3731 
3732 	if (state->classification.flags & PP_StateClassificationFlag_ACPI)
3733 		data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
3734 
3735 	ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3736 	ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3737 
3738 	if (!result) {
3739 		uint32_t i;
3740 
3741 		switch (state->classification.ui_label) {
3742 		case PP_StateUILabel_Performance:
3743 			data->use_pcie_performance_levels = true;
3744 			for (i = 0; i < ps->performance_level_count; i++) {
3745 				if (data->pcie_gen_performance.max <
3746 						ps->performance_levels[i].pcie_gen)
3747 					data->pcie_gen_performance.max =
3748 							ps->performance_levels[i].pcie_gen;
3749 
3750 				if (data->pcie_gen_performance.min >
3751 						ps->performance_levels[i].pcie_gen)
3752 					data->pcie_gen_performance.min =
3753 							ps->performance_levels[i].pcie_gen;
3754 
3755 				if (data->pcie_lane_performance.max <
3756 						ps->performance_levels[i].pcie_lane)
3757 					data->pcie_lane_performance.max =
3758 							ps->performance_levels[i].pcie_lane;
3759 				if (data->pcie_lane_performance.min >
3760 						ps->performance_levels[i].pcie_lane)
3761 					data->pcie_lane_performance.min =
3762 							ps->performance_levels[i].pcie_lane;
3763 			}
3764 			break;
3765 		case PP_StateUILabel_Battery:
3766 			data->use_pcie_power_saving_levels = true;
3767 
3768 			for (i = 0; i < ps->performance_level_count; i++) {
3769 				if (data->pcie_gen_power_saving.max <
3770 						ps->performance_levels[i].pcie_gen)
3771 					data->pcie_gen_power_saving.max =
3772 							ps->performance_levels[i].pcie_gen;
3773 
3774 				if (data->pcie_gen_power_saving.min >
3775 						ps->performance_levels[i].pcie_gen)
3776 					data->pcie_gen_power_saving.min =
3777 							ps->performance_levels[i].pcie_gen;
3778 
3779 				if (data->pcie_lane_power_saving.max <
3780 						ps->performance_levels[i].pcie_lane)
3781 					data->pcie_lane_power_saving.max =
3782 							ps->performance_levels[i].pcie_lane;
3783 
3784 				if (data->pcie_lane_power_saving.min >
3785 						ps->performance_levels[i].pcie_lane)
3786 					data->pcie_lane_power_saving.min =
3787 							ps->performance_levels[i].pcie_lane;
3788 			}
3789 			break;
3790 		default:
3791 			break;
3792 		}
3793 	}
3794 	return 0;
3795 }
3796 
3797 static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr,
3798 					struct pp_hw_power_state *power_state,
3799 					unsigned int index, const void *clock_info)
3800 {
3801 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3802 	struct smu7_power_state  *ps = cast_phw_smu7_power_state(power_state);
3803 	const ATOM_PPLIB_CI_CLOCK_INFO *visland_clk_info = clock_info;
3804 	struct smu7_performance_level *performance_level;
3805 	uint32_t engine_clock, memory_clock;
3806 	uint16_t pcie_gen_from_bios;
3807 
3808 	engine_clock = visland_clk_info->ucEngineClockHigh << 16 | visland_clk_info->usEngineClockLow;
3809 	memory_clock = visland_clk_info->ucMemoryClockHigh << 16 | visland_clk_info->usMemoryClockLow;
3810 
3811 	if (!(data->mc_micro_code_feature & DISABLE_MC_LOADMICROCODE) && memory_clock > data->highest_mclk)
3812 		data->highest_mclk = memory_clock;
3813 
3814 	PP_ASSERT_WITH_CODE(
3815 			(ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)),
3816 			"Performance levels exceeds SMC limit!",
3817 			return -EINVAL);
3818 
3819 	PP_ASSERT_WITH_CODE(
3820 			(ps->performance_level_count <
3821 					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
3822 			"Performance levels exceeds Driver limit, Skip!",
3823 			return 0);
3824 
3825 	performance_level = &(ps->performance_levels
3826 			[ps->performance_level_count++]);
3827 
3828 	/* Performance levels are arranged from low to high. */
3829 	performance_level->memory_clock = memory_clock;
3830 	performance_level->engine_clock = engine_clock;
3831 
3832 	pcie_gen_from_bios = visland_clk_info->ucPCIEGen;
3833 
3834 	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, pcie_gen_from_bios);
3835 	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, visland_clk_info->usPCIELane);
3836 
3837 	return 0;
3838 }
3839 
3840 static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr,
3841 		unsigned long entry_index, struct pp_power_state *state)
3842 {
3843 	int result;
3844 	struct smu7_power_state *ps;
3845 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
3846 	struct phm_clock_voltage_dependency_table *dep_mclk_table =
3847 			hwmgr->dyn_state.vddci_dependency_on_mclk;
3848 
3849 	memset(&state->hardware, 0x00, sizeof(struct pp_hw_power_state));
3850 
3851 	state->hardware.magic = PHM_VIslands_Magic;
3852 
3853 	ps = (struct smu7_power_state *)(&state->hardware);
3854 
3855 	result = pp_tables_get_entry(hwmgr, entry_index, state,
3856 			smu7_get_pp_table_entry_callback_func_v0);
3857 
3858 	/*
3859 	 * This is the earliest time we have all the dependency table
3860 	 * and the VBIOS boot state as
3861 	 * PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot
3862 	 * state if there is only one VDDCI/MCLK level, check if it's
3863 	 * the same as VBIOS boot state
3864 	 */
3865 	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
3866 		if (dep_mclk_table->entries[0].clk !=
3867 				data->vbios_boot_state.mclk_bootup_value)
3868 			pr_debug("Single MCLK entry VDDCI/MCLK dependency table "
3869 					"does not match VBIOS boot MCLK level");
3870 		if (dep_mclk_table->entries[0].v !=
3871 				data->vbios_boot_state.vddci_bootup_value)
3872 			pr_debug("Single VDDCI entry VDDCI/MCLK dependency table "
3873 					"does not match VBIOS boot VDDCI level");
3874 	}
3875 
3876 	/* set DC compatible flag if this state supports DC */
3877 	if (!state->validation.disallowOnDC)
3878 		ps->dc_compatible = true;
3879 
3880 	if (state->classification.flags & PP_StateClassificationFlag_ACPI)
3881 		data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
3882 
3883 	ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
3884 	ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
3885 
3886 	if (!result) {
3887 		uint32_t i;
3888 
3889 		switch (state->classification.ui_label) {
3890 		case PP_StateUILabel_Performance:
3891 			data->use_pcie_performance_levels = true;
3892 
3893 			for (i = 0; i < ps->performance_level_count; i++) {
3894 				if (data->pcie_gen_performance.max <
3895 						ps->performance_levels[i].pcie_gen)
3896 					data->pcie_gen_performance.max =
3897 							ps->performance_levels[i].pcie_gen;
3898 
3899 				if (data->pcie_gen_performance.min >
3900 						ps->performance_levels[i].pcie_gen)
3901 					data->pcie_gen_performance.min =
3902 							ps->performance_levels[i].pcie_gen;
3903 
3904 				if (data->pcie_lane_performance.max <
3905 						ps->performance_levels[i].pcie_lane)
3906 					data->pcie_lane_performance.max =
3907 							ps->performance_levels[i].pcie_lane;
3908 
3909 				if (data->pcie_lane_performance.min >
3910 						ps->performance_levels[i].pcie_lane)
3911 					data->pcie_lane_performance.min =
3912 							ps->performance_levels[i].pcie_lane;
3913 			}
3914 			break;
3915 		case PP_StateUILabel_Battery:
3916 			data->use_pcie_power_saving_levels = true;
3917 
3918 			for (i = 0; i < ps->performance_level_count; i++) {
3919 				if (data->pcie_gen_power_saving.max <
3920 						ps->performance_levels[i].pcie_gen)
3921 					data->pcie_gen_power_saving.max =
3922 							ps->performance_levels[i].pcie_gen;
3923 
3924 				if (data->pcie_gen_power_saving.min >
3925 						ps->performance_levels[i].pcie_gen)
3926 					data->pcie_gen_power_saving.min =
3927 							ps->performance_levels[i].pcie_gen;
3928 
3929 				if (data->pcie_lane_power_saving.max <
3930 						ps->performance_levels[i].pcie_lane)
3931 					data->pcie_lane_power_saving.max =
3932 							ps->performance_levels[i].pcie_lane;
3933 
3934 				if (data->pcie_lane_power_saving.min >
3935 						ps->performance_levels[i].pcie_lane)
3936 					data->pcie_lane_power_saving.min =
3937 							ps->performance_levels[i].pcie_lane;
3938 			}
3939 			break;
3940 		default:
3941 			break;
3942 		}
3943 	}
3944 	return 0;
3945 }
3946 
3947 static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr,
3948 		unsigned long entry_index, struct pp_power_state *state)
3949 {
3950 	if (hwmgr->pp_table_version == PP_TABLE_V0)
3951 		return smu7_get_pp_table_entry_v0(hwmgr, entry_index, state);
3952 	else if (hwmgr->pp_table_version == PP_TABLE_V1)
3953 		return smu7_get_pp_table_entry_v1(hwmgr, entry_index, state);
3954 
3955 	return 0;
3956 }
3957 
3958 static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query)
3959 {
3960 	struct amdgpu_device *adev = hwmgr->adev;
3961 	int i;
3962 	u32 tmp = 0;
3963 
3964 	if (!query)
3965 		return -EINVAL;
3966 
3967 	/*
3968 	 * PPSMC_MSG_GetCurrPkgPwr is not supported on:
3969 	 *  - Hawaii
3970 	 *  - Bonaire
3971 	 *  - Fiji
3972 	 *  - Tonga
3973 	 */
3974 	if ((adev->asic_type != CHIP_HAWAII) &&
3975 	    (adev->asic_type != CHIP_BONAIRE) &&
3976 	    (adev->asic_type != CHIP_FIJI) &&
3977 	    (adev->asic_type != CHIP_TONGA)) {
3978 		smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0, &tmp);
3979 		*query = tmp;
3980 
3981 		if (tmp != 0)
3982 			return 0;
3983 	}
3984 
3985 	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart, NULL);
3986 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
3987 							ixSMU_PM_STATUS_95, 0);
3988 
3989 	for (i = 0; i < 10; i++) {
3990 		msleep(500);
3991 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample, NULL);
3992 		tmp = cgs_read_ind_register(hwmgr->device,
3993 						CGS_IND_REG__SMC,
3994 						ixSMU_PM_STATUS_95);
3995 		if (tmp != 0)
3996 			break;
3997 	}
3998 	*query = tmp;
3999 
4000 	return 0;
4001 }
4002 
4003 static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx,
4004 			    void *value, int *size)
4005 {
4006 	uint32_t sclk, mclk, activity_percent;
4007 	uint32_t offset, val_vid;
4008 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4009 
4010 	/* size must be at least 4 bytes for all sensors */
4011 	if (*size < 4)
4012 		return -EINVAL;
4013 
4014 	switch (idx) {
4015 	case AMDGPU_PP_SENSOR_GFX_SCLK:
4016 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &sclk);
4017 		*((uint32_t *)value) = sclk;
4018 		*size = 4;
4019 		return 0;
4020 	case AMDGPU_PP_SENSOR_GFX_MCLK:
4021 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &mclk);
4022 		*((uint32_t *)value) = mclk;
4023 		*size = 4;
4024 		return 0;
4025 	case AMDGPU_PP_SENSOR_GPU_LOAD:
4026 	case AMDGPU_PP_SENSOR_MEM_LOAD:
4027 		offset = data->soft_regs_start + smum_get_offsetof(hwmgr,
4028 								SMU_SoftRegisters,
4029 								(idx == AMDGPU_PP_SENSOR_GPU_LOAD) ?
4030 								AverageGraphicsActivity:
4031 								AverageMemoryActivity);
4032 
4033 		activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
4034 		activity_percent += 0x80;
4035 		activity_percent >>= 8;
4036 		*((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
4037 		*size = 4;
4038 		return 0;
4039 	case AMDGPU_PP_SENSOR_GPU_TEMP:
4040 		*((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr);
4041 		*size = 4;
4042 		return 0;
4043 	case AMDGPU_PP_SENSOR_UVD_POWER:
4044 		*((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
4045 		*size = 4;
4046 		return 0;
4047 	case AMDGPU_PP_SENSOR_VCE_POWER:
4048 		*((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
4049 		*size = 4;
4050 		return 0;
4051 	case AMDGPU_PP_SENSOR_GPU_POWER:
4052 		return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
4053 	case AMDGPU_PP_SENSOR_VDDGFX:
4054 		if ((data->vr_config & VRCONF_VDDGFX_MASK) ==
4055 		    (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT))
4056 			val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,
4057 					CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID);
4058 		else
4059 			val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,
4060 					CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE1_VID);
4061 
4062 		*((uint32_t *)value) = (uint32_t)convert_to_vddc(val_vid);
4063 		return 0;
4064 	default:
4065 		return -EOPNOTSUPP;
4066 	}
4067 }
4068 
4069 static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
4070 {
4071 	const struct phm_set_power_state_input *states =
4072 			(const struct phm_set_power_state_input *)input;
4073 	const struct smu7_power_state *smu7_ps =
4074 			cast_const_phw_smu7_power_state(states->pnew_state);
4075 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4076 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
4077 	uint32_t sclk = smu7_ps->performance_levels
4078 			[smu7_ps->performance_level_count - 1].engine_clock;
4079 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
4080 	uint32_t mclk = smu7_ps->performance_levels
4081 			[smu7_ps->performance_level_count - 1].memory_clock;
4082 	struct PP_Clocks min_clocks = {0};
4083 	uint32_t i;
4084 
4085 	for (i = 0; i < sclk_table->count; i++) {
4086 		if (sclk == sclk_table->dpm_levels[i].value)
4087 			break;
4088 	}
4089 
4090 	if (i >= sclk_table->count) {
4091 		if (sclk > sclk_table->dpm_levels[i-1].value) {
4092 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
4093 			sclk_table->dpm_levels[i-1].value = sclk;
4094 		}
4095 	} else {
4096 	/* TODO: Check SCLK in DAL's minimum clocks
4097 	 * in case DeepSleep divider update is required.
4098 	 */
4099 		if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR &&
4100 			(min_clocks.engineClockInSR >= SMU7_MINIMUM_ENGINE_CLOCK ||
4101 				data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK))
4102 			data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
4103 	}
4104 
4105 	for (i = 0; i < mclk_table->count; i++) {
4106 		if (mclk == mclk_table->dpm_levels[i].value)
4107 			break;
4108 	}
4109 
4110 	if (i >= mclk_table->count) {
4111 		if (mclk > mclk_table->dpm_levels[i-1].value) {
4112 			data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
4113 			mclk_table->dpm_levels[i-1].value = mclk;
4114 		}
4115 	}
4116 
4117 	if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4118 		data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
4119 
4120 	return 0;
4121 }
4122 
4123 static uint16_t smu7_get_maximum_link_speed(struct pp_hwmgr *hwmgr,
4124 		const struct smu7_power_state *smu7_ps)
4125 {
4126 	uint32_t i;
4127 	uint32_t sclk, max_sclk = 0;
4128 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4129 	struct smu7_dpm_table *dpm_table = &data->dpm_table;
4130 
4131 	for (i = 0; i < smu7_ps->performance_level_count; i++) {
4132 		sclk = smu7_ps->performance_levels[i].engine_clock;
4133 		if (max_sclk < sclk)
4134 			max_sclk = sclk;
4135 	}
4136 
4137 	for (i = 0; i < dpm_table->sclk_table.count; i++) {
4138 		if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk)
4139 			return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ?
4140 					dpm_table->pcie_speed_table.dpm_levels
4141 					[dpm_table->pcie_speed_table.count - 1].value :
4142 					dpm_table->pcie_speed_table.dpm_levels[i].value);
4143 	}
4144 
4145 	return 0;
4146 }
4147 
4148 static int smu7_request_link_speed_change_before_state_change(
4149 		struct pp_hwmgr *hwmgr, const void *input)
4150 {
4151 	const struct phm_set_power_state_input *states =
4152 			(const struct phm_set_power_state_input *)input;
4153 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4154 	const struct smu7_power_state *smu7_nps =
4155 			cast_const_phw_smu7_power_state(states->pnew_state);
4156 	const struct smu7_power_state *polaris10_cps =
4157 			cast_const_phw_smu7_power_state(states->pcurrent_state);
4158 
4159 	uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_nps);
4160 	uint16_t current_link_speed;
4161 
4162 	if (data->force_pcie_gen == PP_PCIEGenInvalid)
4163 		current_link_speed = smu7_get_maximum_link_speed(hwmgr, polaris10_cps);
4164 	else
4165 		current_link_speed = data->force_pcie_gen;
4166 
4167 	data->force_pcie_gen = PP_PCIEGenInvalid;
4168 	data->pspp_notify_required = false;
4169 
4170 	if (target_link_speed > current_link_speed) {
4171 		switch (target_link_speed) {
4172 #ifdef CONFIG_ACPI
4173 		case PP_PCIEGen3:
4174 			if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN3, false))
4175 				break;
4176 			data->force_pcie_gen = PP_PCIEGen2;
4177 			if (current_link_speed == PP_PCIEGen2)
4178 				break;
4179 			fallthrough;
4180 		case PP_PCIEGen2:
4181 			if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN2, false))
4182 				break;
4183 			fallthrough;
4184 #endif
4185 		default:
4186 			data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr);
4187 			break;
4188 		}
4189 	} else {
4190 		if (target_link_speed < current_link_speed)
4191 			data->pspp_notify_required = true;
4192 	}
4193 
4194 	return 0;
4195 }
4196 
4197 static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
4198 {
4199 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4200 
4201 	if (0 == data->need_update_smu7_dpm_table)
4202 		return 0;
4203 
4204 	if ((0 == data->sclk_dpm_key_disabled) &&
4205 		(data->need_update_smu7_dpm_table &
4206 			(DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK))) {
4207 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4208 				"Trying to freeze SCLK DPM when DPM is disabled",
4209 				);
4210 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4211 				PPSMC_MSG_SCLKDPM_FreezeLevel,
4212 				NULL),
4213 				"Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",
4214 				return -EINVAL);
4215 	}
4216 
4217 	if ((0 == data->mclk_dpm_key_disabled) &&
4218 		!data->mclk_ignore_signal &&
4219 		(data->need_update_smu7_dpm_table &
4220 		 DPMTABLE_OD_UPDATE_MCLK)) {
4221 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4222 				"Trying to freeze MCLK DPM when DPM is disabled",
4223 				);
4224 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4225 				PPSMC_MSG_MCLKDPM_FreezeLevel,
4226 				NULL),
4227 				"Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",
4228 				return -EINVAL);
4229 	}
4230 
4231 	return 0;
4232 }
4233 
4234 static int smu7_populate_and_upload_sclk_mclk_dpm_levels(
4235 		struct pp_hwmgr *hwmgr, const void *input)
4236 {
4237 	int result = 0;
4238 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4239 	struct smu7_dpm_table *dpm_table = &data->dpm_table;
4240 	uint32_t count;
4241 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4242 	struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
4243 	struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
4244 
4245 	if (0 == data->need_update_smu7_dpm_table)
4246 		return 0;
4247 
4248 	if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
4249 		for (count = 0; count < dpm_table->sclk_table.count; count++) {
4250 			dpm_table->sclk_table.dpm_levels[count].enabled = odn_sclk_table->entries[count].enabled;
4251 			dpm_table->sclk_table.dpm_levels[count].value = odn_sclk_table->entries[count].clock;
4252 		}
4253 	}
4254 
4255 	if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
4256 		for (count = 0; count < dpm_table->mclk_table.count; count++) {
4257 			dpm_table->mclk_table.dpm_levels[count].enabled = odn_mclk_table->entries[count].enabled;
4258 			dpm_table->mclk_table.dpm_levels[count].value = odn_mclk_table->entries[count].clock;
4259 		}
4260 	}
4261 
4262 	if (data->need_update_smu7_dpm_table &
4263 			(DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK)) {
4264 		result = smum_populate_all_graphic_levels(hwmgr);
4265 		PP_ASSERT_WITH_CODE((0 == result),
4266 				"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
4267 				return result);
4268 	}
4269 
4270 	if (data->need_update_smu7_dpm_table &
4271 			(DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) {
4272 		/*populate MCLK dpm table to SMU7 */
4273 		result = smum_populate_all_memory_levels(hwmgr);
4274 		PP_ASSERT_WITH_CODE((0 == result),
4275 				"Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
4276 				return result);
4277 	}
4278 
4279 	return result;
4280 }
4281 
4282 static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
4283 			  struct smu7_single_dpm_table *dpm_table,
4284 			uint32_t low_limit, uint32_t high_limit)
4285 {
4286 	uint32_t i;
4287 
4288 	/* force the trim if mclk_switching is disabled to prevent flicker */
4289 	bool force_trim = (low_limit == high_limit);
4290 	for (i = 0; i < dpm_table->count; i++) {
4291 	/*skip the trim if od is enabled*/
4292 		if ((!hwmgr->od_enabled || force_trim)
4293 			&& (dpm_table->dpm_levels[i].value < low_limit
4294 			|| dpm_table->dpm_levels[i].value > high_limit))
4295 			dpm_table->dpm_levels[i].enabled = false;
4296 		else
4297 			dpm_table->dpm_levels[i].enabled = true;
4298 	}
4299 
4300 	return 0;
4301 }
4302 
4303 static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr,
4304 		const struct smu7_power_state *smu7_ps)
4305 {
4306 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4307 	uint32_t high_limit_count;
4308 
4309 	PP_ASSERT_WITH_CODE((smu7_ps->performance_level_count >= 1),
4310 			"power state did not have any performance level",
4311 			return -EINVAL);
4312 
4313 	high_limit_count = (1 == smu7_ps->performance_level_count) ? 0 : 1;
4314 
4315 	smu7_trim_single_dpm_states(hwmgr,
4316 			&(data->dpm_table.sclk_table),
4317 			smu7_ps->performance_levels[0].engine_clock,
4318 			smu7_ps->performance_levels[high_limit_count].engine_clock);
4319 
4320 	smu7_trim_single_dpm_states(hwmgr,
4321 			&(data->dpm_table.mclk_table),
4322 			smu7_ps->performance_levels[0].memory_clock,
4323 			smu7_ps->performance_levels[high_limit_count].memory_clock);
4324 
4325 	return 0;
4326 }
4327 
4328 static int smu7_generate_dpm_level_enable_mask(
4329 		struct pp_hwmgr *hwmgr, const void *input)
4330 {
4331 	int result = 0;
4332 	const struct phm_set_power_state_input *states =
4333 			(const struct phm_set_power_state_input *)input;
4334 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4335 	const struct smu7_power_state *smu7_ps =
4336 			cast_const_phw_smu7_power_state(states->pnew_state);
4337 
4338 
4339 	result = smu7_trim_dpm_states(hwmgr, smu7_ps);
4340 	if (result)
4341 		return result;
4342 
4343 	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
4344 			phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
4345 	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
4346 			phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
4347 	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
4348 			phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
4349 
4350 	return 0;
4351 }
4352 
4353 static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
4354 {
4355 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4356 
4357 	if (0 == data->need_update_smu7_dpm_table)
4358 		return 0;
4359 
4360 	if ((0 == data->sclk_dpm_key_disabled) &&
4361 		(data->need_update_smu7_dpm_table &
4362 		(DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK))) {
4363 
4364 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4365 				"Trying to Unfreeze SCLK DPM when DPM is disabled",
4366 				);
4367 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4368 				PPSMC_MSG_SCLKDPM_UnfreezeLevel,
4369 				NULL),
4370 			"Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",
4371 			return -EINVAL);
4372 	}
4373 
4374 	if ((0 == data->mclk_dpm_key_disabled) &&
4375 		!data->mclk_ignore_signal &&
4376 		(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
4377 
4378 		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
4379 				"Trying to Unfreeze MCLK DPM when DPM is disabled",
4380 				);
4381 		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr,
4382 				PPSMC_MSG_MCLKDPM_UnfreezeLevel,
4383 				NULL),
4384 		    "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
4385 		    return -EINVAL);
4386 	}
4387 
4388 	data->need_update_smu7_dpm_table &= DPMTABLE_OD_UPDATE_VDDC;
4389 
4390 	return 0;
4391 }
4392 
4393 static int smu7_notify_link_speed_change_after_state_change(
4394 		struct pp_hwmgr *hwmgr, const void *input)
4395 {
4396 	const struct phm_set_power_state_input *states =
4397 			(const struct phm_set_power_state_input *)input;
4398 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4399 	const struct smu7_power_state *smu7_ps =
4400 			cast_const_phw_smu7_power_state(states->pnew_state);
4401 	uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_ps);
4402 	uint8_t  request;
4403 
4404 	if (data->pspp_notify_required) {
4405 		if (target_link_speed == PP_PCIEGen3)
4406 			request = PCIE_PERF_REQ_GEN3;
4407 		else if (target_link_speed == PP_PCIEGen2)
4408 			request = PCIE_PERF_REQ_GEN2;
4409 		else
4410 			request = PCIE_PERF_REQ_GEN1;
4411 
4412 		if (request == PCIE_PERF_REQ_GEN1 &&
4413 				smu7_get_current_pcie_speed(hwmgr) > 0)
4414 			return 0;
4415 
4416 #ifdef CONFIG_ACPI
4417 		if (amdgpu_acpi_pcie_performance_request(hwmgr->adev, request, false)) {
4418 			if (PP_PCIEGen2 == target_link_speed)
4419 				pr_info("PSPP request to switch to Gen2 from Gen3 Failed!");
4420 			else
4421 				pr_info("PSPP request to switch to Gen1 from Gen2 Failed!");
4422 		}
4423 #endif
4424 	}
4425 
4426 	return 0;
4427 }
4428 
4429 static int smu7_notify_no_display(struct pp_hwmgr *hwmgr)
4430 {
4431 	return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL) == 0) ?  0 : -EINVAL;
4432 }
4433 
4434 static int smu7_notify_has_display(struct pp_hwmgr *hwmgr)
4435 {
4436 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4437 
4438 	if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) {
4439 		if (hwmgr->chip_id == CHIP_VEGAM)
4440 			smum_send_msg_to_smc_with_parameter(hwmgr,
4441 					(PPSMC_Msg)PPSMC_MSG_SetVBITimeout_VEGAM, data->frame_time_x2,
4442 					NULL);
4443 		else
4444 			smum_send_msg_to_smc_with_parameter(hwmgr,
4445 					(PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2,
4446 					NULL);
4447 		data->last_sent_vbi_timeout = data->frame_time_x2;
4448 	}
4449 
4450 	return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ?  0 : -EINVAL;
4451 }
4452 
4453 static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr)
4454 {
4455 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4456 	int result = 0;
4457 
4458 	if (data->mclk_ignore_signal)
4459 		result = smu7_notify_no_display(hwmgr);
4460 	else
4461 		result = smu7_notify_has_display(hwmgr);
4462 
4463 	return result;
4464 }
4465 
4466 static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
4467 {
4468 	int tmp_result, result = 0;
4469 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4470 
4471 	tmp_result = smu7_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
4472 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4473 			"Failed to find DPM states clocks in DPM table!",
4474 			result = tmp_result);
4475 
4476 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4477 			PHM_PlatformCaps_PCIEPerformanceRequest)) {
4478 		tmp_result =
4479 			smu7_request_link_speed_change_before_state_change(hwmgr, input);
4480 		PP_ASSERT_WITH_CODE((0 == tmp_result),
4481 				"Failed to request link speed change before state change!",
4482 				result = tmp_result);
4483 	}
4484 
4485 	tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr);
4486 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4487 			"Failed to freeze SCLK MCLK DPM!", result = tmp_result);
4488 
4489 	tmp_result = smu7_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
4490 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4491 			"Failed to populate and upload SCLK MCLK DPM levels!",
4492 			result = tmp_result);
4493 
4494 	/*
4495 	 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag.
4496 	 * That effectively disables AVFS feature.
4497 	 */
4498 	if (hwmgr->hardcode_pp_table != NULL)
4499 		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
4500 
4501 	tmp_result = smu7_update_avfs(hwmgr);
4502 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4503 			"Failed to update avfs voltages!",
4504 			result = tmp_result);
4505 
4506 	tmp_result = smu7_generate_dpm_level_enable_mask(hwmgr, input);
4507 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4508 			"Failed to generate DPM level enabled mask!",
4509 			result = tmp_result);
4510 
4511 	tmp_result = smum_update_sclk_threshold(hwmgr);
4512 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4513 			"Failed to update SCLK threshold!",
4514 			result = tmp_result);
4515 
4516 	tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr);
4517 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4518 			"Failed to unfreeze SCLK MCLK DPM!",
4519 			result = tmp_result);
4520 
4521 	tmp_result = smu7_upload_dpm_level_enable_mask(hwmgr);
4522 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4523 			"Failed to upload DPM level enabled mask!",
4524 			result = tmp_result);
4525 
4526 	tmp_result = smu7_notify_smc_display(hwmgr);
4527 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4528 			"Failed to notify smc display settings!",
4529 			result = tmp_result);
4530 
4531 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4532 			PHM_PlatformCaps_PCIEPerformanceRequest)) {
4533 		tmp_result =
4534 			smu7_notify_link_speed_change_after_state_change(hwmgr, input);
4535 		PP_ASSERT_WITH_CODE((0 == tmp_result),
4536 				"Failed to notify link speed change after state change!",
4537 				result = tmp_result);
4538 	}
4539 	data->apply_optimized_settings = false;
4540 	return result;
4541 }
4542 
4543 static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
4544 {
4545 	hwmgr->thermal_controller.
4546 	advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
4547 
4548 	return smum_send_msg_to_smc_with_parameter(hwmgr,
4549 			PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm,
4550 			NULL);
4551 }
4552 
4553 static int
4554 smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
4555 {
4556 	return 0;
4557 }
4558 
4559 /**
4560  * smu7_program_display_gap - Programs the display gap
4561  *
4562  * @hwmgr:  the address of the powerplay hardware manager.
4563  * Return:   always OK
4564  */
4565 static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
4566 {
4567 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4568 	uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
4569 	uint32_t display_gap2;
4570 	uint32_t pre_vbi_time_in_us;
4571 	uint32_t frame_time_in_us;
4572 	uint32_t ref_clock, refresh_rate;
4573 
4574 	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (hwmgr->display_config->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE);
4575 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap);
4576 
4577 	ref_clock =  amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
4578 	refresh_rate = hwmgr->display_config->vrefresh;
4579 
4580 	if (0 == refresh_rate)
4581 		refresh_rate = 60;
4582 
4583 	frame_time_in_us = 1000000 / refresh_rate;
4584 
4585 	pre_vbi_time_in_us = frame_time_in_us - 200 - hwmgr->display_config->min_vblank_time;
4586 
4587 	data->frame_time_x2 = frame_time_in_us * 2 / 100;
4588 
4589 	if (data->frame_time_x2 < 280) {
4590 		pr_debug("%s: enforce minimal VBITimeout: %d -> 280\n", __func__, data->frame_time_x2);
4591 		data->frame_time_x2 = 280;
4592 	}
4593 
4594 	display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
4595 
4596 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2);
4597 
4598 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4599 			data->soft_regs_start + smum_get_offsetof(hwmgr,
4600 							SMU_SoftRegisters,
4601 							PreVBlankGap), 0x64);
4602 
4603 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
4604 			data->soft_regs_start + smum_get_offsetof(hwmgr,
4605 							SMU_SoftRegisters,
4606 							VBlankTimeout),
4607 					(frame_time_in_us - pre_vbi_time_in_us));
4608 
4609 	return 0;
4610 }
4611 
4612 static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
4613 {
4614 	return smu7_program_display_gap(hwmgr);
4615 }
4616 
4617 /**
4618  * smu7_set_max_fan_rpm_output - Set maximum target operating fan output RPM
4619  *
4620  * @hwmgr:  the address of the powerplay hardware manager.
4621  * @us_max_fan_rpm:  max operating fan RPM value.
4622  * Return:   The response that came from the SMC.
4623  */
4624 static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm)
4625 {
4626 	hwmgr->thermal_controller.
4627 	advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm;
4628 
4629 	return smum_send_msg_to_smc_with_parameter(hwmgr,
4630 			PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm,
4631 			NULL);
4632 }
4633 
4634 static const struct amdgpu_irq_src_funcs smu7_irq_funcs = {
4635 	.process = phm_irq_process,
4636 };
4637 
4638 static int smu7_register_irq_handlers(struct pp_hwmgr *hwmgr)
4639 {
4640 	struct amdgpu_irq_src *source =
4641 		kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL);
4642 
4643 	if (!source)
4644 		return -ENOMEM;
4645 
4646 	source->funcs = &smu7_irq_funcs;
4647 
4648 	amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4649 			AMDGPU_IRQ_CLIENTID_LEGACY,
4650 			VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH,
4651 			source);
4652 	amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4653 			AMDGPU_IRQ_CLIENTID_LEGACY,
4654 			VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW,
4655 			source);
4656 
4657 	/* Register CTF(GPIO_19) interrupt */
4658 	amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
4659 			AMDGPU_IRQ_CLIENTID_LEGACY,
4660 			VISLANDS30_IV_SRCID_GPIO_19,
4661 			source);
4662 
4663 	return 0;
4664 }
4665 
4666 static bool
4667 smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
4668 {
4669 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4670 	bool is_update_required = false;
4671 
4672 	if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
4673 		is_update_required = true;
4674 
4675 	if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh)
4676 		is_update_required = true;
4677 
4678 	if (hwmgr->chip_id >= CHIP_POLARIS10 &&
4679 	    hwmgr->chip_id <= CHIP_VEGAM &&
4680 	    data->last_sent_vbi_timeout != data->frame_time_x2)
4681 		is_update_required = true;
4682 
4683 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
4684 		if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr &&
4685 			(data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK ||
4686 			hwmgr->display_config->min_core_set_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK))
4687 			is_update_required = true;
4688 	}
4689 	return is_update_required;
4690 }
4691 
4692 static inline bool smu7_are_power_levels_equal(const struct smu7_performance_level *pl1,
4693 							   const struct smu7_performance_level *pl2)
4694 {
4695 	return ((pl1->memory_clock == pl2->memory_clock) &&
4696 		  (pl1->engine_clock == pl2->engine_clock) &&
4697 		  (pl1->pcie_gen == pl2->pcie_gen) &&
4698 		  (pl1->pcie_lane == pl2->pcie_lane));
4699 }
4700 
4701 static int smu7_check_states_equal(struct pp_hwmgr *hwmgr,
4702 		const struct pp_hw_power_state *pstate1,
4703 		const struct pp_hw_power_state *pstate2, bool *equal)
4704 {
4705 	const struct smu7_power_state *psa;
4706 	const struct smu7_power_state *psb;
4707 	int i;
4708 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4709 
4710 	if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
4711 		return -EINVAL;
4712 
4713 	psa = cast_const_phw_smu7_power_state(pstate1);
4714 	psb = cast_const_phw_smu7_power_state(pstate2);
4715 	/* If the two states don't even have the same number of performance levels they cannot be the same state. */
4716 	if (psa->performance_level_count != psb->performance_level_count) {
4717 		*equal = false;
4718 		return 0;
4719 	}
4720 
4721 	for (i = 0; i < psa->performance_level_count; i++) {
4722 		if (!smu7_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
4723 			/* If we have found even one performance level pair that is different the states are different. */
4724 			*equal = false;
4725 			return 0;
4726 		}
4727 	}
4728 
4729 	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
4730 	*equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
4731 	*equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
4732 	*equal &= (psa->sclk_threshold == psb->sclk_threshold);
4733 	/* For OD call, set value based on flag */
4734 	*equal &= !(data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK |
4735 							DPMTABLE_OD_UPDATE_MCLK |
4736 							DPMTABLE_OD_UPDATE_VDDC));
4737 
4738 	return 0;
4739 }
4740 
4741 static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr)
4742 {
4743 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4744 
4745 	uint32_t tmp;
4746 
4747 	/* Read MC indirect register offset 0x9F bits [3:0] to see
4748 	 * if VBIOS has already loaded a full version of MC ucode
4749 	 * or not.
4750 	 */
4751 
4752 	smu7_get_mc_microcode_version(hwmgr);
4753 
4754 	data->need_long_memory_training = false;
4755 
4756 	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX,
4757 							ixMC_IO_DEBUG_UP_13);
4758 	tmp = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
4759 
4760 	if (tmp & (1 << 23)) {
4761 		data->mem_latency_high = MEM_LATENCY_HIGH;
4762 		data->mem_latency_low = MEM_LATENCY_LOW;
4763 		if ((hwmgr->chip_id == CHIP_POLARIS10) ||
4764 		    (hwmgr->chip_id == CHIP_POLARIS11) ||
4765 		    (hwmgr->chip_id == CHIP_POLARIS12))
4766 			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC, NULL);
4767 	} else {
4768 		data->mem_latency_high = 330;
4769 		data->mem_latency_low = 330;
4770 		if ((hwmgr->chip_id == CHIP_POLARIS10) ||
4771 		    (hwmgr->chip_id == CHIP_POLARIS11) ||
4772 		    (hwmgr->chip_id == CHIP_POLARIS12))
4773 			smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC, NULL);
4774 	}
4775 
4776 	return 0;
4777 }
4778 
4779 static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr)
4780 {
4781 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4782 
4783 	data->clock_registers.vCG_SPLL_FUNC_CNTL         =
4784 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL);
4785 	data->clock_registers.vCG_SPLL_FUNC_CNTL_2       =
4786 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2);
4787 	data->clock_registers.vCG_SPLL_FUNC_CNTL_3       =
4788 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3);
4789 	data->clock_registers.vCG_SPLL_FUNC_CNTL_4       =
4790 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4);
4791 	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM   =
4792 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM);
4793 	data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 =
4794 		cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2);
4795 	data->clock_registers.vDLL_CNTL                  =
4796 		cgs_read_register(hwmgr->device, mmDLL_CNTL);
4797 	data->clock_registers.vMCLK_PWRMGT_CNTL          =
4798 		cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL);
4799 	data->clock_registers.vMPLL_AD_FUNC_CNTL         =
4800 		cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL);
4801 	data->clock_registers.vMPLL_DQ_FUNC_CNTL         =
4802 		cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL);
4803 	data->clock_registers.vMPLL_FUNC_CNTL            =
4804 		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL);
4805 	data->clock_registers.vMPLL_FUNC_CNTL_1          =
4806 		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1);
4807 	data->clock_registers.vMPLL_FUNC_CNTL_2          =
4808 		cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2);
4809 	data->clock_registers.vMPLL_SS1                  =
4810 		cgs_read_register(hwmgr->device, mmMPLL_SS1);
4811 	data->clock_registers.vMPLL_SS2                  =
4812 		cgs_read_register(hwmgr->device, mmMPLL_SS2);
4813 	return 0;
4814 
4815 }
4816 
4817 /**
4818  * smu7_get_memory_type - Find out if memory is GDDR5.
4819  *
4820  * @hwmgr:  the address of the powerplay hardware manager.
4821  * Return:   always 0
4822  */
4823 static int smu7_get_memory_type(struct pp_hwmgr *hwmgr)
4824 {
4825 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4826 	struct amdgpu_device *adev = hwmgr->adev;
4827 
4828 	data->is_memory_gddr5 = (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5);
4829 
4830 	return 0;
4831 }
4832 
4833 /**
4834  * smu7_enable_acpi_power_management - Enables Dynamic Power Management by SMC
4835  *
4836  * @hwmgr:  the address of the powerplay hardware manager.
4837  * Return:   always 0
4838  */
4839 static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
4840 {
4841 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
4842 			GENERAL_PWRMGT, STATIC_PM_EN, 1);
4843 
4844 	return 0;
4845 }
4846 
4847 /**
4848  * smu7_init_power_gate_state - Initialize PowerGating States for different engines
4849  *
4850  * @hwmgr:  the address of the powerplay hardware manager.
4851  * Return:   always 0
4852  */
4853 static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr)
4854 {
4855 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4856 
4857 	data->uvd_power_gated = false;
4858 	data->vce_power_gated = false;
4859 
4860 	return 0;
4861 }
4862 
4863 static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr)
4864 {
4865 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4866 
4867 	data->low_sclk_interrupt_threshold = 0;
4868 	return 0;
4869 }
4870 
4871 static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
4872 {
4873 	int tmp_result, result = 0;
4874 
4875 	smu7_check_mc_firmware(hwmgr);
4876 
4877 	tmp_result = smu7_read_clock_registers(hwmgr);
4878 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4879 			"Failed to read clock registers!", result = tmp_result);
4880 
4881 	tmp_result = smu7_get_memory_type(hwmgr);
4882 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4883 			"Failed to get memory type!", result = tmp_result);
4884 
4885 	tmp_result = smu7_enable_acpi_power_management(hwmgr);
4886 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4887 			"Failed to enable ACPI power management!", result = tmp_result);
4888 
4889 	tmp_result = smu7_init_power_gate_state(hwmgr);
4890 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4891 			"Failed to init power gate state!", result = tmp_result);
4892 
4893 	tmp_result = smu7_get_mc_microcode_version(hwmgr);
4894 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4895 			"Failed to get MC microcode version!", result = tmp_result);
4896 
4897 	tmp_result = smu7_init_sclk_threshold(hwmgr);
4898 	PP_ASSERT_WITH_CODE((0 == tmp_result),
4899 			"Failed to init sclk threshold!", result = tmp_result);
4900 
4901 	return result;
4902 }
4903 
4904 static int smu7_force_clock_level(struct pp_hwmgr *hwmgr,
4905 		enum pp_clock_type type, uint32_t mask)
4906 {
4907 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4908 
4909 	if (mask == 0)
4910 		return -EINVAL;
4911 
4912 	switch (type) {
4913 	case PP_SCLK:
4914 		if (!data->sclk_dpm_key_disabled)
4915 			smum_send_msg_to_smc_with_parameter(hwmgr,
4916 					PPSMC_MSG_SCLKDPM_SetEnabledMask,
4917 					data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask,
4918 					NULL);
4919 		break;
4920 	case PP_MCLK:
4921 		if (!data->mclk_dpm_key_disabled)
4922 			smum_send_msg_to_smc_with_parameter(hwmgr,
4923 					PPSMC_MSG_MCLKDPM_SetEnabledMask,
4924 					data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask,
4925 					NULL);
4926 		break;
4927 	case PP_PCIE:
4928 	{
4929 		uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
4930 
4931 		if (!data->pcie_dpm_key_disabled) {
4932 			if (fls(tmp) != ffs(tmp))
4933 				smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel,
4934 						NULL);
4935 			else
4936 				smum_send_msg_to_smc_with_parameter(hwmgr,
4937 					PPSMC_MSG_PCIeDPM_ForceLevel,
4938 					fls(tmp) - 1,
4939 					NULL);
4940 		}
4941 		break;
4942 	}
4943 	default:
4944 		break;
4945 	}
4946 
4947 	return 0;
4948 }
4949 
4950 static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
4951 		enum pp_clock_type type, char *buf)
4952 {
4953 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4954 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
4955 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
4956 	struct smu7_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table);
4957 	struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4958 	struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels);
4959 	struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels);
4960 	int size = 0;
4961 	uint32_t i, now, clock, pcie_speed;
4962 
4963 	switch (type) {
4964 	case PP_SCLK:
4965 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &clock);
4966 
4967 		for (i = 0; i < sclk_table->count; i++) {
4968 			if (clock > sclk_table->dpm_levels[i].value)
4969 				continue;
4970 			break;
4971 		}
4972 		now = i;
4973 
4974 		for (i = 0; i < sclk_table->count; i++)
4975 			size += sprintf(buf + size, "%d: %uMhz %s\n",
4976 					i, sclk_table->dpm_levels[i].value / 100,
4977 					(i == now) ? "*" : "");
4978 		break;
4979 	case PP_MCLK:
4980 		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &clock);
4981 
4982 		for (i = 0; i < mclk_table->count; i++) {
4983 			if (clock > mclk_table->dpm_levels[i].value)
4984 				continue;
4985 			break;
4986 		}
4987 		now = i;
4988 
4989 		for (i = 0; i < mclk_table->count; i++)
4990 			size += sprintf(buf + size, "%d: %uMhz %s\n",
4991 					i, mclk_table->dpm_levels[i].value / 100,
4992 					(i == now) ? "*" : "");
4993 		break;
4994 	case PP_PCIE:
4995 		pcie_speed = smu7_get_current_pcie_speed(hwmgr);
4996 		for (i = 0; i < pcie_table->count; i++) {
4997 			if (pcie_speed != pcie_table->dpm_levels[i].value)
4998 				continue;
4999 			break;
5000 		}
5001 		now = i;
5002 
5003 		for (i = 0; i < pcie_table->count; i++)
5004 			size += sprintf(buf + size, "%d: %s %s\n", i,
5005 					(pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" :
5006 					(pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" :
5007 					(pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "",
5008 					(i == now) ? "*" : "");
5009 		break;
5010 	case OD_SCLK:
5011 		if (hwmgr->od_enabled) {
5012 			size += sprintf(buf + size, "%s:\n", "OD_SCLK");
5013 			for (i = 0; i < odn_sclk_table->num_of_pl; i++)
5014 				size += sprintf(buf + size, "%d: %10uMHz %10umV\n",
5015 					i, odn_sclk_table->entries[i].clock/100,
5016 					odn_sclk_table->entries[i].vddc);
5017 		}
5018 		break;
5019 	case OD_MCLK:
5020 		if (hwmgr->od_enabled) {
5021 			size += sprintf(buf + size, "%s:\n", "OD_MCLK");
5022 			for (i = 0; i < odn_mclk_table->num_of_pl; i++)
5023 				size += sprintf(buf + size, "%d: %10uMHz %10umV\n",
5024 					i, odn_mclk_table->entries[i].clock/100,
5025 					odn_mclk_table->entries[i].vddc);
5026 		}
5027 		break;
5028 	case OD_RANGE:
5029 		if (hwmgr->od_enabled) {
5030 			size += sprintf(buf + size, "%s:\n", "OD_RANGE");
5031 			size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
5032 				data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,
5033 				hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
5034 			size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
5035 				data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,
5036 				hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
5037 			size += sprintf(buf + size, "VDDC: %7umV %11umV\n",
5038 				data->odn_dpm_table.min_vddc,
5039 				data->odn_dpm_table.max_vddc);
5040 		}
5041 		break;
5042 	default:
5043 		break;
5044 	}
5045 	return size;
5046 }
5047 
5048 static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
5049 {
5050 	switch (mode) {
5051 	case AMD_FAN_CTRL_NONE:
5052 		smu7_fan_ctrl_set_fan_speed_pwm(hwmgr, 255);
5053 		break;
5054 	case AMD_FAN_CTRL_MANUAL:
5055 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
5056 			PHM_PlatformCaps_MicrocodeFanControl))
5057 			smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
5058 		break;
5059 	case AMD_FAN_CTRL_AUTO:
5060 		if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode))
5061 			smu7_fan_ctrl_start_smc_fan_control(hwmgr);
5062 		break;
5063 	default:
5064 		break;
5065 	}
5066 }
5067 
5068 static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr)
5069 {
5070 	return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL;
5071 }
5072 
5073 static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
5074 {
5075 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5076 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
5077 	struct smu7_single_dpm_table *golden_sclk_table =
5078 			&(data->golden_dpm_table.sclk_table);
5079 	int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
5080 	int golden_value = golden_sclk_table->dpm_levels
5081 			[golden_sclk_table->count - 1].value;
5082 
5083 	value -= golden_value;
5084 	value = DIV_ROUND_UP(value * 100, golden_value);
5085 
5086 	return value;
5087 }
5088 
5089 static int smu7_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
5090 {
5091 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5092 	struct smu7_single_dpm_table *golden_sclk_table =
5093 			&(data->golden_dpm_table.sclk_table);
5094 	struct pp_power_state  *ps;
5095 	struct smu7_power_state  *smu7_ps;
5096 
5097 	if (value > 20)
5098 		value = 20;
5099 
5100 	ps = hwmgr->request_ps;
5101 
5102 	if (ps == NULL)
5103 		return -EINVAL;
5104 
5105 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
5106 
5107 	smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].engine_clock =
5108 			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value *
5109 			value / 100 +
5110 			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
5111 
5112 	return 0;
5113 }
5114 
5115 static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)
5116 {
5117 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5118 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
5119 	struct smu7_single_dpm_table *golden_mclk_table =
5120 			&(data->golden_dpm_table.mclk_table);
5121         int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
5122 	int golden_value = golden_mclk_table->dpm_levels
5123 			[golden_mclk_table->count - 1].value;
5124 
5125 	value -= golden_value;
5126 	value = DIV_ROUND_UP(value * 100, golden_value);
5127 
5128 	return value;
5129 }
5130 
5131 static int smu7_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value)
5132 {
5133 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5134 	struct smu7_single_dpm_table *golden_mclk_table =
5135 			&(data->golden_dpm_table.mclk_table);
5136 	struct pp_power_state  *ps;
5137 	struct smu7_power_state  *smu7_ps;
5138 
5139 	if (value > 20)
5140 		value = 20;
5141 
5142 	ps = hwmgr->request_ps;
5143 
5144 	if (ps == NULL)
5145 		return -EINVAL;
5146 
5147 	smu7_ps = cast_phw_smu7_power_state(&ps->hardware);
5148 
5149 	smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].memory_clock =
5150 			golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value *
5151 			value / 100 +
5152 			golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
5153 
5154 	return 0;
5155 }
5156 
5157 
5158 static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
5159 {
5160 	struct phm_ppt_v1_information *table_info =
5161 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5162 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = NULL;
5163 	struct phm_clock_voltage_dependency_table *sclk_table;
5164 	int i;
5165 
5166 	if (hwmgr->pp_table_version == PP_TABLE_V1) {
5167 		if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL)
5168 			return -EINVAL;
5169 		dep_sclk_table = table_info->vdd_dep_on_sclk;
5170 		for (i = 0; i < dep_sclk_table->count; i++)
5171 			clocks->clock[i] = dep_sclk_table->entries[i].clk * 10;
5172 		clocks->count = dep_sclk_table->count;
5173 	} else if (hwmgr->pp_table_version == PP_TABLE_V0) {
5174 		sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
5175 		for (i = 0; i < sclk_table->count; i++)
5176 			clocks->clock[i] = sclk_table->entries[i].clk * 10;
5177 		clocks->count = sclk_table->count;
5178 	}
5179 
5180 	return 0;
5181 }
5182 
5183 static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk)
5184 {
5185 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5186 
5187 	if (clk >= MEM_FREQ_LOW_LATENCY && clk < MEM_FREQ_HIGH_LATENCY)
5188 		return data->mem_latency_high;
5189 	else if (clk >= MEM_FREQ_HIGH_LATENCY)
5190 		return data->mem_latency_low;
5191 	else
5192 		return MEM_LATENCY_ERR;
5193 }
5194 
5195 static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
5196 {
5197 	struct phm_ppt_v1_information *table_info =
5198 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5199 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table;
5200 	int i;
5201 	struct phm_clock_voltage_dependency_table *mclk_table;
5202 
5203 	if (hwmgr->pp_table_version == PP_TABLE_V1) {
5204 		if (table_info == NULL)
5205 			return -EINVAL;
5206 		dep_mclk_table = table_info->vdd_dep_on_mclk;
5207 		for (i = 0; i < dep_mclk_table->count; i++) {
5208 			clocks->clock[i] = dep_mclk_table->entries[i].clk * 10;
5209 			clocks->latency[i] = smu7_get_mem_latency(hwmgr,
5210 						dep_mclk_table->entries[i].clk);
5211 		}
5212 		clocks->count = dep_mclk_table->count;
5213 	} else if (hwmgr->pp_table_version == PP_TABLE_V0) {
5214 		mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
5215 		for (i = 0; i < mclk_table->count; i++)
5216 			clocks->clock[i] = mclk_table->entries[i].clk * 10;
5217 		clocks->count = mclk_table->count;
5218 	}
5219 	return 0;
5220 }
5221 
5222 static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type,
5223 						struct amd_pp_clocks *clocks)
5224 {
5225 	switch (type) {
5226 	case amd_pp_sys_clock:
5227 		smu7_get_sclks(hwmgr, clocks);
5228 		break;
5229 	case amd_pp_mem_clock:
5230 		smu7_get_mclks(hwmgr, clocks);
5231 		break;
5232 	default:
5233 		return -EINVAL;
5234 	}
5235 
5236 	return 0;
5237 }
5238 
5239 static int smu7_get_sclks_with_latency(struct pp_hwmgr *hwmgr,
5240 				       struct pp_clock_levels_with_latency *clocks)
5241 {
5242 	struct phm_ppt_v1_information *table_info =
5243 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5244 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
5245 			table_info->vdd_dep_on_sclk;
5246 	int i;
5247 
5248 	clocks->num_levels = 0;
5249 	for (i = 0; i < dep_sclk_table->count; i++) {
5250 		if (dep_sclk_table->entries[i].clk) {
5251 			clocks->data[clocks->num_levels].clocks_in_khz =
5252 				dep_sclk_table->entries[i].clk * 10;
5253 			clocks->num_levels++;
5254 		}
5255 	}
5256 
5257 	return 0;
5258 }
5259 
5260 static int smu7_get_mclks_with_latency(struct pp_hwmgr *hwmgr,
5261 				       struct pp_clock_levels_with_latency *clocks)
5262 {
5263 	struct phm_ppt_v1_information *table_info =
5264 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5265 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5266 			table_info->vdd_dep_on_mclk;
5267 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5268 	int i;
5269 
5270 	clocks->num_levels = 0;
5271 	data->mclk_latency_table.count = 0;
5272 	for (i = 0; i < dep_mclk_table->count; i++) {
5273 		if (dep_mclk_table->entries[i].clk) {
5274 			clocks->data[clocks->num_levels].clocks_in_khz =
5275 					dep_mclk_table->entries[i].clk * 10;
5276 			data->mclk_latency_table.entries[data->mclk_latency_table.count].frequency =
5277 					dep_mclk_table->entries[i].clk;
5278 			clocks->data[clocks->num_levels].latency_in_us =
5279 				data->mclk_latency_table.entries[data->mclk_latency_table.count].latency =
5280 					smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk);
5281 			clocks->num_levels++;
5282 			data->mclk_latency_table.count++;
5283 		}
5284 	}
5285 
5286 	return 0;
5287 }
5288 
5289 static int smu7_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
5290 					       enum amd_pp_clock_type type,
5291 					       struct pp_clock_levels_with_latency *clocks)
5292 {
5293 	if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
5294 	      hwmgr->chip_id <= CHIP_VEGAM))
5295 		return -EINVAL;
5296 
5297 	switch (type) {
5298 	case amd_pp_sys_clock:
5299 		smu7_get_sclks_with_latency(hwmgr, clocks);
5300 		break;
5301 	case amd_pp_mem_clock:
5302 		smu7_get_mclks_with_latency(hwmgr, clocks);
5303 		break;
5304 	default:
5305 		return -EINVAL;
5306 	}
5307 
5308 	return 0;
5309 }
5310 
5311 static int smu7_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
5312 						 void *clock_range)
5313 {
5314 	struct phm_ppt_v1_information *table_info =
5315 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5316 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
5317 			table_info->vdd_dep_on_mclk;
5318 	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
5319 			table_info->vdd_dep_on_sclk;
5320 	struct polaris10_smumgr *smu_data =
5321 			(struct polaris10_smumgr *)(hwmgr->smu_backend);
5322 	SMU74_Discrete_DpmTable  *table = &(smu_data->smc_state_table);
5323 	struct dm_pp_wm_sets_with_clock_ranges *watermarks =
5324 			(struct dm_pp_wm_sets_with_clock_ranges *)clock_range;
5325 	uint32_t i, j, k;
5326 	bool valid_entry;
5327 
5328 	if (!(hwmgr->chip_id >= CHIP_POLARIS10 &&
5329 	      hwmgr->chip_id <= CHIP_VEGAM))
5330 		return -EINVAL;
5331 
5332 	for (i = 0; i < dep_mclk_table->count; i++) {
5333 		for (j = 0; j < dep_sclk_table->count; j++) {
5334 			valid_entry = false;
5335 			for (k = 0; k < watermarks->num_wm_sets; k++) {
5336 				if (dep_sclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz / 10 &&
5337 				    dep_sclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz / 10 &&
5338 				    dep_mclk_table->entries[i].clk >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz / 10 &&
5339 				    dep_mclk_table->entries[i].clk < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz / 10) {
5340 					valid_entry = true;
5341 					table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id;
5342 					break;
5343 				}
5344 			}
5345 			PP_ASSERT_WITH_CODE(valid_entry,
5346 					"Clock is not in range of specified clock range for watermark from DAL!  Using highest water mark set.",
5347 					table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k - 1].wm_set_id);
5348 		}
5349 	}
5350 
5351 	return smu7_copy_bytes_to_smc(hwmgr,
5352 				      smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, DisplayWatermark),
5353 				      (uint8_t *)table->DisplayWatermark,
5354 				      sizeof(uint8_t) * SMU74_MAX_LEVELS_MEMORY * SMU74_MAX_LEVELS_GRAPHICS,
5355 				      SMC_RAM_END);
5356 }
5357 
5358 static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
5359 					uint32_t virtual_addr_low,
5360 					uint32_t virtual_addr_hi,
5361 					uint32_t mc_addr_low,
5362 					uint32_t mc_addr_hi,
5363 					uint32_t size)
5364 {
5365 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5366 
5367 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5368 					data->soft_regs_start +
5369 					smum_get_offsetof(hwmgr,
5370 					SMU_SoftRegisters, DRAM_LOG_ADDR_H),
5371 					mc_addr_hi);
5372 
5373 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5374 					data->soft_regs_start +
5375 					smum_get_offsetof(hwmgr,
5376 					SMU_SoftRegisters, DRAM_LOG_ADDR_L),
5377 					mc_addr_low);
5378 
5379 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5380 					data->soft_regs_start +
5381 					smum_get_offsetof(hwmgr,
5382 					SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H),
5383 					virtual_addr_hi);
5384 
5385 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5386 					data->soft_regs_start +
5387 					smum_get_offsetof(hwmgr,
5388 					SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L),
5389 					virtual_addr_low);
5390 
5391 	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
5392 					data->soft_regs_start +
5393 					smum_get_offsetof(hwmgr,
5394 					SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE),
5395 					size);
5396 	return 0;
5397 }
5398 
5399 static int smu7_get_max_high_clocks(struct pp_hwmgr *hwmgr,
5400 					struct amd_pp_simple_clock_info *clocks)
5401 {
5402 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5403 	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
5404 	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
5405 
5406 	if (clocks == NULL)
5407 		return -EINVAL;
5408 
5409 	clocks->memory_max_clock = mclk_table->count > 1 ?
5410 				mclk_table->dpm_levels[mclk_table->count-1].value :
5411 				mclk_table->dpm_levels[0].value;
5412 	clocks->engine_max_clock = sclk_table->count > 1 ?
5413 				sclk_table->dpm_levels[sclk_table->count-1].value :
5414 				sclk_table->dpm_levels[0].value;
5415 	return 0;
5416 }
5417 
5418 static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
5419 		struct PP_TemperatureRange *thermal_data)
5420 {
5421 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5422 	struct phm_ppt_v1_information *table_info =
5423 			(struct phm_ppt_v1_information *)hwmgr->pptable;
5424 
5425 	memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange));
5426 
5427 	if (hwmgr->pp_table_version == PP_TABLE_V1)
5428 		thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp *
5429 			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
5430 	else if (hwmgr->pp_table_version == PP_TABLE_V0)
5431 		thermal_data->max = data->thermal_temp_setting.temperature_shutdown *
5432 			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
5433 
5434 	return 0;
5435 }
5436 
5437 static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
5438 					enum PP_OD_DPM_TABLE_COMMAND type,
5439 					uint32_t clk,
5440 					uint32_t voltage)
5441 {
5442 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5443 
5444 	if (voltage < data->odn_dpm_table.min_vddc || voltage > data->odn_dpm_table.max_vddc) {
5445 		pr_info("OD voltage is out of range [%d - %d] mV\n",
5446 						data->odn_dpm_table.min_vddc,
5447 						data->odn_dpm_table.max_vddc);
5448 		return false;
5449 	}
5450 
5451 	if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
5452 		if (data->golden_dpm_table.sclk_table.dpm_levels[0].value > clk ||
5453 			hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
5454 			pr_info("OD engine clock is out of range [%d - %d] MHz\n",
5455 				data->golden_dpm_table.sclk_table.dpm_levels[0].value/100,
5456 				hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
5457 			return false;
5458 		}
5459 	} else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
5460 		if (data->golden_dpm_table.mclk_table.dpm_levels[0].value > clk ||
5461 			hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
5462 			pr_info("OD memory clock is out of range [%d - %d] MHz\n",
5463 				data->golden_dpm_table.mclk_table.dpm_levels[0].value/100,
5464 				hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
5465 			return false;
5466 		}
5467 	} else {
5468 		return false;
5469 	}
5470 
5471 	return true;
5472 }
5473 
5474 static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
5475 					enum PP_OD_DPM_TABLE_COMMAND type,
5476 					long *input, uint32_t size)
5477 {
5478 	uint32_t i;
5479 	struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL;
5480 	struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL;
5481 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5482 
5483 	uint32_t input_clk;
5484 	uint32_t input_vol;
5485 	uint32_t input_level;
5486 
5487 	PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
5488 				return -EINVAL);
5489 
5490 	if (!hwmgr->od_enabled) {
5491 		pr_info("OverDrive feature not enabled\n");
5492 		return -EINVAL;
5493 	}
5494 
5495 	if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
5496 		podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels;
5497 		podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk;
5498 		PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),
5499 				"Failed to get ODN SCLK and Voltage tables",
5500 				return -EINVAL);
5501 	} else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
5502 		podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels;
5503 		podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk;
5504 
5505 		PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),
5506 			"Failed to get ODN MCLK and Voltage tables",
5507 			return -EINVAL);
5508 	} else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
5509 		smu7_odn_initial_default_setting(hwmgr);
5510 		return 0;
5511 	} else if (PP_OD_COMMIT_DPM_TABLE == type) {
5512 		smu7_check_dpm_table_updated(hwmgr);
5513 		return 0;
5514 	} else {
5515 		return -EINVAL;
5516 	}
5517 
5518 	for (i = 0; i < size; i += 3) {
5519 		if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) {
5520 			pr_info("invalid clock voltage input \n");
5521 			return 0;
5522 		}
5523 		input_level = input[i];
5524 		input_clk = input[i+1] * 100;
5525 		input_vol = input[i+2];
5526 
5527 		if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
5528 			podn_dpm_table_in_backend->entries[input_level].clock = input_clk;
5529 			podn_vdd_dep_in_backend->entries[input_level].clk = input_clk;
5530 			podn_dpm_table_in_backend->entries[input_level].vddc = input_vol;
5531 			podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol;
5532 			podn_vdd_dep_in_backend->entries[input_level].vddgfx = input_vol;
5533 		} else {
5534 			return -EINVAL;
5535 		}
5536 	}
5537 
5538 	return 0;
5539 }
5540 
5541 static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
5542 {
5543 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5544 	uint32_t i, size = 0;
5545 	uint32_t len;
5546 
5547 	static const char *title[8] = {"NUM",
5548 			"MODE_NAME",
5549 			"SCLK_UP_HYST",
5550 			"SCLK_DOWN_HYST",
5551 			"SCLK_ACTIVE_LEVEL",
5552 			"MCLK_UP_HYST",
5553 			"MCLK_DOWN_HYST",
5554 			"MCLK_ACTIVE_LEVEL"};
5555 
5556 	if (!buf)
5557 		return -EINVAL;
5558 
5559 	phm_get_sysfs_buf(&buf, &size);
5560 
5561 	size += sysfs_emit_at(buf, size, "%s %16s %16s %16s %16s %16s %16s %16s\n",
5562 			title[0], title[1], title[2], title[3],
5563 			title[4], title[5], title[6], title[7]);
5564 
5565 	len = ARRAY_SIZE(smu7_profiling);
5566 
5567 	for (i = 0; i < len; i++) {
5568 		if (i == hwmgr->power_profile_mode) {
5569 			size += sysfs_emit_at(buf, size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n",
5570 			i, amdgpu_pp_profile_name[i], "*",
5571 			data->current_profile_setting.sclk_up_hyst,
5572 			data->current_profile_setting.sclk_down_hyst,
5573 			data->current_profile_setting.sclk_activity,
5574 			data->current_profile_setting.mclk_up_hyst,
5575 			data->current_profile_setting.mclk_down_hyst,
5576 			data->current_profile_setting.mclk_activity);
5577 			continue;
5578 		}
5579 		if (smu7_profiling[i].bupdate_sclk)
5580 			size += sysfs_emit_at(buf, size, "%3d %16s: %8d %16d %16d ",
5581 			i, amdgpu_pp_profile_name[i], smu7_profiling[i].sclk_up_hyst,
5582 			smu7_profiling[i].sclk_down_hyst,
5583 			smu7_profiling[i].sclk_activity);
5584 		else
5585 			size += sysfs_emit_at(buf, size, "%3d %16s: %8s %16s %16s ",
5586 			i, amdgpu_pp_profile_name[i], "-", "-", "-");
5587 
5588 		if (smu7_profiling[i].bupdate_mclk)
5589 			size += sysfs_emit_at(buf, size, "%16d %16d %16d\n",
5590 			smu7_profiling[i].mclk_up_hyst,
5591 			smu7_profiling[i].mclk_down_hyst,
5592 			smu7_profiling[i].mclk_activity);
5593 		else
5594 			size += sysfs_emit_at(buf, size, "%16s %16s %16s\n",
5595 			"-", "-", "-");
5596 	}
5597 
5598 	return size;
5599 }
5600 
5601 static void smu7_patch_compute_profile_mode(struct pp_hwmgr *hwmgr,
5602 					enum PP_SMC_POWER_PROFILE requst)
5603 {
5604 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5605 	uint32_t tmp, level;
5606 
5607 	if (requst == PP_SMC_POWER_PROFILE_COMPUTE) {
5608 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
5609 			level = 0;
5610 			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
5611 			while (tmp >>= 1)
5612 				level++;
5613 			if (level > 0)
5614 				smu7_force_clock_level(hwmgr, PP_SCLK, 3 << (level-1));
5615 		}
5616 	} else if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) {
5617 		smu7_force_clock_level(hwmgr, PP_SCLK, data->dpm_level_enable_mask.sclk_dpm_enable_mask);
5618 	}
5619 }
5620 
5621 static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
5622 {
5623 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
5624 	struct profile_mode_setting tmp;
5625 	enum PP_SMC_POWER_PROFILE mode;
5626 
5627 	if (input == NULL)
5628 		return -EINVAL;
5629 
5630 	mode = input[size];
5631 	switch (mode) {
5632 	case PP_SMC_POWER_PROFILE_CUSTOM:
5633 		if (size < 8 && size != 0)
5634 			return -EINVAL;
5635 		/* If only CUSTOM is passed in, use the saved values. Check
5636 		 * that we actually have a CUSTOM profile by ensuring that
5637 		 * the "use sclk" or the "use mclk" bits are set
5638 		 */
5639 		tmp = smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM];
5640 		if (size == 0) {
5641 			if (tmp.bupdate_sclk == 0 && tmp.bupdate_mclk == 0)
5642 				return -EINVAL;
5643 		} else {
5644 			tmp.bupdate_sclk = input[0];
5645 			tmp.sclk_up_hyst = input[1];
5646 			tmp.sclk_down_hyst = input[2];
5647 			tmp.sclk_activity = input[3];
5648 			tmp.bupdate_mclk = input[4];
5649 			tmp.mclk_up_hyst = input[5];
5650 			tmp.mclk_down_hyst = input[6];
5651 			tmp.mclk_activity = input[7];
5652 			smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM] = tmp;
5653 		}
5654 		if (!smum_update_dpm_settings(hwmgr, &tmp)) {
5655 			memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting));
5656 			hwmgr->power_profile_mode = mode;
5657 		}
5658 		break;
5659 	case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
5660 	case PP_SMC_POWER_PROFILE_POWERSAVING:
5661 	case PP_SMC_POWER_PROFILE_VIDEO:
5662 	case PP_SMC_POWER_PROFILE_VR:
5663 	case PP_SMC_POWER_PROFILE_COMPUTE:
5664 		if (mode == hwmgr->power_profile_mode)
5665 			return 0;
5666 
5667 		memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting));
5668 		if (!smum_update_dpm_settings(hwmgr, &tmp)) {
5669 			if (tmp.bupdate_sclk) {
5670 				data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk;
5671 				data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst;
5672 				data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst;
5673 				data->current_profile_setting.sclk_activity = tmp.sclk_activity;
5674 			}
5675 			if (tmp.bupdate_mclk) {
5676 				data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk;
5677 				data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst;
5678 				data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst;
5679 				data->current_profile_setting.mclk_activity = tmp.mclk_activity;
5680 			}
5681 			smu7_patch_compute_profile_mode(hwmgr, mode);
5682 			hwmgr->power_profile_mode = mode;
5683 		}
5684 		break;
5685 	default:
5686 		return -EINVAL;
5687 	}
5688 
5689 	return 0;
5690 }
5691 
5692 static int smu7_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
5693 				PHM_PerformanceLevelDesignation designation, uint32_t index,
5694 				PHM_PerformanceLevel *level)
5695 {
5696 	const struct smu7_power_state *ps;
5697 	uint32_t i;
5698 
5699 	if (level == NULL || hwmgr == NULL || state == NULL)
5700 		return -EINVAL;
5701 
5702 	ps = cast_const_phw_smu7_power_state(state);
5703 
5704 	i = index > ps->performance_level_count - 1 ?
5705 			ps->performance_level_count - 1 : index;
5706 
5707 	level->coreClock = ps->performance_levels[i].engine_clock;
5708 	level->memory_clock = ps->performance_levels[i].memory_clock;
5709 
5710 	return 0;
5711 }
5712 
5713 static int smu7_power_off_asic(struct pp_hwmgr *hwmgr)
5714 {
5715 	int result;
5716 
5717 	result = smu7_disable_dpm_tasks(hwmgr);
5718 	PP_ASSERT_WITH_CODE((0 == result),
5719 			"[disable_dpm_tasks] Failed to disable DPM!",
5720 			);
5721 
5722 	return result;
5723 }
5724 
5725 static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
5726 	.backend_init = &smu7_hwmgr_backend_init,
5727 	.backend_fini = &smu7_hwmgr_backend_fini,
5728 	.asic_setup = &smu7_setup_asic_task,
5729 	.dynamic_state_management_enable = &smu7_enable_dpm_tasks,
5730 	.apply_state_adjust_rules = smu7_apply_state_adjust_rules,
5731 	.force_dpm_level = &smu7_force_dpm_level,
5732 	.power_state_set = smu7_set_power_state_tasks,
5733 	.get_power_state_size = smu7_get_power_state_size,
5734 	.get_mclk = smu7_dpm_get_mclk,
5735 	.get_sclk = smu7_dpm_get_sclk,
5736 	.patch_boot_state = smu7_dpm_patch_boot_state,
5737 	.get_pp_table_entry = smu7_get_pp_table_entry,
5738 	.get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries,
5739 	.powerdown_uvd = smu7_powerdown_uvd,
5740 	.powergate_uvd = smu7_powergate_uvd,
5741 	.powergate_vce = smu7_powergate_vce,
5742 	.disable_clock_power_gating = smu7_disable_clock_power_gating,
5743 	.update_clock_gatings = smu7_update_clock_gatings,
5744 	.notify_smc_display_config_after_ps_adjustment = smu7_notify_smc_display_config_after_ps_adjustment,
5745 	.display_config_changed = smu7_display_configuration_changed_task,
5746 	.set_max_fan_pwm_output = smu7_set_max_fan_pwm_output,
5747 	.set_max_fan_rpm_output = smu7_set_max_fan_rpm_output,
5748 	.stop_thermal_controller = smu7_thermal_stop_thermal_controller,
5749 	.get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info,
5750 	.get_fan_speed_pwm = smu7_fan_ctrl_get_fan_speed_pwm,
5751 	.set_fan_speed_pwm = smu7_fan_ctrl_set_fan_speed_pwm,
5752 	.reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default,
5753 	.get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm,
5754 	.set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm,
5755 	.uninitialize_thermal_controller = smu7_thermal_ctrl_uninitialize_thermal_controller,
5756 	.register_irq_handlers = smu7_register_irq_handlers,
5757 	.check_smc_update_required_for_display_configuration = smu7_check_smc_update_required_for_display_configuration,
5758 	.check_states_equal = smu7_check_states_equal,
5759 	.set_fan_control_mode = smu7_set_fan_control_mode,
5760 	.get_fan_control_mode = smu7_get_fan_control_mode,
5761 	.force_clock_level = smu7_force_clock_level,
5762 	.print_clock_levels = smu7_print_clock_levels,
5763 	.powergate_gfx = smu7_powergate_gfx,
5764 	.get_sclk_od = smu7_get_sclk_od,
5765 	.set_sclk_od = smu7_set_sclk_od,
5766 	.get_mclk_od = smu7_get_mclk_od,
5767 	.set_mclk_od = smu7_set_mclk_od,
5768 	.get_clock_by_type = smu7_get_clock_by_type,
5769 	.get_clock_by_type_with_latency = smu7_get_clock_by_type_with_latency,
5770 	.set_watermarks_for_clocks_ranges = smu7_set_watermarks_for_clocks_ranges,
5771 	.read_sensor = smu7_read_sensor,
5772 	.dynamic_state_management_disable = smu7_disable_dpm_tasks,
5773 	.avfs_control = smu7_avfs_control,
5774 	.disable_smc_firmware_ctf = smu7_thermal_disable_alert,
5775 	.start_thermal_controller = smu7_start_thermal_controller,
5776 	.notify_cac_buffer_info = smu7_notify_cac_buffer_info,
5777 	.get_max_high_clocks = smu7_get_max_high_clocks,
5778 	.get_thermal_temperature_range = smu7_get_thermal_temperature_range,
5779 	.odn_edit_dpm_table = smu7_odn_edit_dpm_table,
5780 	.set_power_limit = smu7_set_power_limit,
5781 	.get_power_profile_mode = smu7_get_power_profile_mode,
5782 	.set_power_profile_mode = smu7_set_power_profile_mode,
5783 	.get_performance_level = smu7_get_performance_level,
5784 	.get_asic_baco_capability = smu7_baco_get_capability,
5785 	.get_asic_baco_state = smu7_baco_get_state,
5786 	.set_asic_baco_state = smu7_baco_set_state,
5787 	.power_off_asic = smu7_power_off_asic,
5788 };
5789 
5790 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
5791 		uint32_t clock_insr)
5792 {
5793 	uint8_t i;
5794 	uint32_t temp;
5795 	uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK);
5796 
5797 	PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0);
5798 	for (i = SMU7_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
5799 		temp = clock >> i;
5800 
5801 		if (temp >= min || i == 0)
5802 			break;
5803 	}
5804 	return i;
5805 }
5806 
5807 int smu7_init_function_pointers(struct pp_hwmgr *hwmgr)
5808 {
5809 	hwmgr->hwmgr_func = &smu7_hwmgr_funcs;
5810 	if (hwmgr->pp_table_version == PP_TABLE_V0)
5811 		hwmgr->pptable_func = &pptable_funcs;
5812 	else if (hwmgr->pp_table_version == PP_TABLE_V1)
5813 		hwmgr->pptable_func = &pptable_v1_0_funcs;
5814 
5815 	return 0;
5816 }
5817