drm/amd/powerplay: fix pcie dpm table for vega10
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / powerplay / hwmgr / vega10_hwmgr.c
1 /*
2  * Copyright 2016 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 <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/fb.h>
26 #include "linux/delay.h"
27
28 #include "hwmgr.h"
29 #include "amd_powerplay.h"
30 #include "vega10_smumgr.h"
31 #include "hardwaremanager.h"
32 #include "ppatomfwctrl.h"
33 #include "atomfirmware.h"
34 #include "cgs_common.h"
35 #include "vega10_powertune.h"
36 #include "smu9.h"
37 #include "smu9_driver_if.h"
38 #include "vega10_inc.h"
39 #include "pp_soc15.h"
40 #include "pppcielanes.h"
41 #include "vega10_hwmgr.h"
42 #include "vega10_processpptables.h"
43 #include "vega10_pptable.h"
44 #include "vega10_thermal.h"
45 #include "pp_debug.h"
46 #include "pp_acpi.h"
47 #include "amd_pcie_helpers.h"
48 #include "cgs_linux.h"
49 #include "ppinterrupt.h"
50 #include "pp_overdriver.h"
51
52 #define VOLTAGE_SCALE  4
53 #define VOLTAGE_VID_OFFSET_SCALE1   625
54 #define VOLTAGE_VID_OFFSET_SCALE2   100
55
56 #define HBM_MEMORY_CHANNEL_WIDTH    128
57
58 uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2};
59
60 #define MEM_FREQ_LOW_LATENCY        25000
61 #define MEM_FREQ_HIGH_LATENCY       80000
62 #define MEM_LATENCY_HIGH            245
63 #define MEM_LATENCY_LOW             35
64 #define MEM_LATENCY_ERR             0xFFFF
65
66 #define mmDF_CS_AON0_DramBaseAddress0                                                                  0x0044
67 #define mmDF_CS_AON0_DramBaseAddress0_BASE_IDX                                                         0
68
69 //DF_CS_AON0_DramBaseAddress0
70 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal__SHIFT                                                        0x0
71 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT                                                    0x1
72 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT                                                      0x4
73 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT                                                      0x8
74 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr__SHIFT                                                      0xc
75 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal_MASK                                                          0x00000001L
76 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK                                                      0x00000002L
77 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK                                                        0x000000F0L
78 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK                                                        0x00000700L
79 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK                                                        0xFFFFF000L
80
81 const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic);
82
83 struct vega10_power_state *cast_phw_vega10_power_state(
84                                   struct pp_hw_power_state *hw_ps)
85 {
86         PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic),
87                                 "Invalid Powerstate Type!",
88                                  return NULL;);
89
90         return (struct vega10_power_state *)hw_ps;
91 }
92
93 const struct vega10_power_state *cast_const_phw_vega10_power_state(
94                                  const struct pp_hw_power_state *hw_ps)
95 {
96         PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic),
97                                 "Invalid Powerstate Type!",
98                                  return NULL;);
99
100         return (const struct vega10_power_state *)hw_ps;
101 }
102
103 static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr)
104 {
105         struct vega10_hwmgr *data =
106                         (struct vega10_hwmgr *)(hwmgr->backend);
107
108         data->registry_data.sclk_dpm_key_disabled =
109                         hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
110         data->registry_data.socclk_dpm_key_disabled =
111                         hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true;
112         data->registry_data.mclk_dpm_key_disabled =
113                         hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
114         data->registry_data.pcie_dpm_key_disabled =
115                         hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
116
117         data->registry_data.dcefclk_dpm_key_disabled =
118                         hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true;
119
120         if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
121                 data->registry_data.power_containment_support = 1;
122                 data->registry_data.enable_pkg_pwr_tracking_feature = 1;
123                 data->registry_data.enable_tdc_limit_feature = 1;
124         }
125
126         data->registry_data.clock_stretcher_support =
127                         hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? false : true;
128
129         data->registry_data.disable_water_mark = 0;
130
131         data->registry_data.fan_control_support = 1;
132         data->registry_data.thermal_support = 1;
133         data->registry_data.fw_ctf_enabled = 1;
134
135         data->registry_data.avfs_support = 1;
136         data->registry_data.led_dpm_enabled = 1;
137
138         data->registry_data.vr0hot_enabled = 1;
139         data->registry_data.vr1hot_enabled = 1;
140         data->registry_data.regulator_hot_gpio_support = 1;
141
142         data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT;
143         data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
144         data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
145         data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
146         data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
147         data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
148         data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
149         data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
150         data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
151         data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
152         data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
153         data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
154         data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
155
156         data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT;
157         data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT;
158         data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT;
159         data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT;
160 }
161
162 static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
163 {
164         struct vega10_hwmgr *data =
165                         (struct vega10_hwmgr *)(hwmgr->backend);
166         struct phm_ppt_v2_information *table_info =
167                         (struct phm_ppt_v2_information *)hwmgr->pptable;
168         struct cgs_system_info sys_info = {0};
169         int result;
170
171         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
172                         PHM_PlatformCaps_SclkDeepSleep);
173
174         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
175                         PHM_PlatformCaps_DynamicPatchPowerState);
176
177         if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE)
178                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
179                                 PHM_PlatformCaps_ControlVDDCI);
180
181         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
182                         PHM_PlatformCaps_TablelessHardwareInterface);
183
184         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
185                         PHM_PlatformCaps_EnableSMU7ThermalManagement);
186
187         sys_info.size = sizeof(struct cgs_system_info);
188         sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
189         result = cgs_query_system_info(hwmgr->device, &sys_info);
190
191         if (!result && (sys_info.value & AMD_PG_SUPPORT_UVD))
192                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
193                                 PHM_PlatformCaps_UVDPowerGating);
194
195         if (!result && (sys_info.value & AMD_PG_SUPPORT_VCE))
196                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
197                                 PHM_PlatformCaps_VCEPowerGating);
198
199         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
200                         PHM_PlatformCaps_UnTabledHardwareInterface);
201
202         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
203                         PHM_PlatformCaps_FanSpeedInTableIsRPM);
204
205         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
206                         PHM_PlatformCaps_ODFuzzyFanControlSupport);
207
208         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
209                                 PHM_PlatformCaps_DynamicPowerManagement);
210
211         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
212                         PHM_PlatformCaps_SMC);
213
214         /* power tune caps */
215         /* assume disabled */
216         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
217                         PHM_PlatformCaps_PowerContainment);
218         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
219                         PHM_PlatformCaps_SQRamping);
220         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
221                         PHM_PlatformCaps_DBRamping);
222         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
223                         PHM_PlatformCaps_TDRamping);
224         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
225                         PHM_PlatformCaps_TCPRamping);
226
227         if (data->registry_data.power_containment_support)
228                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
229                                 PHM_PlatformCaps_PowerContainment);
230         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
231                         PHM_PlatformCaps_CAC);
232
233         if (table_info->tdp_table->usClockStretchAmount &&
234                         data->registry_data.clock_stretcher_support)
235                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
236                                 PHM_PlatformCaps_ClockStretcher);
237
238         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
239                         PHM_PlatformCaps_RegulatorHot);
240         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
241                         PHM_PlatformCaps_AutomaticDCTransition);
242
243         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
244                         PHM_PlatformCaps_UVDDPM);
245         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
246                         PHM_PlatformCaps_VCEDPM);
247
248         return 0;
249 }
250
251 static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
252 {
253         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
254         int i;
255
256         vega10_initialize_power_tune_defaults(hwmgr);
257
258         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
259                 data->smu_features[i].smu_feature_id = 0xffff;
260                 data->smu_features[i].smu_feature_bitmap = 1 << i;
261                 data->smu_features[i].enabled = false;
262                 data->smu_features[i].supported = false;
263         }
264
265         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
266                         FEATURE_DPM_PREFETCHER_BIT;
267         data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
268                         FEATURE_DPM_GFXCLK_BIT;
269         data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
270                         FEATURE_DPM_UCLK_BIT;
271         data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
272                         FEATURE_DPM_SOCCLK_BIT;
273         data->smu_features[GNLD_DPM_UVD].smu_feature_id =
274                         FEATURE_DPM_UVD_BIT;
275         data->smu_features[GNLD_DPM_VCE].smu_feature_id =
276                         FEATURE_DPM_VCE_BIT;
277         data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
278                         FEATURE_DPM_MP0CLK_BIT;
279         data->smu_features[GNLD_DPM_LINK].smu_feature_id =
280                         FEATURE_DPM_LINK_BIT;
281         data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
282                         FEATURE_DPM_DCEFCLK_BIT;
283         data->smu_features[GNLD_ULV].smu_feature_id =
284                         FEATURE_ULV_BIT;
285         data->smu_features[GNLD_AVFS].smu_feature_id =
286                         FEATURE_AVFS_BIT;
287         data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
288                         FEATURE_DS_GFXCLK_BIT;
289         data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
290                         FEATURE_DS_SOCCLK_BIT;
291         data->smu_features[GNLD_DS_LCLK].smu_feature_id =
292                         FEATURE_DS_LCLK_BIT;
293         data->smu_features[GNLD_PPT].smu_feature_id =
294                         FEATURE_PPT_BIT;
295         data->smu_features[GNLD_TDC].smu_feature_id =
296                         FEATURE_TDC_BIT;
297         data->smu_features[GNLD_THERMAL].smu_feature_id =
298                         FEATURE_THERMAL_BIT;
299         data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
300                         FEATURE_GFX_PER_CU_CG_BIT;
301         data->smu_features[GNLD_RM].smu_feature_id =
302                         FEATURE_RM_BIT;
303         data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
304                         FEATURE_DS_DCEFCLK_BIT;
305         data->smu_features[GNLD_ACDC].smu_feature_id =
306                         FEATURE_ACDC_BIT;
307         data->smu_features[GNLD_VR0HOT].smu_feature_id =
308                         FEATURE_VR0HOT_BIT;
309         data->smu_features[GNLD_VR1HOT].smu_feature_id =
310                         FEATURE_VR1HOT_BIT;
311         data->smu_features[GNLD_FW_CTF].smu_feature_id =
312                         FEATURE_FW_CTF_BIT;
313         data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
314                         FEATURE_LED_DISPLAY_BIT;
315         data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
316                         FEATURE_FAN_CONTROL_BIT;
317         data->smu_features[GNLD_VOLTAGE_CONTROLLER].smu_feature_id =
318                         FEATURE_VOLTAGE_CONTROLLER_BIT;
319
320         if (!data->registry_data.prefetcher_dpm_key_disabled)
321                 data->smu_features[GNLD_DPM_PREFETCHER].supported = true;
322
323         if (!data->registry_data.sclk_dpm_key_disabled)
324                 data->smu_features[GNLD_DPM_GFXCLK].supported = true;
325
326         if (!data->registry_data.mclk_dpm_key_disabled)
327                 data->smu_features[GNLD_DPM_UCLK].supported = true;
328
329         if (!data->registry_data.socclk_dpm_key_disabled)
330                 data->smu_features[GNLD_DPM_SOCCLK].supported = true;
331
332         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
333                         PHM_PlatformCaps_UVDDPM))
334                 data->smu_features[GNLD_DPM_UVD].supported = true;
335
336         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
337                         PHM_PlatformCaps_VCEDPM))
338                 data->smu_features[GNLD_DPM_VCE].supported = true;
339
340         if (!data->registry_data.pcie_dpm_key_disabled)
341                 data->smu_features[GNLD_DPM_LINK].supported = true;
342
343         if (!data->registry_data.dcefclk_dpm_key_disabled)
344                 data->smu_features[GNLD_DPM_DCEFCLK].supported = true;
345
346         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
347                         PHM_PlatformCaps_SclkDeepSleep) &&
348                         data->registry_data.sclk_deep_sleep_support) {
349                 data->smu_features[GNLD_DS_GFXCLK].supported = true;
350                 data->smu_features[GNLD_DS_SOCCLK].supported = true;
351                 data->smu_features[GNLD_DS_LCLK].supported = true;
352         }
353
354         if (data->registry_data.enable_pkg_pwr_tracking_feature)
355                 data->smu_features[GNLD_PPT].supported = true;
356
357         if (data->registry_data.enable_tdc_limit_feature)
358                 data->smu_features[GNLD_TDC].supported = true;
359
360         if (data->registry_data.thermal_support)
361                 data->smu_features[GNLD_THERMAL].supported = true;
362
363         if (data->registry_data.fan_control_support)
364                 data->smu_features[GNLD_FAN_CONTROL].supported = true;
365
366         if (data->registry_data.fw_ctf_enabled)
367                 data->smu_features[GNLD_FW_CTF].supported = true;
368
369         if (data->registry_data.avfs_support)
370                 data->smu_features[GNLD_AVFS].supported = true;
371
372         if (data->registry_data.led_dpm_enabled)
373                 data->smu_features[GNLD_LED_DISPLAY].supported = true;
374
375         if (data->registry_data.vr1hot_enabled)
376                 data->smu_features[GNLD_VR1HOT].supported = true;
377
378         if (data->registry_data.vr0hot_enabled)
379                 data->smu_features[GNLD_VR0HOT].supported = true;
380
381 }
382
383 #ifdef PPLIB_VEGA10_EVV_SUPPORT
384 static int vega10_get_socclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
385         phm_ppt_v1_voltage_lookup_table *lookup_table,
386         uint16_t virtual_voltage_id, int32_t *socclk)
387 {
388         uint8_t entry_id;
389         uint8_t voltage_id;
390         struct phm_ppt_v2_information *table_info =
391                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
392
393         PP_ASSERT_WITH_CODE(lookup_table->count != 0,
394                         "Lookup table is empty",
395                         return -EINVAL);
396
397         /* search for leakage voltage ID 0xff01 ~ 0xff08 and sclk */
398         for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) {
399                 voltage_id = table_info->vdd_dep_on_socclk->entries[entry_id].vddInd;
400                 if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id)
401                         break;
402         }
403
404         PP_ASSERT_WITH_CODE(entry_id < table_info->vdd_dep_on_socclk->count,
405                         "Can't find requested voltage id in vdd_dep_on_socclk table!",
406                         return -EINVAL);
407
408         *socclk = table_info->vdd_dep_on_socclk->entries[entry_id].clk;
409
410         return 0;
411 }
412
413 #define ATOM_VIRTUAL_VOLTAGE_ID0             0xff01
414 /**
415 * Get Leakage VDDC based on leakage ID.
416 *
417 * @param    hwmgr  the address of the powerplay hardware manager.
418 * @return   always 0.
419 */
420 static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr)
421 {
422         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
423         uint16_t vv_id;
424         uint32_t vddc = 0;
425         uint16_t i, j;
426         uint32_t sclk = 0;
427         struct phm_ppt_v2_information *table_info =
428                         (struct phm_ppt_v2_information *)hwmgr->pptable;
429         struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table =
430                         table_info->vdd_dep_on_socclk;
431         int result;
432
433         for (i = 0; i < VEGA10_MAX_LEAKAGE_COUNT; i++) {
434                 vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
435
436                 if (!vega10_get_socclk_for_voltage_evv(hwmgr,
437                                 table_info->vddc_lookup_table, vv_id, &sclk)) {
438                         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
439                                         PHM_PlatformCaps_ClockStretcher)) {
440                                 for (j = 1; j < socclk_table->count; j++) {
441                                         if (socclk_table->entries[j].clk == sclk &&
442                                                         socclk_table->entries[j].cks_enable == 0) {
443                                                 sclk += 5000;
444                                                 break;
445                                         }
446                                 }
447                         }
448
449                         PP_ASSERT_WITH_CODE(!atomctrl_get_voltage_evv_on_sclk_ai(hwmgr,
450                                         VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc),
451                                         "Error retrieving EVV voltage value!",
452                                         continue);
453
454
455                         /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
456                         PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0),
457                                         "Invalid VDDC value", result = -EINVAL;);
458
459                         /* the voltage should not be zero nor equal to leakage ID */
460                         if (vddc != 0 && vddc != vv_id) {
461                                 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100);
462                                 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
463                                 data->vddc_leakage.count++;
464                         }
465                 }
466         }
467
468         return 0;
469 }
470
471 /**
472  * Change virtual leakage voltage to actual value.
473  *
474  * @param     hwmgr  the address of the powerplay hardware manager.
475  * @param     pointer to changing voltage
476  * @param     pointer to leakage table
477  */
478 static void vega10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
479                 uint16_t *voltage, struct vega10_leakage_voltage *leakage_table)
480 {
481         uint32_t index;
482
483         /* search for leakage voltage ID 0xff01 ~ 0xff08 */
484         for (index = 0; index < leakage_table->count; index++) {
485                 /* if this voltage matches a leakage voltage ID */
486                 /* patch with actual leakage voltage */
487                 if (leakage_table->leakage_id[index] == *voltage) {
488                         *voltage = leakage_table->actual_voltage[index];
489                         break;
490                 }
491         }
492
493         if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
494                 pr_info("Voltage value looks like a Leakage ID \
495                                 but it's not patched\n");
496 }
497
498 /**
499 * Patch voltage lookup table by EVV leakages.
500 *
501 * @param     hwmgr  the address of the powerplay hardware manager.
502 * @param     pointer to voltage lookup table
503 * @param     pointer to leakage table
504 * @return     always 0
505 */
506 static int vega10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
507                 phm_ppt_v1_voltage_lookup_table *lookup_table,
508                 struct vega10_leakage_voltage *leakage_table)
509 {
510         uint32_t i;
511
512         for (i = 0; i < lookup_table->count; i++)
513                 vega10_patch_with_vdd_leakage(hwmgr,
514                                 &lookup_table->entries[i].us_vdd, leakage_table);
515
516         return 0;
517 }
518
519 static int vega10_patch_clock_voltage_limits_with_vddc_leakage(
520                 struct pp_hwmgr *hwmgr, struct vega10_leakage_voltage *leakage_table,
521                 uint16_t *vddc)
522 {
523         vega10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
524
525         return 0;
526 }
527 #endif
528
529 static int vega10_patch_voltage_dependency_tables_with_lookup_table(
530                 struct pp_hwmgr *hwmgr)
531 {
532         uint8_t entry_id;
533         uint8_t voltage_id;
534         struct phm_ppt_v2_information *table_info =
535                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
536         struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table =
537                         table_info->vdd_dep_on_socclk;
538         struct phm_ppt_v1_clock_voltage_dependency_table *gfxclk_table =
539                         table_info->vdd_dep_on_sclk;
540         struct phm_ppt_v1_clock_voltage_dependency_table *dcefclk_table =
541                         table_info->vdd_dep_on_dcefclk;
542         struct phm_ppt_v1_clock_voltage_dependency_table *pixclk_table =
543                         table_info->vdd_dep_on_pixclk;
544         struct phm_ppt_v1_clock_voltage_dependency_table *dspclk_table =
545                         table_info->vdd_dep_on_dispclk;
546         struct phm_ppt_v1_clock_voltage_dependency_table *phyclk_table =
547                         table_info->vdd_dep_on_phyclk;
548         struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
549                         table_info->vdd_dep_on_mclk;
550         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
551                         table_info->mm_dep_table;
552
553         for (entry_id = 0; entry_id < socclk_table->count; entry_id++) {
554                 voltage_id = socclk_table->entries[entry_id].vddInd;
555                 socclk_table->entries[entry_id].vddc =
556                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
557         }
558
559         for (entry_id = 0; entry_id < gfxclk_table->count; entry_id++) {
560                 voltage_id = gfxclk_table->entries[entry_id].vddInd;
561                 gfxclk_table->entries[entry_id].vddc =
562                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
563         }
564
565         for (entry_id = 0; entry_id < dcefclk_table->count; entry_id++) {
566                 voltage_id = dcefclk_table->entries[entry_id].vddInd;
567                 dcefclk_table->entries[entry_id].vddc =
568                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
569         }
570
571         for (entry_id = 0; entry_id < pixclk_table->count; entry_id++) {
572                 voltage_id = pixclk_table->entries[entry_id].vddInd;
573                 pixclk_table->entries[entry_id].vddc =
574                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
575         }
576
577         for (entry_id = 0; entry_id < dspclk_table->count; entry_id++) {
578                 voltage_id = dspclk_table->entries[entry_id].vddInd;
579                 dspclk_table->entries[entry_id].vddc =
580                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
581         }
582
583         for (entry_id = 0; entry_id < phyclk_table->count; entry_id++) {
584                 voltage_id = phyclk_table->entries[entry_id].vddInd;
585                 phyclk_table->entries[entry_id].vddc =
586                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
587         }
588
589         for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
590                 voltage_id = mclk_table->entries[entry_id].vddInd;
591                 mclk_table->entries[entry_id].vddc =
592                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
593                 voltage_id = mclk_table->entries[entry_id].vddciInd;
594                 mclk_table->entries[entry_id].vddci =
595                                 table_info->vddci_lookup_table->entries[voltage_id].us_vdd;
596                 voltage_id = mclk_table->entries[entry_id].mvddInd;
597                 mclk_table->entries[entry_id].mvdd =
598                                 table_info->vddmem_lookup_table->entries[voltage_id].us_vdd;
599         }
600
601         for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
602                 voltage_id = mm_table->entries[entry_id].vddcInd;
603                 mm_table->entries[entry_id].vddc =
604                         table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
605         }
606
607         return 0;
608
609 }
610
611 static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr,
612                 struct phm_ppt_v1_voltage_lookup_table *lookup_table)
613 {
614         uint32_t table_size, i, j;
615         struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
616
617         PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count,
618                 "Lookup table is empty", return -EINVAL);
619
620         table_size = lookup_table->count;
621
622         /* Sorting voltages */
623         for (i = 0; i < table_size - 1; i++) {
624                 for (j = i + 1; j > 0; j--) {
625                         if (lookup_table->entries[j].us_vdd <
626                                         lookup_table->entries[j - 1].us_vdd) {
627                                 tmp_voltage_lookup_record = lookup_table->entries[j - 1];
628                                 lookup_table->entries[j - 1] = lookup_table->entries[j];
629                                 lookup_table->entries[j] = tmp_voltage_lookup_record;
630                         }
631                 }
632         }
633
634         return 0;
635 }
636
637 static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr)
638 {
639         int result = 0;
640         int tmp_result;
641         struct phm_ppt_v2_information *table_info =
642                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
643 #ifdef PPLIB_VEGA10_EVV_SUPPORT
644         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
645
646         tmp_result = vega10_patch_lookup_table_with_leakage(hwmgr,
647                         table_info->vddc_lookup_table, &(data->vddc_leakage));
648         if (tmp_result)
649                 result = tmp_result;
650
651         tmp_result = vega10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
652                         &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
653         if (tmp_result)
654                 result = tmp_result;
655 #endif
656
657         tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
658         if (tmp_result)
659                 result = tmp_result;
660
661         tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
662         if (tmp_result)
663                 result = tmp_result;
664
665         return result;
666 }
667
668 static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
669 {
670         struct phm_ppt_v2_information *table_info =
671                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
672         struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
673                         table_info->vdd_dep_on_socclk;
674         struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
675                         table_info->vdd_dep_on_mclk;
676
677         PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table,
678                 "VDD dependency on SCLK table is missing. \
679                 This table is mandatory", return -EINVAL);
680         PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
681                 "VDD dependency on SCLK table is empty. \
682                 This table is mandatory", return -EINVAL);
683
684         PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table,
685                 "VDD dependency on MCLK table is missing. \
686                 This table is mandatory", return -EINVAL);
687         PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
688                 "VDD dependency on MCLK table is empty. \
689                 This table is mandatory", return -EINVAL);
690
691         table_info->max_clock_voltage_on_ac.sclk =
692                 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
693         table_info->max_clock_voltage_on_ac.mclk =
694                 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
695         table_info->max_clock_voltage_on_ac.vddc =
696                 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
697         table_info->max_clock_voltage_on_ac.vddci =
698                 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
699
700         hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
701                 table_info->max_clock_voltage_on_ac.sclk;
702         hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
703                 table_info->max_clock_voltage_on_ac.mclk;
704         hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
705                 table_info->max_clock_voltage_on_ac.vddc;
706         hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
707                 table_info->max_clock_voltage_on_ac.vddci;
708
709         return 0;
710 }
711
712 static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
713 {
714         kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
715         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
716
717         kfree(hwmgr->backend);
718         hwmgr->backend = NULL;
719
720         return 0;
721 }
722
723 static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
724 {
725         int result = 0;
726         struct vega10_hwmgr *data;
727         uint32_t config_telemetry = 0;
728         struct pp_atomfwctrl_voltage_table vol_table;
729         struct cgs_system_info sys_info = {0};
730
731         data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL);
732         if (data == NULL)
733                 return -ENOMEM;
734
735         hwmgr->backend = data;
736
737         vega10_set_default_registry_data(hwmgr);
738
739         data->disable_dpm_mask = 0xff;
740         data->workload_mask = 0xff;
741
742         /* need to set voltage control types before EVV patching */
743         data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
744         data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE;
745         data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE;
746
747         /* VDDCR_SOC */
748         if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
749                         VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
750                 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
751                                 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2,
752                                 &vol_table)) {
753                         config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) |
754                                         (vol_table.telemetry_offset & 0xff);
755                         data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
756                 }
757         } else {
758                 kfree(hwmgr->backend);
759                 hwmgr->backend = NULL;
760                 PP_ASSERT_WITH_CODE(false,
761                                 "VDDCR_SOC is not SVID2!",
762                                 return -1);
763         }
764
765         /* MVDDC */
766         if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
767                         VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) {
768                 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
769                                 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2,
770                                 &vol_table)) {
771                         config_telemetry |=
772                                         ((vol_table.telemetry_slope << 24) & 0xff000000) |
773                                         ((vol_table.telemetry_offset << 16) & 0xff0000);
774                         data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
775                 }
776         }
777
778          /* VDDCI_MEM */
779         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
780                         PHM_PlatformCaps_ControlVDDCI)) {
781                 if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
782                                 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
783                         data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO;
784         }
785
786         data->config_telemetry = config_telemetry;
787
788         vega10_set_features_platform_caps(hwmgr);
789
790         vega10_init_dpm_defaults(hwmgr);
791
792 #ifdef PPLIB_VEGA10_EVV_SUPPORT
793         /* Get leakage voltage based on leakage ID. */
794         PP_ASSERT_WITH_CODE(!vega10_get_evv_voltages(hwmgr),
795                         "Get EVV Voltage Failed.  Abort Driver loading!",
796                         return -1);
797 #endif
798
799         /* Patch our voltage dependency table with actual leakage voltage
800          * We need to perform leakage translation before it's used by other functions
801          */
802         vega10_complete_dependency_tables(hwmgr);
803
804         /* Parse pptable data read from VBIOS */
805         vega10_set_private_data_based_on_pptable(hwmgr);
806
807         data->is_tlu_enabled = false;
808
809         hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
810                         VEGA10_MAX_HARDWARE_POWERLEVELS;
811         hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
812         hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
813
814         hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
815         /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
816         hwmgr->platform_descriptor.clockStep.engineClock = 500;
817         hwmgr->platform_descriptor.clockStep.memoryClock = 500;
818
819         sys_info.size = sizeof(struct cgs_system_info);
820         sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
821         result = cgs_query_system_info(hwmgr->device, &sys_info);
822         data->total_active_cus = sys_info.value;
823         /* Setup default Overdrive Fan control settings */
824         data->odn_fan_table.target_fan_speed =
825                         hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
826         data->odn_fan_table.target_temperature =
827                         hwmgr->thermal_controller.
828                         advanceFanControlParameters.ucTargetTemperature;
829         data->odn_fan_table.min_performance_clock =
830                         hwmgr->thermal_controller.advanceFanControlParameters.
831                         ulMinFanSCLKAcousticLimit;
832         data->odn_fan_table.min_fan_limit =
833                         hwmgr->thermal_controller.
834                         advanceFanControlParameters.usFanPWMMinLimit *
835                         hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
836
837         return result;
838 }
839
840 static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr)
841 {
842         struct vega10_hwmgr *data =
843                         (struct vega10_hwmgr *)(hwmgr->backend);
844
845         data->low_sclk_interrupt_threshold = 0;
846
847         return 0;
848 }
849
850 static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
851 {
852         struct vega10_hwmgr *data =
853                         (struct vega10_hwmgr *)(hwmgr->backend);
854         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
855
856         struct pp_atomfwctrl_voltage_table table;
857         uint8_t i, j;
858         uint32_t mask = 0;
859         uint32_t tmp;
860         int32_t ret = 0;
861
862         ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM,
863                                                 VOLTAGE_OBJ_GPIO_LUT, &table);
864
865         if (!ret) {
866                 tmp = table.mask_low;
867                 for (i = 0, j = 0; i < 32; i++) {
868                         if (tmp & 1) {
869                                 mask |= (uint32_t)(i << (8 * j));
870                                 if (++j >= 3)
871                                         break;
872                         }
873                         tmp >>= 1;
874                 }
875         }
876
877         pp_table->LedPin0 = (uint8_t)(mask & 0xff);
878         pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff);
879         pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff);
880         return 0;
881 }
882
883 static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr)
884 {
885         PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr),
886                         "Failed to init sclk threshold!",
887                         return -EINVAL);
888
889         PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr),
890                         "Failed to set up led dpm config!",
891                         return -EINVAL);
892
893         return 0;
894 }
895
896 static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
897 {
898         uint32_t features_enabled;
899
900         if (!vega10_get_smc_features(hwmgr->smumgr, &features_enabled)) {
901                 if (features_enabled & SMC_DPM_FEATURES)
902                         return true;
903         }
904         return false;
905 }
906
907 /**
908 * Remove repeated voltage values and create table with unique values.
909 *
910 * @param    hwmgr  the address of the powerplay hardware manager.
911 * @param    vol_table  the pointer to changing voltage table
912 * @return    0 in success
913 */
914
915 static int vega10_trim_voltage_table(struct pp_hwmgr *hwmgr,
916                 struct pp_atomfwctrl_voltage_table *vol_table)
917 {
918         uint32_t i, j;
919         uint16_t vvalue;
920         bool found = false;
921         struct pp_atomfwctrl_voltage_table *table;
922
923         PP_ASSERT_WITH_CODE(vol_table,
924                         "Voltage Table empty.", return -EINVAL);
925         table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table),
926                         GFP_KERNEL);
927
928         if (!table)
929                 return -ENOMEM;
930
931         table->mask_low = vol_table->mask_low;
932         table->phase_delay = vol_table->phase_delay;
933
934         for (i = 0; i < vol_table->count; i++) {
935                 vvalue = vol_table->entries[i].value;
936                 found = false;
937
938                 for (j = 0; j < table->count; j++) {
939                         if (vvalue == table->entries[j].value) {
940                                 found = true;
941                                 break;
942                         }
943                 }
944
945                 if (!found) {
946                         table->entries[table->count].value = vvalue;
947                         table->entries[table->count].smio_low =
948                                         vol_table->entries[i].smio_low;
949                         table->count++;
950                 }
951         }
952
953         memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table));
954         kfree(table);
955
956         return 0;
957 }
958
959 static int vega10_get_mvdd_voltage_table(struct pp_hwmgr *hwmgr,
960                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
961                 struct pp_atomfwctrl_voltage_table *vol_table)
962 {
963         int i;
964
965         PP_ASSERT_WITH_CODE(dep_table->count,
966                         "Voltage Dependency Table empty.",
967                         return -EINVAL);
968
969         vol_table->mask_low = 0;
970         vol_table->phase_delay = 0;
971         vol_table->count = dep_table->count;
972
973         for (i = 0; i < vol_table->count; i++) {
974                 vol_table->entries[i].value = dep_table->entries[i].mvdd;
975                 vol_table->entries[i].smio_low = 0;
976         }
977
978         PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr,
979                         vol_table),
980                         "Failed to trim MVDD Table!",
981                         return -1);
982
983         return 0;
984 }
985
986 static int vega10_get_vddci_voltage_table(struct pp_hwmgr *hwmgr,
987                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
988                 struct pp_atomfwctrl_voltage_table *vol_table)
989 {
990         uint32_t i;
991
992         PP_ASSERT_WITH_CODE(dep_table->count,
993                         "Voltage Dependency Table empty.",
994                         return -EINVAL);
995
996         vol_table->mask_low = 0;
997         vol_table->phase_delay = 0;
998         vol_table->count = dep_table->count;
999
1000         for (i = 0; i < dep_table->count; i++) {
1001                 vol_table->entries[i].value = dep_table->entries[i].vddci;
1002                 vol_table->entries[i].smio_low = 0;
1003         }
1004
1005         PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, vol_table),
1006                         "Failed to trim VDDCI table.",
1007                         return -1);
1008
1009         return 0;
1010 }
1011
1012 static int vega10_get_vdd_voltage_table(struct pp_hwmgr *hwmgr,
1013                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
1014                 struct pp_atomfwctrl_voltage_table *vol_table)
1015 {
1016         int i;
1017
1018         PP_ASSERT_WITH_CODE(dep_table->count,
1019                         "Voltage Dependency Table empty.",
1020                         return -EINVAL);
1021
1022         vol_table->mask_low = 0;
1023         vol_table->phase_delay = 0;
1024         vol_table->count = dep_table->count;
1025
1026         for (i = 0; i < vol_table->count; i++) {
1027                 vol_table->entries[i].value = dep_table->entries[i].vddc;
1028                 vol_table->entries[i].smio_low = 0;
1029         }
1030
1031         return 0;
1032 }
1033
1034 /* ---- Voltage Tables ----
1035  * If the voltage table would be bigger than
1036  * what will fit into the state table on
1037  * the SMC keep only the higher entries.
1038  */
1039 static void vega10_trim_voltage_table_to_fit_state_table(
1040                 struct pp_hwmgr *hwmgr,
1041                 uint32_t max_vol_steps,
1042                 struct pp_atomfwctrl_voltage_table *vol_table)
1043 {
1044         unsigned int i, diff;
1045
1046         if (vol_table->count <= max_vol_steps)
1047                 return;
1048
1049         diff = vol_table->count - max_vol_steps;
1050
1051         for (i = 0; i < max_vol_steps; i++)
1052                 vol_table->entries[i] = vol_table->entries[i + diff];
1053
1054         vol_table->count = max_vol_steps;
1055 }
1056
1057 /**
1058 * Create Voltage Tables.
1059 *
1060 * @param    hwmgr  the address of the powerplay hardware manager.
1061 * @return   always 0
1062 */
1063 static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr)
1064 {
1065         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
1066         struct phm_ppt_v2_information *table_info =
1067                         (struct phm_ppt_v2_information *)hwmgr->pptable;
1068         int result;
1069
1070         if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
1071                         data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1072                 result = vega10_get_mvdd_voltage_table(hwmgr,
1073                                 table_info->vdd_dep_on_mclk,
1074                                 &(data->mvdd_voltage_table));
1075                 PP_ASSERT_WITH_CODE(!result,
1076                                 "Failed to retrieve MVDDC table!",
1077                                 return result);
1078         }
1079
1080         if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1081                 result = vega10_get_vddci_voltage_table(hwmgr,
1082                                 table_info->vdd_dep_on_mclk,
1083                                 &(data->vddci_voltage_table));
1084                 PP_ASSERT_WITH_CODE(!result,
1085                                 "Failed to retrieve VDDCI_MEM table!",
1086                                 return result);
1087         }
1088
1089         if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
1090                         data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1091                 result = vega10_get_vdd_voltage_table(hwmgr,
1092                                 table_info->vdd_dep_on_sclk,
1093                                 &(data->vddc_voltage_table));
1094                 PP_ASSERT_WITH_CODE(!result,
1095                                 "Failed to retrieve VDDCR_SOC table!",
1096                                 return result);
1097         }
1098
1099         PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 16,
1100                         "Too many voltage values for VDDC. Trimming to fit state table.",
1101                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1102                                         16, &(data->vddc_voltage_table)));
1103
1104         PP_ASSERT_WITH_CODE(data->vddci_voltage_table.count <= 16,
1105                         "Too many voltage values for VDDCI. Trimming to fit state table.",
1106                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1107                                         16, &(data->vddci_voltage_table)));
1108
1109         PP_ASSERT_WITH_CODE(data->mvdd_voltage_table.count <= 16,
1110                         "Too many voltage values for MVDD. Trimming to fit state table.",
1111                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1112                                         16, &(data->mvdd_voltage_table)));
1113
1114
1115         return 0;
1116 }
1117
1118 /*
1119  * @fn vega10_init_dpm_state
1120  * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
1121  *
1122  * @param    dpm_state - the address of the DPM Table to initiailize.
1123  * @return   None.
1124  */
1125 static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state)
1126 {
1127         dpm_state->soft_min_level = 0xff;
1128         dpm_state->soft_max_level = 0xff;
1129         dpm_state->hard_min_level = 0xff;
1130         dpm_state->hard_max_level = 0xff;
1131 }
1132
1133 static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr,
1134                 struct vega10_single_dpm_table *dpm_table,
1135                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
1136 {
1137         int i;
1138
1139         for (i = 0; i < dep_table->count; i++) {
1140                 if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <=
1141                                 dep_table->entries[i].clk) {
1142                         dpm_table->dpm_levels[dpm_table->count].value =
1143                                         dep_table->entries[i].clk;
1144                         dpm_table->dpm_levels[dpm_table->count].enabled = true;
1145                         dpm_table->count++;
1146                 }
1147         }
1148 }
1149 static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
1150 {
1151         struct vega10_hwmgr *data =
1152                         (struct vega10_hwmgr *)(hwmgr->backend);
1153         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
1154         struct phm_ppt_v2_information *table_info =
1155                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1156         struct phm_ppt_v1_pcie_table *bios_pcie_table =
1157                         table_info->pcie_table;
1158         uint32_t i;
1159
1160         PP_ASSERT_WITH_CODE(bios_pcie_table->count,
1161                         "Incorrect number of PCIE States from VBIOS!",
1162                         return -1);
1163
1164         for (i = 0; i < NUM_LINK_LEVELS; i++) {
1165                 if (data->registry_data.pcieSpeedOverride)
1166                         pcie_table->pcie_gen[i] =
1167                                         data->registry_data.pcieSpeedOverride;
1168                 else
1169                         pcie_table->pcie_gen[i] =
1170                                         bios_pcie_table->entries[i].gen_speed;
1171
1172                 if (data->registry_data.pcieLaneOverride)
1173                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1174                                         data->registry_data.pcieLaneOverride);
1175                 else
1176                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1177                                                         bios_pcie_table->entries[i].lane_width);
1178                 printk("pcie_table->pcie_lane[%d] is %d  %d\n", i, pcie_table->pcie_lane[i], bios_pcie_table->entries[i].lane_width);
1179                 if (data->registry_data.pcieClockOverride)
1180                         pcie_table->lclk[i] =
1181                                         data->registry_data.pcieClockOverride;
1182                 else
1183                         pcie_table->lclk[i] =
1184                                         bios_pcie_table->entries[i].pcie_sclk;
1185         }
1186
1187         pcie_table->count = NUM_LINK_LEVELS;
1188
1189         return 0;
1190 }
1191
1192 /*
1193  * This function is to initialize all DPM state tables
1194  * for SMU based on the dependency table.
1195  * Dynamic state patching function will then trim these
1196  * state tables to the allowed range based
1197  * on the power policy or external client requests,
1198  * such as UVD request, etc.
1199  */
1200 static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1201 {
1202         struct vega10_hwmgr *data =
1203                         (struct vega10_hwmgr *)(hwmgr->backend);
1204         struct phm_ppt_v2_information *table_info =
1205                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1206         struct vega10_single_dpm_table *dpm_table;
1207         uint32_t i;
1208
1209         struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table =
1210                         table_info->vdd_dep_on_socclk;
1211         struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table =
1212                         table_info->vdd_dep_on_sclk;
1213         struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
1214                         table_info->vdd_dep_on_mclk;
1215         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table =
1216                         table_info->mm_dep_table;
1217         struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table =
1218                         table_info->vdd_dep_on_dcefclk;
1219         struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table =
1220                         table_info->vdd_dep_on_pixclk;
1221         struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table =
1222                         table_info->vdd_dep_on_dispclk;
1223         struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table =
1224                         table_info->vdd_dep_on_phyclk;
1225
1226         PP_ASSERT_WITH_CODE(dep_soc_table,
1227                         "SOCCLK dependency table is missing. This table is mandatory",
1228                         return -EINVAL);
1229         PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1,
1230                         "SOCCLK dependency table is empty. This table is mandatory",
1231                         return -EINVAL);
1232
1233         PP_ASSERT_WITH_CODE(dep_gfx_table,
1234                         "GFXCLK dependency table is missing. This table is mandatory",
1235                         return -EINVAL);
1236         PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1,
1237                         "GFXCLK dependency table is empty. This table is mandatory",
1238                         return -EINVAL);
1239
1240         PP_ASSERT_WITH_CODE(dep_mclk_table,
1241                         "MCLK dependency table is missing. This table is mandatory",
1242                         return -EINVAL);
1243         PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
1244                         "MCLK dependency table has to have is missing. This table is mandatory",
1245                         return -EINVAL);
1246
1247         /* Initialize Sclk DPM table based on allow Sclk values */
1248         data->dpm_table.soc_table.count = 0;
1249         data->dpm_table.gfx_table.count = 0;
1250         data->dpm_table.dcef_table.count = 0;
1251
1252         dpm_table = &(data->dpm_table.soc_table);
1253         vega10_setup_default_single_dpm_table(hwmgr,
1254                         dpm_table,
1255                         dep_soc_table);
1256
1257         vega10_init_dpm_state(&(dpm_table->dpm_state));
1258
1259         dpm_table = &(data->dpm_table.gfx_table);
1260         vega10_setup_default_single_dpm_table(hwmgr,
1261                         dpm_table,
1262                         dep_gfx_table);
1263         vega10_init_dpm_state(&(dpm_table->dpm_state));
1264
1265         /* Initialize Mclk DPM table based on allow Mclk values */
1266         data->dpm_table.mem_table.count = 0;
1267         dpm_table = &(data->dpm_table.mem_table);
1268         vega10_setup_default_single_dpm_table(hwmgr,
1269                         dpm_table,
1270                         dep_mclk_table);
1271         vega10_init_dpm_state(&(dpm_table->dpm_state));
1272
1273         data->dpm_table.eclk_table.count = 0;
1274         dpm_table = &(data->dpm_table.eclk_table);
1275         for (i = 0; i < dep_mm_table->count; i++) {
1276                 if (i == 0 || dpm_table->dpm_levels
1277                                 [dpm_table->count - 1].value <=
1278                                                 dep_mm_table->entries[i].eclk) {
1279                         dpm_table->dpm_levels[dpm_table->count].value =
1280                                         dep_mm_table->entries[i].eclk;
1281                         dpm_table->dpm_levels[dpm_table->count].enabled =
1282                                         (i == 0) ? true : false;
1283                         dpm_table->count++;
1284                 }
1285         }
1286         vega10_init_dpm_state(&(dpm_table->dpm_state));
1287
1288         data->dpm_table.vclk_table.count = 0;
1289         data->dpm_table.dclk_table.count = 0;
1290         dpm_table = &(data->dpm_table.vclk_table);
1291         for (i = 0; i < dep_mm_table->count; i++) {
1292                 if (i == 0 || dpm_table->dpm_levels
1293                                 [dpm_table->count - 1].value <=
1294                                                 dep_mm_table->entries[i].vclk) {
1295                         dpm_table->dpm_levels[dpm_table->count].value =
1296                                         dep_mm_table->entries[i].vclk;
1297                         dpm_table->dpm_levels[dpm_table->count].enabled =
1298                                         (i == 0) ? true : false;
1299                         dpm_table->count++;
1300                 }
1301         }
1302         vega10_init_dpm_state(&(dpm_table->dpm_state));
1303
1304         dpm_table = &(data->dpm_table.dclk_table);
1305         for (i = 0; i < dep_mm_table->count; i++) {
1306                 if (i == 0 || dpm_table->dpm_levels
1307                                 [dpm_table->count - 1].value <=
1308                                                 dep_mm_table->entries[i].dclk) {
1309                         dpm_table->dpm_levels[dpm_table->count].value =
1310                                         dep_mm_table->entries[i].dclk;
1311                         dpm_table->dpm_levels[dpm_table->count].enabled =
1312                                         (i == 0) ? true : false;
1313                         dpm_table->count++;
1314                 }
1315         }
1316         vega10_init_dpm_state(&(dpm_table->dpm_state));
1317
1318         /* Assume there is no headless Vega10 for now */
1319         dpm_table = &(data->dpm_table.dcef_table);
1320         vega10_setup_default_single_dpm_table(hwmgr,
1321                         dpm_table,
1322                         dep_dcef_table);
1323
1324         vega10_init_dpm_state(&(dpm_table->dpm_state));
1325
1326         dpm_table = &(data->dpm_table.pixel_table);
1327         vega10_setup_default_single_dpm_table(hwmgr,
1328                         dpm_table,
1329                         dep_pix_table);
1330
1331         vega10_init_dpm_state(&(dpm_table->dpm_state));
1332
1333         dpm_table = &(data->dpm_table.display_table);
1334         vega10_setup_default_single_dpm_table(hwmgr,
1335                         dpm_table,
1336                         dep_disp_table);
1337
1338         vega10_init_dpm_state(&(dpm_table->dpm_state));
1339
1340         dpm_table = &(data->dpm_table.phy_table);
1341         vega10_setup_default_single_dpm_table(hwmgr,
1342                         dpm_table,
1343                         dep_phy_table);
1344
1345         vega10_init_dpm_state(&(dpm_table->dpm_state));
1346
1347         vega10_setup_default_pcie_table(hwmgr);
1348
1349         /* save a copy of the default DPM table */
1350         memcpy(&(data->golden_dpm_table), &(data->dpm_table),
1351                         sizeof(struct vega10_dpm_table));
1352
1353         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1354                         PHM_PlatformCaps_ODNinACSupport) ||
1355                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1356                         PHM_PlatformCaps_ODNinDCSupport)) {
1357                 data->odn_dpm_table.odn_core_clock_dpm_levels.
1358                 number_of_performance_levels = data->dpm_table.gfx_table.count;
1359                 for (i = 0; i < data->dpm_table.gfx_table.count; i++) {
1360                         data->odn_dpm_table.odn_core_clock_dpm_levels.
1361                         performance_level_entries[i].clock =
1362                                         data->dpm_table.gfx_table.dpm_levels[i].value;
1363                         data->odn_dpm_table.odn_core_clock_dpm_levels.
1364                         performance_level_entries[i].enabled = true;
1365                 }
1366
1367                 data->odn_dpm_table.vdd_dependency_on_sclk.count =
1368                                 dep_gfx_table->count;
1369                 for (i = 0; i < dep_gfx_table->count; i++) {
1370                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].clk =
1371                                         dep_gfx_table->entries[i].clk;
1372                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].vddInd =
1373                                         dep_gfx_table->entries[i].vddInd;
1374                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_enable =
1375                                         dep_gfx_table->entries[i].cks_enable;
1376                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_voffset =
1377                                         dep_gfx_table->entries[i].cks_voffset;
1378                 }
1379
1380                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
1381                 number_of_performance_levels = data->dpm_table.mem_table.count;
1382                 for (i = 0; i < data->dpm_table.mem_table.count; i++) {
1383                         data->odn_dpm_table.odn_memory_clock_dpm_levels.
1384                         performance_level_entries[i].clock =
1385                                         data->dpm_table.mem_table.dpm_levels[i].value;
1386                         data->odn_dpm_table.odn_memory_clock_dpm_levels.
1387                         performance_level_entries[i].enabled = true;
1388                 }
1389
1390                 data->odn_dpm_table.vdd_dependency_on_mclk.count = dep_mclk_table->count;
1391                 for (i = 0; i < dep_mclk_table->count; i++) {
1392                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].clk =
1393                                         dep_mclk_table->entries[i].clk;
1394                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddInd =
1395                                         dep_mclk_table->entries[i].vddInd;
1396                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddci =
1397                                         dep_mclk_table->entries[i].vddci;
1398                 }
1399         }
1400
1401         return 0;
1402 }
1403
1404 /*
1405  * @fn vega10_populate_ulv_state
1406  * @brief Function to provide parameters for Utral Low Voltage state to SMC.
1407  *
1408  * @param    hwmgr - the address of the hardware manager.
1409  * @return   Always 0.
1410  */
1411 static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr)
1412 {
1413         struct vega10_hwmgr *data =
1414                         (struct vega10_hwmgr *)(hwmgr->backend);
1415         struct phm_ppt_v2_information *table_info =
1416                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1417
1418         data->smc_state_table.pp_table.UlvOffsetVid =
1419                         (uint8_t)table_info->us_ulv_voltage_offset;
1420
1421         data->smc_state_table.pp_table.UlvSmnclkDid =
1422                         (uint8_t)(table_info->us_ulv_smnclk_did);
1423         data->smc_state_table.pp_table.UlvMp1clkDid =
1424                         (uint8_t)(table_info->us_ulv_mp1clk_did);
1425         data->smc_state_table.pp_table.UlvGfxclkBypass =
1426                         (uint8_t)(table_info->us_ulv_gfxclk_bypass);
1427         data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 =
1428                         (uint8_t)(data->vddc_voltage_table.psi0_enable);
1429         data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 =
1430                         (uint8_t)(data->vddc_voltage_table.psi1_enable);
1431
1432         return 0;
1433 }
1434
1435 static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr,
1436                 uint32_t lclock, uint8_t *curr_lclk_did)
1437 {
1438         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1439
1440         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1441                         hwmgr,
1442                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1443                         lclock, &dividers),
1444                         "Failed to get LCLK clock settings from VBIOS!",
1445                         return -1);
1446
1447         *curr_lclk_did = dividers.ulDid;
1448
1449         return 0;
1450 }
1451
1452 static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
1453 {
1454         int result = -1;
1455         struct vega10_hwmgr *data =
1456                         (struct vega10_hwmgr *)(hwmgr->backend);
1457         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1458         struct vega10_pcie_table *pcie_table =
1459                         &(data->dpm_table.pcie_table);
1460         uint32_t i, j;
1461
1462         for (i = 0; i < pcie_table->count; i++) {
1463                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i];
1464                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i];
1465
1466                 result = vega10_populate_single_lclk_level(hwmgr,
1467                                 pcie_table->lclk[i], &(pp_table->LclkDid[i]));
1468                 if (result) {
1469                         pr_info("Populate LClock Level %d Failed!\n", i);
1470                         return result;
1471                 }
1472         }
1473
1474         j = i - 1;
1475         while (i < NUM_LINK_LEVELS) {
1476                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j];
1477                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j];
1478
1479                 result = vega10_populate_single_lclk_level(hwmgr,
1480                                 pcie_table->lclk[j], &(pp_table->LclkDid[i]));
1481                 if (result) {
1482                         pr_info("Populate LClock Level %d Failed!\n", i);
1483                         return result;
1484                 }
1485                 i++;
1486         }
1487
1488         return result;
1489 }
1490
1491 /**
1492 * Populates single SMC GFXSCLK structure using the provided engine clock
1493 *
1494 * @param    hwmgr      the address of the hardware manager
1495 * @param    gfx_clock  the GFX clock to use to populate the structure.
1496 * @param    current_gfxclk_level  location in PPTable for the SMC GFXCLK structure.
1497 */
1498
1499 static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr,
1500                 uint32_t gfx_clock, PllSetting_t *current_gfxclk_level)
1501 {
1502         struct phm_ppt_v2_information *table_info =
1503                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1504         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk =
1505                         table_info->vdd_dep_on_sclk;
1506         struct vega10_hwmgr *data =
1507                         (struct vega10_hwmgr *)(hwmgr->backend);
1508         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1509         uint32_t i;
1510
1511         if (data->apply_overdrive_next_settings_mask &
1512                         DPMTABLE_OD_UPDATE_VDDC)
1513                 dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1514                                                 &(data->odn_dpm_table.vdd_dependency_on_sclk);
1515
1516         PP_ASSERT_WITH_CODE(dep_on_sclk,
1517                         "Invalid SOC_VDD-GFX_CLK Dependency Table!",
1518                         return -EINVAL);
1519
1520         for (i = 0; i < dep_on_sclk->count; i++) {
1521                 if (dep_on_sclk->entries[i].clk == gfx_clock)
1522                         break;
1523         }
1524
1525         PP_ASSERT_WITH_CODE(dep_on_sclk->count > i,
1526                         "Cannot find gfx_clk in SOC_VDD-GFX_CLK!",
1527                         return -EINVAL);
1528         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1529                         COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK,
1530                         gfx_clock, &dividers),
1531                         "Failed to get GFX Clock settings from VBIOS!",
1532                         return -EINVAL);
1533
1534         /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */
1535         current_gfxclk_level->FbMult =
1536                         cpu_to_le32(dividers.ulPll_fb_mult);
1537         /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */
1538         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1539                                 PHM_PlatformCaps_EngineSpreadSpectrumSupport))
1540                 current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
1541         else
1542                 current_gfxclk_level->SsOn = 0;
1543         current_gfxclk_level->SsFbMult =
1544                         cpu_to_le32(dividers.ulPll_ss_fbsmult);
1545         current_gfxclk_level->SsSlewFrac =
1546                         cpu_to_le16(dividers.usPll_ss_slew_frac);
1547         current_gfxclk_level->Did = (uint8_t)(dividers.ulDid);
1548
1549         return 0;
1550 }
1551
1552 /**
1553  * @brief Populates single SMC SOCCLK structure using the provided clock.
1554  *
1555  * @param    hwmgr - the address of the hardware manager.
1556  * @param    soc_clock - the SOC clock to use to populate the structure.
1557  * @param    current_socclk_level - location in PPTable for the SMC SOCCLK structure.
1558  * @return   0 on success..
1559  */
1560 static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr,
1561                 uint32_t soc_clock, uint8_t *current_soc_did,
1562                 uint8_t *current_vol_index)
1563 {
1564         struct phm_ppt_v2_information *table_info =
1565                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1566         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc =
1567                         table_info->vdd_dep_on_socclk;
1568         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1569         uint32_t i;
1570
1571         PP_ASSERT_WITH_CODE(dep_on_soc,
1572                         "Invalid SOC_VDD-SOC_CLK Dependency Table!",
1573                         return -EINVAL);
1574         for (i = 0; i < dep_on_soc->count; i++) {
1575                 if (dep_on_soc->entries[i].clk == soc_clock)
1576                         break;
1577         }
1578         PP_ASSERT_WITH_CODE(dep_on_soc->count > i,
1579                         "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table",
1580                         return -EINVAL);
1581         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1582                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1583                         soc_clock, &dividers),
1584                         "Failed to get SOC Clock settings from VBIOS!",
1585                         return -EINVAL);
1586
1587         *current_soc_did = (uint8_t)dividers.ulDid;
1588         *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd);
1589
1590         return 0;
1591 }
1592
1593 uint16_t vega10_locate_vddc_given_clock(struct pp_hwmgr *hwmgr,
1594                 uint32_t clk,
1595                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
1596 {
1597         uint16_t i;
1598
1599         for (i = 0; i < dep_table->count; i++) {
1600                 if (dep_table->entries[i].clk == clk)
1601                         return dep_table->entries[i].vddc;
1602         }
1603
1604         pr_info("[LocateVddcGivenClock] Cannot locate SOC Vddc for this clock!");
1605         return 0;
1606 }
1607
1608 /**
1609 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
1610 *
1611 * @param    hwmgr      the address of the hardware manager
1612 */
1613 static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
1614 {
1615         struct vega10_hwmgr *data =
1616                         (struct vega10_hwmgr *)(hwmgr->backend);
1617         struct phm_ppt_v2_information *table_info =
1618                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1619         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
1620                         table_info->vdd_dep_on_socclk;
1621         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1622         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
1623         int result = 0;
1624         uint32_t i, j;
1625
1626         for (i = 0; i < dpm_table->count; i++) {
1627                 result = vega10_populate_single_gfx_level(hwmgr,
1628                                 dpm_table->dpm_levels[i].value,
1629                                 &(pp_table->GfxclkLevel[i]));
1630                 if (result)
1631                         return result;
1632         }
1633
1634         j = i - 1;
1635         while (i < NUM_GFXCLK_DPM_LEVELS) {
1636                 result = vega10_populate_single_gfx_level(hwmgr,
1637                                 dpm_table->dpm_levels[j].value,
1638                                 &(pp_table->GfxclkLevel[i]));
1639                 if (result)
1640                         return result;
1641                 i++;
1642         }
1643
1644         pp_table->GfxclkSlewRate =
1645                         cpu_to_le16(table_info->us_gfxclk_slew_rate);
1646
1647         dpm_table = &(data->dpm_table.soc_table);
1648         for (i = 0; i < dpm_table->count; i++) {
1649                 pp_table->SocVid[i] =
1650                                 (uint8_t)convert_to_vid(
1651                                 vega10_locate_vddc_given_clock(hwmgr,
1652                                                 dpm_table->dpm_levels[i].value,
1653                                                 dep_table));
1654                 result = vega10_populate_single_soc_level(hwmgr,
1655                                 dpm_table->dpm_levels[i].value,
1656                                 &(pp_table->SocclkDid[i]),
1657                                 &(pp_table->SocDpmVoltageIndex[i]));
1658                 if (result)
1659                         return result;
1660         }
1661
1662         j = i - 1;
1663         while (i < NUM_SOCCLK_DPM_LEVELS) {
1664                 pp_table->SocVid[i] = pp_table->SocVid[j];
1665                 result = vega10_populate_single_soc_level(hwmgr,
1666                                 dpm_table->dpm_levels[j].value,
1667                                 &(pp_table->SocclkDid[i]),
1668                                 &(pp_table->SocDpmVoltageIndex[i]));
1669                 if (result)
1670                         return result;
1671                 i++;
1672         }
1673
1674         return result;
1675 }
1676
1677 /**
1678  * @brief Populates single SMC GFXCLK structure using the provided clock.
1679  *
1680  * @param    hwmgr - the address of the hardware manager.
1681  * @param    mem_clock - the memory clock to use to populate the structure.
1682  * @return   0 on success..
1683  */
1684 static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
1685                 uint32_t mem_clock, uint8_t *current_mem_vid,
1686                 PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind)
1687 {
1688         struct vega10_hwmgr *data =
1689                         (struct vega10_hwmgr *)(hwmgr->backend);
1690         struct phm_ppt_v2_information *table_info =
1691                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1692         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk =
1693                         table_info->vdd_dep_on_mclk;
1694         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1695         uint32_t i;
1696
1697         if (data->apply_overdrive_next_settings_mask &
1698                         DPMTABLE_OD_UPDATE_VDDC)
1699                 dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1700                                         &data->odn_dpm_table.vdd_dependency_on_mclk;
1701
1702         PP_ASSERT_WITH_CODE(dep_on_mclk,
1703                         "Invalid SOC_VDD-UCLK Dependency Table!",
1704                         return -EINVAL);
1705
1706         for (i = 0; i < dep_on_mclk->count; i++) {
1707                 if (dep_on_mclk->entries[i].clk == mem_clock)
1708                         break;
1709         }
1710
1711         PP_ASSERT_WITH_CODE(dep_on_mclk->count > i,
1712                         "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!",
1713                         return -EINVAL);
1714
1715         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1716                         hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, &dividers),
1717                         "Failed to get UCLK settings from VBIOS!",
1718                         return -1);
1719
1720         *current_mem_vid =
1721                         (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd));
1722         *current_mem_soc_vind =
1723                         (uint8_t)(dep_on_mclk->entries[i].vddInd);
1724         current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult);
1725         current_memclk_level->Did = (uint8_t)(dividers.ulDid);
1726
1727         PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1,
1728                         "Invalid Divider ID!",
1729                         return -EINVAL);
1730
1731         return 0;
1732 }
1733
1734 /**
1735  * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states.
1736  *
1737  * @param    pHwMgr - the address of the hardware manager.
1738  * @return   PP_Result_OK on success.
1739  */
1740 static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1741 {
1742         struct vega10_hwmgr *data =
1743                         (struct vega10_hwmgr *)(hwmgr->backend);
1744         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1745         struct vega10_single_dpm_table *dpm_table =
1746                         &(data->dpm_table.mem_table);
1747         int result = 0;
1748         uint32_t i, j, reg, mem_channels;
1749
1750         for (i = 0; i < dpm_table->count; i++) {
1751                 result = vega10_populate_single_memory_level(hwmgr,
1752                                 dpm_table->dpm_levels[i].value,
1753                                 &(pp_table->MemVid[i]),
1754                                 &(pp_table->UclkLevel[i]),
1755                                 &(pp_table->MemSocVoltageIndex[i]));
1756                 if (result)
1757                         return result;
1758         }
1759
1760         j = i - 1;
1761         while (i < NUM_UCLK_DPM_LEVELS) {
1762                 result = vega10_populate_single_memory_level(hwmgr,
1763                                 dpm_table->dpm_levels[j].value,
1764                                 &(pp_table->MemVid[i]),
1765                                 &(pp_table->UclkLevel[i]),
1766                                 &(pp_table->MemSocVoltageIndex[i]));
1767                 if (result)
1768                         return result;
1769                 i++;
1770         }
1771
1772         reg = soc15_get_register_offset(DF_HWID, 0,
1773                         mmDF_CS_AON0_DramBaseAddress0_BASE_IDX,
1774                         mmDF_CS_AON0_DramBaseAddress0);
1775         mem_channels = (cgs_read_register(hwmgr->device, reg) &
1776                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
1777                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
1778         pp_table->NumMemoryChannels = cpu_to_le16(mem_channels);
1779         pp_table->MemoryChannelWidth =
1780                         cpu_to_le16(HBM_MEMORY_CHANNEL_WIDTH *
1781                                         channel_number[mem_channels]);
1782
1783         pp_table->LowestUclkReservedForUlv =
1784                         (uint8_t)(data->lowest_uclk_reserved_for_ulv);
1785
1786         return result;
1787 }
1788
1789 static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr,
1790                 DSPCLK_e disp_clock)
1791 {
1792         struct vega10_hwmgr *data =
1793                         (struct vega10_hwmgr *)(hwmgr->backend);
1794         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1795         struct phm_ppt_v2_information *table_info =
1796                         (struct phm_ppt_v2_information *)
1797                         (hwmgr->pptable);
1798         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
1799         uint32_t i;
1800         uint16_t clk = 0, vddc = 0;
1801         uint8_t vid = 0;
1802
1803         switch (disp_clock) {
1804         case DSPCLK_DCEFCLK:
1805                 dep_table = table_info->vdd_dep_on_dcefclk;
1806                 break;
1807         case DSPCLK_DISPCLK:
1808                 dep_table = table_info->vdd_dep_on_dispclk;
1809                 break;
1810         case DSPCLK_PIXCLK:
1811                 dep_table = table_info->vdd_dep_on_pixclk;
1812                 break;
1813         case DSPCLK_PHYCLK:
1814                 dep_table = table_info->vdd_dep_on_phyclk;
1815                 break;
1816         default:
1817                 return -1;
1818         }
1819
1820         PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS,
1821                         "Number Of Entries Exceeded maximum!",
1822                         return -1);
1823
1824         for (i = 0; i < dep_table->count; i++) {
1825                 clk = (uint16_t)(dep_table->entries[i].clk / 100);
1826                 vddc = table_info->vddc_lookup_table->
1827                                 entries[dep_table->entries[i].vddInd].us_vdd;
1828                 vid = (uint8_t)convert_to_vid(vddc);
1829                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1830                                 cpu_to_le16(clk);
1831                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1832                                 cpu_to_le16(vid);
1833         }
1834
1835         while (i < NUM_DSPCLK_LEVELS) {
1836                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1837                                 cpu_to_le16(clk);
1838                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1839                                 cpu_to_le16(vid);
1840                 i++;
1841         }
1842
1843         return 0;
1844 }
1845
1846 static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr)
1847 {
1848         uint32_t i;
1849
1850         for (i = 0; i < DSPCLK_COUNT; i++) {
1851                 PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i),
1852                                 "Failed to populate Clock in DisplayClockTable!",
1853                                 return -1);
1854         }
1855
1856         return 0;
1857 }
1858
1859 static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr,
1860                 uint32_t eclock, uint8_t *current_eclk_did,
1861                 uint8_t *current_soc_vol)
1862 {
1863         struct phm_ppt_v2_information *table_info =
1864                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1865         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1866                         table_info->mm_dep_table;
1867         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1868         uint32_t i;
1869
1870         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1871                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1872                         eclock, &dividers),
1873                         "Failed to get ECLK clock settings from VBIOS!",
1874                         return -1);
1875
1876         *current_eclk_did = (uint8_t)dividers.ulDid;
1877
1878         for (i = 0; i < dep_table->count; i++) {
1879                 if (dep_table->entries[i].eclk == eclock)
1880                         *current_soc_vol = dep_table->entries[i].vddcInd;
1881         }
1882
1883         return 0;
1884 }
1885
1886 static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr)
1887 {
1888         struct vega10_hwmgr *data =
1889                         (struct vega10_hwmgr *)(hwmgr->backend);
1890         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1891         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table);
1892         int result = -EINVAL;
1893         uint32_t i, j;
1894
1895         for (i = 0; i < dpm_table->count; i++) {
1896                 result = vega10_populate_single_eclock_level(hwmgr,
1897                                 dpm_table->dpm_levels[i].value,
1898                                 &(pp_table->EclkDid[i]),
1899                                 &(pp_table->VceDpmVoltageIndex[i]));
1900                 if (result)
1901                         return result;
1902         }
1903
1904         j = i - 1;
1905         while (i < NUM_VCE_DPM_LEVELS) {
1906                 result = vega10_populate_single_eclock_level(hwmgr,
1907                                 dpm_table->dpm_levels[j].value,
1908                                 &(pp_table->EclkDid[i]),
1909                                 &(pp_table->VceDpmVoltageIndex[i]));
1910                 if (result)
1911                         return result;
1912                 i++;
1913         }
1914
1915         return result;
1916 }
1917
1918 static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr,
1919                 uint32_t vclock, uint8_t *current_vclk_did)
1920 {
1921         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1922
1923         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1924                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1925                         vclock, &dividers),
1926                         "Failed to get VCLK clock settings from VBIOS!",
1927                         return -EINVAL);
1928
1929         *current_vclk_did = (uint8_t)dividers.ulDid;
1930
1931         return 0;
1932 }
1933
1934 static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr,
1935                 uint32_t dclock, uint8_t *current_dclk_did)
1936 {
1937         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1938
1939         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1940                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1941                         dclock, &dividers),
1942                         "Failed to get DCLK clock settings from VBIOS!",
1943                         return -EINVAL);
1944
1945         *current_dclk_did = (uint8_t)dividers.ulDid;
1946
1947         return 0;
1948 }
1949
1950 static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr)
1951 {
1952         struct vega10_hwmgr *data =
1953                         (struct vega10_hwmgr *)(hwmgr->backend);
1954         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1955         struct vega10_single_dpm_table *vclk_dpm_table =
1956                         &(data->dpm_table.vclk_table);
1957         struct vega10_single_dpm_table *dclk_dpm_table =
1958                         &(data->dpm_table.dclk_table);
1959         struct phm_ppt_v2_information *table_info =
1960                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1961         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1962                         table_info->mm_dep_table;
1963         int result = -EINVAL;
1964         uint32_t i, j;
1965
1966         for (i = 0; i < vclk_dpm_table->count; i++) {
1967                 result = vega10_populate_single_vclock_level(hwmgr,
1968                                 vclk_dpm_table->dpm_levels[i].value,
1969                                 &(pp_table->VclkDid[i]));
1970                 if (result)
1971                         return result;
1972         }
1973
1974         j = i - 1;
1975         while (i < NUM_UVD_DPM_LEVELS) {
1976                 result = vega10_populate_single_vclock_level(hwmgr,
1977                                 vclk_dpm_table->dpm_levels[j].value,
1978                                 &(pp_table->VclkDid[i]));
1979                 if (result)
1980                         return result;
1981                 i++;
1982         }
1983
1984         for (i = 0; i < dclk_dpm_table->count; i++) {
1985                 result = vega10_populate_single_dclock_level(hwmgr,
1986                                 dclk_dpm_table->dpm_levels[i].value,
1987                                 &(pp_table->DclkDid[i]));
1988                 if (result)
1989                         return result;
1990         }
1991
1992         j = i - 1;
1993         while (i < NUM_UVD_DPM_LEVELS) {
1994                 result = vega10_populate_single_dclock_level(hwmgr,
1995                                 dclk_dpm_table->dpm_levels[j].value,
1996                                 &(pp_table->DclkDid[i]));
1997                 if (result)
1998                         return result;
1999                 i++;
2000         }
2001
2002         for (i = 0; i < dep_table->count; i++) {
2003                 if (dep_table->entries[i].vclk ==
2004                                 vclk_dpm_table->dpm_levels[i].value &&
2005                         dep_table->entries[i].dclk ==
2006                                 dclk_dpm_table->dpm_levels[i].value)
2007                         pp_table->UvdDpmVoltageIndex[i] =
2008                                         dep_table->entries[i].vddcInd;
2009                 else
2010                         return -1;
2011         }
2012
2013         j = i - 1;
2014         while (i < NUM_UVD_DPM_LEVELS) {
2015                 pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd;
2016                 i++;
2017         }
2018
2019         return 0;
2020 }
2021
2022 static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr)
2023 {
2024         struct vega10_hwmgr *data =
2025                         (struct vega10_hwmgr *)(hwmgr->backend);
2026         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2027         struct phm_ppt_v2_information *table_info =
2028                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2029         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2030                         table_info->vdd_dep_on_sclk;
2031         uint32_t i;
2032
2033         for (i = 0; i < dep_table->count; i++) {
2034                 pp_table->CksEnable[i] = dep_table->entries[i].cks_enable;
2035                 pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset
2036                                 * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
2037         }
2038
2039         return 0;
2040 }
2041
2042 static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
2043 {
2044         struct vega10_hwmgr *data =
2045                         (struct vega10_hwmgr *)(hwmgr->backend);
2046         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2047         struct phm_ppt_v2_information *table_info =
2048                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2049         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2050                         table_info->vdd_dep_on_sclk;
2051         struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
2052         int result = 0;
2053         uint32_t i;
2054
2055         pp_table->MinVoltageVid = (uint8_t)0xff;
2056         pp_table->MaxVoltageVid = (uint8_t)0;
2057
2058         if (data->smu_features[GNLD_AVFS].supported) {
2059                 result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
2060                 if (!result) {
2061                         pp_table->MinVoltageVid = (uint8_t)
2062                                         convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
2063                         pp_table->MaxVoltageVid = (uint8_t)
2064                                         convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
2065
2066                         pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
2067                         pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
2068                         pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
2069                         pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2070                         pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
2071                         pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2072                         pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor);
2073
2074                         pp_table->BtcGbVdroopTableCksOff.a0 =
2075                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0);
2076                         pp_table->BtcGbVdroopTableCksOff.a0_shift = 20;
2077                         pp_table->BtcGbVdroopTableCksOff.a1 =
2078                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1);
2079                         pp_table->BtcGbVdroopTableCksOff.a1_shift = 20;
2080                         pp_table->BtcGbVdroopTableCksOff.a2 =
2081                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2);
2082                         pp_table->BtcGbVdroopTableCksOff.a2_shift = 20;
2083
2084                         pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson;
2085                         pp_table->BtcGbVdroopTableCksOn.a0 =
2086                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
2087                         pp_table->BtcGbVdroopTableCksOn.a0_shift = 20;
2088                         pp_table->BtcGbVdroopTableCksOn.a1 =
2089                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
2090                         pp_table->BtcGbVdroopTableCksOn.a1_shift = 20;
2091                         pp_table->BtcGbVdroopTableCksOn.a2 =
2092                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
2093                         pp_table->BtcGbVdroopTableCksOn.a2_shift = 20;
2094
2095                         pp_table->AvfsGbCksOn.m1 =
2096                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM1);
2097                         pp_table->AvfsGbCksOn.m2 =
2098                                         cpu_to_le16(avfs_params.ulGbFuseTableCksonM2);
2099                         pp_table->AvfsGbCksOn.b =
2100                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonB);
2101                         pp_table->AvfsGbCksOn.m1_shift = 24;
2102                         pp_table->AvfsGbCksOn.m2_shift = 12;
2103                         pp_table->AvfsGbCksOn.b_shift = 0;
2104
2105                         pp_table->OverrideAvfsGbCksOn =
2106                                         avfs_params.ucEnableGbFuseTableCkson;
2107                         pp_table->AvfsGbCksOff.m1 =
2108                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1);
2109                         pp_table->AvfsGbCksOff.m2 =
2110                                         cpu_to_le16(avfs_params.ulGbFuseTableCksoffM2);
2111                         pp_table->AvfsGbCksOff.b =
2112                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffB);
2113                         pp_table->AvfsGbCksOff.m1_shift = 24;
2114                         pp_table->AvfsGbCksOff.m2_shift = 12;
2115                         pp_table->AvfsGbCksOff.b_shift = 0;
2116
2117                         for (i = 0; i < dep_table->count; i++) {
2118                                 if (dep_table->entries[i].sclk_offset == 0)
2119                                         pp_table->StaticVoltageOffsetVid[i] = 248;
2120                                 else
2121                                         pp_table->StaticVoltageOffsetVid[i] =
2122                                                 (uint8_t)(dep_table->entries[i].sclk_offset *
2123                                                                 VOLTAGE_VID_OFFSET_SCALE2 /
2124                                                                 VOLTAGE_VID_OFFSET_SCALE1);
2125                         }
2126
2127                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2128                                         data->disp_clk_quad_eqn_a) &&
2129                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2130                                         data->disp_clk_quad_eqn_b)) {
2131                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2132                                                 (int32_t)data->disp_clk_quad_eqn_a;
2133                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2134                                                 (int32_t)data->disp_clk_quad_eqn_b;
2135                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2136                                                 (int32_t)data->disp_clk_quad_eqn_c;
2137                         } else {
2138                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2139                                                 (int32_t)avfs_params.ulDispclk2GfxclkM1;
2140                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2141                                                 (int32_t)avfs_params.ulDispclk2GfxclkM2;
2142                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2143                                                 (int32_t)avfs_params.ulDispclk2GfxclkB;
2144                         }
2145
2146                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24;
2147                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12;
2148                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12;
2149
2150                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2151                                         data->dcef_clk_quad_eqn_a) &&
2152                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2153                                         data->dcef_clk_quad_eqn_b)) {
2154                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2155                                                 (int32_t)data->dcef_clk_quad_eqn_a;
2156                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2157                                                 (int32_t)data->dcef_clk_quad_eqn_b;
2158                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2159                                                 (int32_t)data->dcef_clk_quad_eqn_c;
2160                         } else {
2161                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2162                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM1;
2163                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2164                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM2;
2165                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2166                                                 (int32_t)avfs_params.ulDcefclk2GfxclkB;
2167                         }
2168
2169                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24;
2170                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12;
2171                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12;
2172
2173                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2174                                         data->pixel_clk_quad_eqn_a) &&
2175                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2176                                         data->pixel_clk_quad_eqn_b)) {
2177                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2178                                                 (int32_t)data->pixel_clk_quad_eqn_a;
2179                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2180                                                 (int32_t)data->pixel_clk_quad_eqn_b;
2181                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2182                                                 (int32_t)data->pixel_clk_quad_eqn_c;
2183                         } else {
2184                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2185                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM1;
2186                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2187                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM2;
2188                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2189                                                 (int32_t)avfs_params.ulPixelclk2GfxclkB;
2190                         }
2191
2192                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24;
2193                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12;
2194                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12;
2195                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2196                                         data->phy_clk_quad_eqn_a) &&
2197                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2198                                         data->phy_clk_quad_eqn_b)) {
2199                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2200                                                 (int32_t)data->phy_clk_quad_eqn_a;
2201                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2202                                                 (int32_t)data->phy_clk_quad_eqn_b;
2203                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2204                                                 (int32_t)data->phy_clk_quad_eqn_c;
2205                         } else {
2206                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2207                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM1;
2208                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2209                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM2;
2210                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2211                                                 (int32_t)avfs_params.ulPhyclk2GfxclkB;
2212                         }
2213
2214                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24;
2215                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12;
2216                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12;
2217                 } else {
2218                         data->smu_features[GNLD_AVFS].supported = false;
2219                 }
2220         }
2221
2222         return 0;
2223 }
2224
2225 static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr)
2226 {
2227         struct vega10_hwmgr *data =
2228                         (struct vega10_hwmgr *)(hwmgr->backend);
2229         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2230         struct pp_atomfwctrl_gpio_parameters gpio_params = {0};
2231         int result;
2232
2233         result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params);
2234         if (!result) {
2235                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2236                                 PHM_PlatformCaps_RegulatorHot) &&
2237                                 (data->registry_data.regulator_hot_gpio_support)) {
2238                         pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio;
2239                         pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity;
2240                         pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio;
2241                         pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity;
2242                 } else {
2243                         pp_table->VR0HotGpio = 0;
2244                         pp_table->VR0HotPolarity = 0;
2245                         pp_table->VR1HotGpio = 0;
2246                         pp_table->VR1HotPolarity = 0;
2247                 }
2248
2249                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2250                                 PHM_PlatformCaps_AutomaticDCTransition) &&
2251                                 (data->registry_data.ac_dc_switch_gpio_support)) {
2252                         pp_table->AcDcGpio = gpio_params.ucAcDcGpio;
2253                         pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity;
2254                 } else {
2255                         pp_table->AcDcGpio = 0;
2256                         pp_table->AcDcPolarity = 0;
2257                 }
2258         }
2259
2260         return result;
2261 }
2262
2263 static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable)
2264 {
2265         struct vega10_hwmgr *data =
2266                         (struct vega10_hwmgr *)(hwmgr->backend);
2267
2268         if (data->smu_features[GNLD_AVFS].supported) {
2269                 if (enable) {
2270                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2271                                         true,
2272                                         data->smu_features[GNLD_AVFS].smu_feature_bitmap),
2273                                         "[avfs_control] Attempt to Enable AVFS feature Failed!",
2274                                         return -1);
2275                         data->smu_features[GNLD_AVFS].enabled = true;
2276                 } else {
2277                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2278                                         false,
2279                                         data->smu_features[GNLD_AVFS].smu_feature_id),
2280                                         "[avfs_control] Attempt to Disable AVFS feature Failed!",
2281                                         return -1);
2282                         data->smu_features[GNLD_AVFS].enabled = false;
2283                 }
2284         }
2285
2286         return 0;
2287 }
2288
2289 static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
2290 {
2291         int result = 0;
2292
2293         uint64_t serial_number = 0;
2294         uint32_t top32, bottom32;
2295         struct phm_fuses_default fuse;
2296
2297         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2298         AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table);
2299
2300         smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ReadSerialNumTop32);
2301         vega10_read_arg_from_smc(hwmgr->smumgr, &top32);
2302
2303         smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ReadSerialNumBottom32);
2304         vega10_read_arg_from_smc(hwmgr->smumgr, &bottom32);
2305
2306         serial_number = ((uint64_t)bottom32 << 32) | top32;
2307
2308         if (pp_override_get_default_fuse_value(serial_number, vega10_fuses_default, &fuse) == 0) {
2309                 avfs_fuse_table->VFT0_b  = fuse.VFT0_b;
2310                 avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1;
2311                 avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2;
2312                 avfs_fuse_table->VFT1_b  = fuse.VFT1_b;
2313                 avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1;
2314                 avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2;
2315                 avfs_fuse_table->VFT2_b  = fuse.VFT2_b;
2316                 avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1;
2317                 avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2;
2318                 result = vega10_copy_table_to_smc(hwmgr->smumgr,
2319                         (uint8_t *)avfs_fuse_table, AVFSFUSETABLE);
2320                 PP_ASSERT_WITH_CODE(!result,
2321                         "Failed to upload FuseOVerride!",
2322                         );
2323         }
2324
2325         return result;
2326 }
2327
2328 static int vega10_save_default_power_profile(struct pp_hwmgr *hwmgr)
2329 {
2330         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2331         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2332         uint32_t min_level;
2333
2334         hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
2335         hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
2336
2337         /* Optimize compute power profile: Use only highest
2338          * 2 power levels (if more than 2 are available)
2339          */
2340         if (dpm_table->count > 2)
2341                 min_level = dpm_table->count - 2;
2342         else if (dpm_table->count == 2)
2343                 min_level = 1;
2344         else
2345                 min_level = 0;
2346
2347         hwmgr->default_compute_power_profile.min_sclk =
2348                         dpm_table->dpm_levels[min_level].value;
2349
2350         hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
2351         hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
2352
2353         return 0;
2354 }
2355
2356 /**
2357 * Initializes the SMC table and uploads it
2358 *
2359 * @param    hwmgr  the address of the powerplay hardware manager.
2360 * @param    pInput  the pointer to input data (PowerState)
2361 * @return   always 0
2362 */
2363 static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
2364 {
2365         int result;
2366         struct vega10_hwmgr *data =
2367                         (struct vega10_hwmgr *)(hwmgr->backend);
2368         struct phm_ppt_v2_information *table_info =
2369                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2370         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2371         struct pp_atomfwctrl_voltage_table voltage_table;
2372         struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
2373
2374         result = vega10_setup_default_dpm_tables(hwmgr);
2375         PP_ASSERT_WITH_CODE(!result,
2376                         "Failed to setup default DPM tables!",
2377                         return result);
2378
2379         pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC,
2380                         VOLTAGE_OBJ_SVID2,  &voltage_table);
2381         pp_table->MaxVidStep = voltage_table.max_vid_step;
2382
2383         pp_table->GfxDpmVoltageMode =
2384                         (uint8_t)(table_info->uc_gfx_dpm_voltage_mode);
2385         pp_table->SocDpmVoltageMode =
2386                         (uint8_t)(table_info->uc_soc_dpm_voltage_mode);
2387         pp_table->UclkDpmVoltageMode =
2388                         (uint8_t)(table_info->uc_uclk_dpm_voltage_mode);
2389         pp_table->UvdDpmVoltageMode =
2390                         (uint8_t)(table_info->uc_uvd_dpm_voltage_mode);
2391         pp_table->VceDpmVoltageMode =
2392                         (uint8_t)(table_info->uc_vce_dpm_voltage_mode);
2393         pp_table->Mp0DpmVoltageMode =
2394                         (uint8_t)(table_info->uc_mp0_dpm_voltage_mode);
2395
2396         pp_table->DisplayDpmVoltageMode =
2397                         (uint8_t)(table_info->uc_dcef_dpm_voltage_mode);
2398
2399         if (data->registry_data.ulv_support &&
2400                         table_info->us_ulv_voltage_offset) {
2401                 result = vega10_populate_ulv_state(hwmgr);
2402                 PP_ASSERT_WITH_CODE(!result,
2403                                 "Failed to initialize ULV state!",
2404                                 return result);
2405         }
2406
2407         result = vega10_populate_smc_link_levels(hwmgr);
2408         PP_ASSERT_WITH_CODE(!result,
2409                         "Failed to initialize Link Level!",
2410                         return result);
2411
2412         result = vega10_populate_all_graphic_levels(hwmgr);
2413         PP_ASSERT_WITH_CODE(!result,
2414                         "Failed to initialize Graphics Level!",
2415                         return result);
2416
2417         result = vega10_populate_all_memory_levels(hwmgr);
2418         PP_ASSERT_WITH_CODE(!result,
2419                         "Failed to initialize Memory Level!",
2420                         return result);
2421
2422         result = vega10_populate_all_display_clock_levels(hwmgr);
2423         PP_ASSERT_WITH_CODE(!result,
2424                         "Failed to initialize Display Level!",
2425                         return result);
2426
2427         result = vega10_populate_smc_vce_levels(hwmgr);
2428         PP_ASSERT_WITH_CODE(!result,
2429                         "Failed to initialize VCE Level!",
2430                         return result);
2431
2432         result = vega10_populate_smc_uvd_levels(hwmgr);
2433         PP_ASSERT_WITH_CODE(!result,
2434                         "Failed to initialize UVD Level!",
2435                         return result);
2436
2437         if (data->registry_data.clock_stretcher_support) {
2438                 result = vega10_populate_clock_stretcher_table(hwmgr);
2439                 PP_ASSERT_WITH_CODE(!result,
2440                                 "Failed to populate Clock Stretcher Table!",
2441                                 return result);
2442         }
2443
2444         result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
2445         if (!result) {
2446                 data->vbios_boot_state.vddc     = boot_up_values.usVddc;
2447                 data->vbios_boot_state.vddci    = boot_up_values.usVddci;
2448                 data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
2449                 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
2450                 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
2451                 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
2452                 if (0 != boot_up_values.usVddc) {
2453                         smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2454                                                 PPSMC_MSG_SetFloorSocVoltage,
2455                                                 (boot_up_values.usVddc * 4));
2456                         data->vbios_boot_state.bsoc_vddc_lock = true;
2457                 } else {
2458                         data->vbios_boot_state.bsoc_vddc_lock = false;
2459                 }
2460         }
2461
2462         result = vega10_populate_avfs_parameters(hwmgr);
2463         PP_ASSERT_WITH_CODE(!result,
2464                         "Failed to initialize AVFS Parameters!",
2465                         return result);
2466
2467         result = vega10_populate_gpio_parameters(hwmgr);
2468         PP_ASSERT_WITH_CODE(!result,
2469                         "Failed to initialize GPIO Parameters!",
2470                         return result);
2471
2472         pp_table->GfxclkAverageAlpha = (uint8_t)
2473                         (data->gfxclk_average_alpha);
2474         pp_table->SocclkAverageAlpha = (uint8_t)
2475                         (data->socclk_average_alpha);
2476         pp_table->UclkAverageAlpha = (uint8_t)
2477                         (data->uclk_average_alpha);
2478         pp_table->GfxActivityAverageAlpha = (uint8_t)
2479                         (data->gfx_activity_average_alpha);
2480
2481         vega10_populate_and_upload_avfs_fuse_override(hwmgr);
2482
2483         result = vega10_copy_table_to_smc(hwmgr->smumgr,
2484                         (uint8_t *)pp_table, PPTABLE);
2485         PP_ASSERT_WITH_CODE(!result,
2486                         "Failed to upload PPtable!", return result);
2487
2488         result = vega10_avfs_enable(hwmgr, true);
2489         PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
2490                                         return result);
2491
2492         vega10_save_default_power_profile(hwmgr);
2493
2494         return 0;
2495 }
2496
2497 static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
2498 {
2499         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2500
2501         if (data->smu_features[GNLD_THERMAL].supported) {
2502                 if (data->smu_features[GNLD_THERMAL].enabled)
2503                         pr_info("THERMAL Feature Already enabled!");
2504
2505                 PP_ASSERT_WITH_CODE(
2506                                 !vega10_enable_smc_features(hwmgr->smumgr,
2507                                 true,
2508                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2509                                 "Enable THERMAL Feature Failed!",
2510                                 return -1);
2511                 data->smu_features[GNLD_THERMAL].enabled = true;
2512         }
2513
2514         return 0;
2515 }
2516
2517 static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr)
2518 {
2519         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2520
2521         if (data->smu_features[GNLD_THERMAL].supported) {
2522                 if (!data->smu_features[GNLD_THERMAL].enabled)
2523                         pr_info("THERMAL Feature Already disabled!");
2524
2525                 PP_ASSERT_WITH_CODE(
2526                                 !vega10_enable_smc_features(hwmgr->smumgr,
2527                                 false,
2528                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2529                                 "disable THERMAL Feature Failed!",
2530                                 return -1);
2531                 data->smu_features[GNLD_THERMAL].enabled = false;
2532         }
2533
2534         return 0;
2535 }
2536
2537 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
2538 {
2539         struct vega10_hwmgr *data =
2540                         (struct vega10_hwmgr *)(hwmgr->backend);
2541
2542         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2543                         PHM_PlatformCaps_RegulatorHot)) {
2544                 if (data->smu_features[GNLD_VR0HOT].supported) {
2545                         PP_ASSERT_WITH_CODE(
2546                                         !vega10_enable_smc_features(hwmgr->smumgr,
2547                                         true,
2548                                         data->smu_features[GNLD_VR0HOT].smu_feature_bitmap),
2549                                         "Attempt to Enable VR0 Hot feature Failed!",
2550                                         return -1);
2551                         data->smu_features[GNLD_VR0HOT].enabled = true;
2552                 } else {
2553                         if (data->smu_features[GNLD_VR1HOT].supported) {
2554                                 PP_ASSERT_WITH_CODE(
2555                                                 !vega10_enable_smc_features(hwmgr->smumgr,
2556                                                 true,
2557                                                 data->smu_features[GNLD_VR1HOT].smu_feature_bitmap),
2558                                                 "Attempt to Enable VR0 Hot feature Failed!",
2559                                                 return -1);
2560                                 data->smu_features[GNLD_VR1HOT].enabled = true;
2561                         }
2562                 }
2563         }
2564         return 0;
2565 }
2566
2567 static int vega10_enable_ulv(struct pp_hwmgr *hwmgr)
2568 {
2569         struct vega10_hwmgr *data =
2570                         (struct vega10_hwmgr *)(hwmgr->backend);
2571
2572         if (data->registry_data.ulv_support) {
2573                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2574                                 true, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2575                                 "Enable ULV Feature Failed!",
2576                                 return -1);
2577                 data->smu_features[GNLD_ULV].enabled = true;
2578         }
2579
2580         return 0;
2581 }
2582
2583 static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2584 {
2585         struct vega10_hwmgr *data =
2586                         (struct vega10_hwmgr *)(hwmgr->backend);
2587
2588         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2589                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2590                                 true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2591                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2592                                 return -1);
2593                 data->smu_features[GNLD_DS_GFXCLK].enabled = true;
2594         }
2595
2596         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2597                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2598                                 true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2599                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2600                                 return -1);
2601                 data->smu_features[GNLD_DS_SOCCLK].enabled = true;
2602         }
2603
2604         if (data->smu_features[GNLD_DS_LCLK].supported) {
2605                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2606                                 true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2607                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2608                                 return -1);
2609                 data->smu_features[GNLD_DS_LCLK].enabled = true;
2610         }
2611
2612         return 0;
2613 }
2614
2615 static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2616 {
2617         struct vega10_hwmgr *data =
2618                         (struct vega10_hwmgr *)(hwmgr->backend);
2619         uint32_t i, feature_mask = 0;
2620
2621
2622         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2623                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2624                                 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2625                 "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
2626                 data->smu_features[GNLD_LED_DISPLAY].enabled = true;
2627         }
2628
2629         for (i = 0; i < GNLD_DPM_MAX; i++) {
2630                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2631                         if (data->smu_features[i].supported) {
2632                                 if (data->smu_features[i].enabled) {
2633                                         feature_mask |= data->smu_features[i].
2634                                                         smu_feature_bitmap;
2635                                         data->smu_features[i].enabled = false;
2636                                 }
2637                         }
2638                 }
2639         }
2640
2641         vega10_enable_smc_features(hwmgr->smumgr, false, feature_mask);
2642
2643         return 0;
2644 }
2645
2646 /**
2647  * @brief Tell SMC to enabled the supported DPMs.
2648  *
2649  * @param    hwmgr - the address of the powerplay hardware manager.
2650  * @Param    bitmap - bitmap for the features to enabled.
2651  * @return   0 on at least one DPM is successfully enabled.
2652  */
2653 static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2654 {
2655         struct vega10_hwmgr *data =
2656                         (struct vega10_hwmgr *)(hwmgr->backend);
2657         uint32_t i, feature_mask = 0;
2658
2659         for (i = 0; i < GNLD_DPM_MAX; i++) {
2660                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2661                         if (data->smu_features[i].supported) {
2662                                 if (!data->smu_features[i].enabled) {
2663                                         feature_mask |= data->smu_features[i].
2664                                                         smu_feature_bitmap;
2665                                         data->smu_features[i].enabled = true;
2666                                 }
2667                         }
2668                 }
2669         }
2670
2671         if (vega10_enable_smc_features(hwmgr->smumgr,
2672                         true, feature_mask)) {
2673                 for (i = 0; i < GNLD_DPM_MAX; i++) {
2674                         if (data->smu_features[i].smu_feature_bitmap &
2675                                         feature_mask)
2676                                 data->smu_features[i].enabled = false;
2677                 }
2678         }
2679
2680         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2681                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2682                                 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2683                 "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
2684                 data->smu_features[GNLD_LED_DISPLAY].enabled = true;
2685         }
2686
2687         if (data->vbios_boot_state.bsoc_vddc_lock) {
2688                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2689                                                 PPSMC_MSG_SetFloorSocVoltage, 0);
2690                 data->vbios_boot_state.bsoc_vddc_lock = false;
2691         }
2692
2693         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2694                         PHM_PlatformCaps_Falcon_QuickTransition)) {
2695                 if (data->smu_features[GNLD_ACDC].supported) {
2696                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2697                                         true, data->smu_features[GNLD_ACDC].smu_feature_bitmap),
2698                                         "Attempt to Enable DS_GFXCLK Feature Failed!",
2699                                         return -1);
2700                         data->smu_features[GNLD_ACDC].enabled = true;
2701                 }
2702         }
2703
2704         return 0;
2705 }
2706
2707 static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
2708 {
2709         struct vega10_hwmgr *data =
2710                         (struct vega10_hwmgr *)(hwmgr->backend);
2711         int tmp_result, result = 0;
2712
2713         tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2714                         PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
2715         PP_ASSERT_WITH_CODE(!tmp_result,
2716                         "Failed to configure telemetry!",
2717                         return tmp_result);
2718
2719         smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2720                         PPSMC_MSG_NumOfDisplays, 0);
2721
2722         tmp_result = (!vega10_is_dpm_running(hwmgr)) ? 0 : -1;
2723         PP_ASSERT_WITH_CODE(!tmp_result,
2724                         "DPM is already running right , skipping re-enablement!",
2725                         return 0);
2726
2727         tmp_result = vega10_construct_voltage_tables(hwmgr);
2728         PP_ASSERT_WITH_CODE(!tmp_result,
2729                         "Failed to contruct voltage tables!",
2730                         result = tmp_result);
2731
2732         tmp_result = vega10_init_smc_table(hwmgr);
2733         PP_ASSERT_WITH_CODE(!tmp_result,
2734                         "Failed to initialize SMC table!",
2735                         result = tmp_result);
2736
2737         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2738                         PHM_PlatformCaps_ThermalController)) {
2739                 tmp_result = vega10_enable_thermal_protection(hwmgr);
2740                 PP_ASSERT_WITH_CODE(!tmp_result,
2741                                 "Failed to enable thermal protection!",
2742                                 result = tmp_result);
2743         }
2744
2745         tmp_result = vega10_enable_vrhot_feature(hwmgr);
2746         PP_ASSERT_WITH_CODE(!tmp_result,
2747                         "Failed to enable VR hot feature!",
2748                         result = tmp_result);
2749
2750         tmp_result = vega10_enable_ulv(hwmgr);
2751         PP_ASSERT_WITH_CODE(!tmp_result,
2752                         "Failed to enable ULV!",
2753                         result = tmp_result);
2754
2755         tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr);
2756         PP_ASSERT_WITH_CODE(!tmp_result,
2757                         "Failed to enable deep sleep master switch!",
2758                         result = tmp_result);
2759
2760         tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES);
2761         PP_ASSERT_WITH_CODE(!tmp_result,
2762                         "Failed to start DPM!", result = tmp_result);
2763
2764         tmp_result = vega10_enable_power_containment(hwmgr);
2765         PP_ASSERT_WITH_CODE(!tmp_result,
2766                         "Failed to enable power containment!",
2767                         result = tmp_result);
2768
2769         tmp_result = vega10_power_control_set_level(hwmgr);
2770         PP_ASSERT_WITH_CODE(!tmp_result,
2771                         "Failed to power control set level!",
2772                         result = tmp_result);
2773
2774         return result;
2775 }
2776
2777 static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr)
2778 {
2779         return sizeof(struct vega10_power_state);
2780 }
2781
2782 static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
2783                 void *state, struct pp_power_state *power_state,
2784                 void *pp_table, uint32_t classification_flag)
2785 {
2786         struct vega10_power_state *vega10_power_state =
2787                         cast_phw_vega10_power_state(&(power_state->hardware));
2788         struct vega10_performance_level *performance_level;
2789         ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state;
2790         ATOM_Vega10_POWERPLAYTABLE *powerplay_table =
2791                         (ATOM_Vega10_POWERPLAYTABLE *)pp_table;
2792         ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table =
2793                         (ATOM_Vega10_SOCCLK_Dependency_Table *)
2794                         (((unsigned long)powerplay_table) +
2795                         le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset));
2796         ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
2797                         (ATOM_Vega10_GFXCLK_Dependency_Table *)
2798                         (((unsigned long)powerplay_table) +
2799                         le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
2800         ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table =
2801                         (ATOM_Vega10_MCLK_Dependency_Table *)
2802                         (((unsigned long)powerplay_table) +
2803                         le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
2804
2805
2806         /* The following fields are not initialized here:
2807          * id orderedList allStatesList
2808          */
2809         power_state->classification.ui_label =
2810                         (le16_to_cpu(state_entry->usClassification) &
2811                         ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
2812                         ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
2813         power_state->classification.flags = classification_flag;
2814         /* NOTE: There is a classification2 flag in BIOS
2815          * that is not being used right now
2816          */
2817         power_state->classification.temporary_state = false;
2818         power_state->classification.to_be_deleted = false;
2819
2820         power_state->validation.disallowOnDC =
2821                         ((le32_to_cpu(state_entry->ulCapsAndSettings) &
2822                                         ATOM_Vega10_DISALLOW_ON_DC) != 0);
2823
2824         power_state->display.disableFrameModulation = false;
2825         power_state->display.limitRefreshrate = false;
2826         power_state->display.enableVariBright =
2827                         ((le32_to_cpu(state_entry->ulCapsAndSettings) &
2828                                         ATOM_Vega10_ENABLE_VARIBRIGHT) != 0);
2829
2830         power_state->validation.supportedPowerLevels = 0;
2831         power_state->uvd_clocks.VCLK = 0;
2832         power_state->uvd_clocks.DCLK = 0;
2833         power_state->temperatures.min = 0;
2834         power_state->temperatures.max = 0;
2835
2836         performance_level = &(vega10_power_state->performance_levels
2837                         [vega10_power_state->performance_level_count++]);
2838
2839         PP_ASSERT_WITH_CODE(
2840                         (vega10_power_state->performance_level_count <
2841                                         NUM_GFXCLK_DPM_LEVELS),
2842                         "Performance levels exceeds SMC limit!",
2843                         return -1);
2844
2845         PP_ASSERT_WITH_CODE(
2846                         (vega10_power_state->performance_level_count <=
2847                                         hwmgr->platform_descriptor.
2848                                         hardwareActivityPerformanceLevels),
2849                         "Performance levels exceeds Driver limit!",
2850                         return -1);
2851
2852         /* Performance levels are arranged from low to high. */
2853         performance_level->soc_clock = socclk_dep_table->entries
2854                         [state_entry->ucSocClockIndexLow].ulClk;
2855         performance_level->gfx_clock = gfxclk_dep_table->entries
2856                         [state_entry->ucGfxClockIndexLow].ulClk;
2857         performance_level->mem_clock = mclk_dep_table->entries
2858                         [state_entry->ucMemClockIndexLow].ulMemClk;
2859
2860         performance_level = &(vega10_power_state->performance_levels
2861                                 [vega10_power_state->performance_level_count++]);
2862
2863         performance_level->soc_clock = socclk_dep_table->entries
2864                         [state_entry->ucSocClockIndexHigh].ulClk;
2865         performance_level->gfx_clock = gfxclk_dep_table->entries
2866                         [state_entry->ucGfxClockIndexHigh].ulClk;
2867         performance_level->mem_clock = mclk_dep_table->entries
2868                         [state_entry->ucMemClockIndexHigh].ulMemClk;
2869         return 0;
2870 }
2871
2872 static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr,
2873                 unsigned long entry_index, struct pp_power_state *state)
2874 {
2875         int result;
2876         struct vega10_power_state *ps;
2877
2878         state->hardware.magic = PhwVega10_Magic;
2879
2880         ps = cast_phw_vega10_power_state(&state->hardware);
2881
2882         result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state,
2883                         vega10_get_pp_table_entry_callback_func);
2884
2885         /*
2886          * This is the earliest time we have all the dependency table
2887          * and the VBIOS boot state
2888          */
2889         /* set DC compatible flag if this state supports DC */
2890         if (!state->validation.disallowOnDC)
2891                 ps->dc_compatible = true;
2892
2893         ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
2894         ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
2895
2896         return 0;
2897 }
2898
2899 static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr,
2900              struct pp_hw_power_state *hw_ps)
2901 {
2902         return 0;
2903 }
2904
2905 static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
2906                                 struct pp_power_state  *request_ps,
2907                         const struct pp_power_state *current_ps)
2908 {
2909         struct vega10_power_state *vega10_ps =
2910                                 cast_phw_vega10_power_state(&request_ps->hardware);
2911         uint32_t sclk;
2912         uint32_t mclk;
2913         struct PP_Clocks minimum_clocks = {0};
2914         bool disable_mclk_switching;
2915         bool disable_mclk_switching_for_frame_lock;
2916         bool disable_mclk_switching_for_vr;
2917         bool force_mclk_high;
2918         struct cgs_display_info info = {0};
2919         const struct phm_clock_and_voltage_limits *max_limits;
2920         uint32_t i;
2921         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2922         struct phm_ppt_v2_information *table_info =
2923                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2924         int32_t count;
2925         uint32_t stable_pstate_sclk_dpm_percentage;
2926         uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
2927         uint32_t latency;
2928
2929         data->battery_state = (PP_StateUILabel_Battery ==
2930                         request_ps->classification.ui_label);
2931
2932         if (vega10_ps->performance_level_count != 2)
2933                 pr_info("VI should always have 2 performance levels");
2934
2935         max_limits = (PP_PowerSource_AC == hwmgr->power_source) ?
2936                         &(hwmgr->dyn_state.max_clock_voltage_on_ac) :
2937                         &(hwmgr->dyn_state.max_clock_voltage_on_dc);
2938
2939         /* Cap clock DPM tables at DC MAX if it is in DC. */
2940         if (PP_PowerSource_DC == hwmgr->power_source) {
2941                 for (i = 0; i < vega10_ps->performance_level_count; i++) {
2942                         if (vega10_ps->performance_levels[i].mem_clock >
2943                                 max_limits->mclk)
2944                                 vega10_ps->performance_levels[i].mem_clock =
2945                                                 max_limits->mclk;
2946                         if (vega10_ps->performance_levels[i].gfx_clock >
2947                                 max_limits->sclk)
2948                                 vega10_ps->performance_levels[i].gfx_clock =
2949                                                 max_limits->sclk;
2950                 }
2951         }
2952
2953         vega10_ps->vce_clks.evclk = hwmgr->vce_arbiter.evclk;
2954         vega10_ps->vce_clks.ecclk = hwmgr->vce_arbiter.ecclk;
2955
2956         cgs_get_active_displays_info(hwmgr->device, &info);
2957
2958         /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
2959         minimum_clocks.engineClock = hwmgr->display_config.min_core_set_clock;
2960         /* minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock; */
2961
2962         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2963                         PHM_PlatformCaps_StablePState)) {
2964                 PP_ASSERT_WITH_CODE(
2965                         data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 &&
2966                         data->registry_data.stable_pstate_sclk_dpm_percentage <= 100,
2967                         "percent sclk value must range from 1% to 100%, setting default value",
2968                         stable_pstate_sclk_dpm_percentage = 75);
2969
2970                 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
2971                 stable_pstate_sclk = (max_limits->sclk *
2972                                 stable_pstate_sclk_dpm_percentage) / 100;
2973
2974                 for (count = table_info->vdd_dep_on_sclk->count - 1;
2975                                 count >= 0; count--) {
2976                         if (stable_pstate_sclk >=
2977                                         table_info->vdd_dep_on_sclk->entries[count].clk) {
2978                                 stable_pstate_sclk =
2979                                                 table_info->vdd_dep_on_sclk->entries[count].clk;
2980                                 break;
2981                         }
2982                 }
2983
2984                 if (count < 0)
2985                         stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
2986
2987                 stable_pstate_mclk = max_limits->mclk;
2988
2989                 minimum_clocks.engineClock = stable_pstate_sclk;
2990                 minimum_clocks.memoryClock = stable_pstate_mclk;
2991         }
2992
2993         if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk)
2994                 minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk;
2995
2996         if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
2997                 minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
2998
2999         vega10_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold;
3000
3001         if (hwmgr->gfx_arbiter.sclk_over_drive) {
3002                 PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <=
3003                                 hwmgr->platform_descriptor.overdriveLimit.engineClock),
3004                                 "Overdrive sclk exceeds limit",
3005                                 hwmgr->gfx_arbiter.sclk_over_drive =
3006                                                 hwmgr->platform_descriptor.overdriveLimit.engineClock);
3007
3008                 if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk)
3009                         vega10_ps->performance_levels[1].gfx_clock =
3010                                         hwmgr->gfx_arbiter.sclk_over_drive;
3011         }
3012
3013         if (hwmgr->gfx_arbiter.mclk_over_drive) {
3014                 PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <=
3015                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock),
3016                                 "Overdrive mclk exceeds limit",
3017                                 hwmgr->gfx_arbiter.mclk_over_drive =
3018                                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock);
3019
3020                 if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk)
3021                         vega10_ps->performance_levels[1].mem_clock =
3022                                         hwmgr->gfx_arbiter.mclk_over_drive;
3023         }
3024
3025         disable_mclk_switching_for_frame_lock = phm_cap_enabled(
3026                                     hwmgr->platform_descriptor.platformCaps,
3027                                     PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
3028         disable_mclk_switching_for_vr = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3029                         PHM_PlatformCaps_DisableMclkSwitchForVR);
3030         force_mclk_high = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3031                         PHM_PlatformCaps_ForceMclkHigh);
3032
3033         disable_mclk_switching = (info.display_count > 1) ||
3034                                     disable_mclk_switching_for_frame_lock ||
3035                                     disable_mclk_switching_for_vr ||
3036                                     force_mclk_high;
3037
3038         sclk = vega10_ps->performance_levels[0].gfx_clock;
3039         mclk = vega10_ps->performance_levels[0].mem_clock;
3040
3041         if (sclk < minimum_clocks.engineClock)
3042                 sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
3043                                 max_limits->sclk : minimum_clocks.engineClock;
3044
3045         if (mclk < minimum_clocks.memoryClock)
3046                 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
3047                                 max_limits->mclk : minimum_clocks.memoryClock;
3048
3049         vega10_ps->performance_levels[0].gfx_clock = sclk;
3050         vega10_ps->performance_levels[0].mem_clock = mclk;
3051
3052         vega10_ps->performance_levels[1].gfx_clock =
3053                 (vega10_ps->performance_levels[1].gfx_clock >=
3054                                 vega10_ps->performance_levels[0].gfx_clock) ?
3055                                                 vega10_ps->performance_levels[1].gfx_clock :
3056                                                 vega10_ps->performance_levels[0].gfx_clock;
3057
3058         if (disable_mclk_switching) {
3059                 /* Set Mclk the max of level 0 and level 1 */
3060                 if (mclk < vega10_ps->performance_levels[1].mem_clock)
3061                         mclk = vega10_ps->performance_levels[1].mem_clock;
3062
3063                 /* Find the lowest MCLK frequency that is within
3064                  * the tolerable latency defined in DAL
3065                  */
3066                 latency = 0;
3067                 for (i = 0; i < data->mclk_latency_table.count; i++) {
3068                         if ((data->mclk_latency_table.entries[i].latency <= latency) &&
3069                                 (data->mclk_latency_table.entries[i].frequency >=
3070                                                 vega10_ps->performance_levels[0].mem_clock) &&
3071                                 (data->mclk_latency_table.entries[i].frequency <=
3072                                                 vega10_ps->performance_levels[1].mem_clock))
3073                                 mclk = data->mclk_latency_table.entries[i].frequency;
3074                 }
3075                 vega10_ps->performance_levels[0].mem_clock = mclk;
3076         } else {
3077                 if (vega10_ps->performance_levels[1].mem_clock <
3078                                 vega10_ps->performance_levels[0].mem_clock)
3079                         vega10_ps->performance_levels[1].mem_clock =
3080                                         vega10_ps->performance_levels[0].mem_clock;
3081         }
3082
3083         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3084                         PHM_PlatformCaps_StablePState)) {
3085                 for (i = 0; i < vega10_ps->performance_level_count; i++) {
3086                         vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk;
3087                         vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk;
3088                 }
3089         }
3090
3091         return 0;
3092 }
3093
3094 static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
3095 {
3096         const struct phm_set_power_state_input *states =
3097                         (const struct phm_set_power_state_input *)input;
3098         const struct vega10_power_state *vega10_ps =
3099                         cast_const_phw_vega10_power_state(states->pnew_state);
3100         struct vega10_hwmgr *data =
3101                         (struct vega10_hwmgr *)(hwmgr->backend);
3102         struct vega10_single_dpm_table *sclk_table =
3103                         &(data->dpm_table.gfx_table);
3104         uint32_t sclk = vega10_ps->performance_levels
3105                         [vega10_ps->performance_level_count - 1].gfx_clock;
3106         struct vega10_single_dpm_table *mclk_table =
3107                         &(data->dpm_table.mem_table);
3108         uint32_t mclk = vega10_ps->performance_levels
3109                         [vega10_ps->performance_level_count - 1].mem_clock;
3110         struct PP_Clocks min_clocks = {0};
3111         uint32_t i;
3112         struct cgs_display_info info = {0};
3113
3114         data->need_update_dpm_table = 0;
3115
3116         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3117                         PHM_PlatformCaps_ODNinACSupport) ||
3118                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3119                                 PHM_PlatformCaps_ODNinDCSupport)) {
3120                 for (i = 0; i < sclk_table->count; i++) {
3121                         if (sclk == sclk_table->dpm_levels[i].value)
3122                                 break;
3123                 }
3124
3125                 if (!(data->apply_overdrive_next_settings_mask &
3126                                 DPMTABLE_OD_UPDATE_SCLK) && i >= sclk_table->count) {
3127                         /* Check SCLK in DAL's minimum clocks
3128                          * in case DeepSleep divider update is required.
3129                          */
3130                         if (data->display_timing.min_clock_in_sr !=
3131                                         min_clocks.engineClockInSR &&
3132                                 (min_clocks.engineClockInSR >=
3133                                                 VEGA10_MINIMUM_ENGINE_CLOCK ||
3134                                         data->display_timing.min_clock_in_sr >=
3135                                                 VEGA10_MINIMUM_ENGINE_CLOCK))
3136                                 data->need_update_dpm_table |= DPMTABLE_UPDATE_SCLK;
3137                 }
3138
3139                 cgs_get_active_displays_info(hwmgr->device, &info);
3140
3141                 if (data->display_timing.num_existing_displays !=
3142                                 info.display_count)
3143                         data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
3144         } else {
3145                 for (i = 0; i < sclk_table->count; i++) {
3146                         if (sclk == sclk_table->dpm_levels[i].value)
3147                                 break;
3148                 }
3149
3150                 if (i >= sclk_table->count)
3151                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
3152                 else {
3153                         /* Check SCLK in DAL's minimum clocks
3154                          * in case DeepSleep divider update is required.
3155                          */
3156                         if (data->display_timing.min_clock_in_sr !=
3157                                         min_clocks.engineClockInSR &&
3158                                 (min_clocks.engineClockInSR >=
3159                                                 VEGA10_MINIMUM_ENGINE_CLOCK ||
3160                                         data->display_timing.min_clock_in_sr >=
3161                                                 VEGA10_MINIMUM_ENGINE_CLOCK))
3162                                 data->need_update_dpm_table |= DPMTABLE_UPDATE_SCLK;
3163                 }
3164
3165                 for (i = 0; i < mclk_table->count; i++) {
3166                         if (mclk == mclk_table->dpm_levels[i].value)
3167                                 break;
3168                 }
3169
3170                 cgs_get_active_displays_info(hwmgr->device, &info);
3171
3172                 if (i >= mclk_table->count)
3173                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
3174
3175                 if (data->display_timing.num_existing_displays !=
3176                                 info.display_count ||
3177                                 i >= mclk_table->count)
3178                         data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
3179         }
3180         return 0;
3181 }
3182
3183 static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
3184                 struct pp_hwmgr *hwmgr, const void *input)
3185 {
3186         int result = 0;
3187         const struct phm_set_power_state_input *states =
3188                         (const struct phm_set_power_state_input *)input;
3189         const struct vega10_power_state *vega10_ps =
3190                         cast_const_phw_vega10_power_state(states->pnew_state);
3191         struct vega10_hwmgr *data =
3192                         (struct vega10_hwmgr *)(hwmgr->backend);
3193         uint32_t sclk = vega10_ps->performance_levels
3194                         [vega10_ps->performance_level_count - 1].gfx_clock;
3195         uint32_t mclk = vega10_ps->performance_levels
3196                         [vega10_ps->performance_level_count - 1].mem_clock;
3197         struct vega10_dpm_table *dpm_table = &data->dpm_table;
3198         struct vega10_dpm_table *golden_dpm_table =
3199                         &data->golden_dpm_table;
3200         uint32_t dpm_count, clock_percent;
3201         uint32_t i;
3202
3203         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3204                         PHM_PlatformCaps_ODNinACSupport) ||
3205                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3206                         PHM_PlatformCaps_ODNinDCSupport)) {
3207
3208                 if (!data->need_update_dpm_table &&
3209                         !data->apply_optimized_settings &&
3210                         !data->apply_overdrive_next_settings_mask)
3211                         return 0;
3212
3213                 if (data->apply_overdrive_next_settings_mask &
3214                                 DPMTABLE_OD_UPDATE_SCLK) {
3215                         for (dpm_count = 0;
3216                                         dpm_count < dpm_table->gfx_table.count;
3217                                         dpm_count++) {
3218                                 dpm_table->gfx_table.dpm_levels[dpm_count].enabled =
3219                                                 data->odn_dpm_table.odn_core_clock_dpm_levels.
3220                                                 performance_level_entries[dpm_count].enabled;
3221                                 dpm_table->gfx_table.dpm_levels[dpm_count].value =
3222                                                 data->odn_dpm_table.odn_core_clock_dpm_levels.
3223                                                 performance_level_entries[dpm_count].clock;
3224                         }
3225                 }
3226
3227                 if (data->apply_overdrive_next_settings_mask &
3228                                 DPMTABLE_OD_UPDATE_MCLK) {
3229                         for (dpm_count = 0;
3230                                         dpm_count < dpm_table->mem_table.count;
3231                                         dpm_count++) {
3232                                 dpm_table->mem_table.dpm_levels[dpm_count].enabled =
3233                                                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
3234                                                 performance_level_entries[dpm_count].enabled;
3235                                 dpm_table->mem_table.dpm_levels[dpm_count].value =
3236                                                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
3237                                                 performance_level_entries[dpm_count].clock;
3238                         }
3239                 }
3240
3241                 if ((data->need_update_dpm_table & DPMTABLE_UPDATE_SCLK) ||
3242                         data->apply_optimized_settings ||
3243                         (data->apply_overdrive_next_settings_mask &
3244                                         DPMTABLE_OD_UPDATE_SCLK)) {
3245                         result = vega10_populate_all_graphic_levels(hwmgr);
3246                         PP_ASSERT_WITH_CODE(!result,
3247                                         "Failed to populate SCLK during \
3248                                         PopulateNewDPMClocksStates Function!",
3249                                         return result);
3250                 }
3251
3252                 if ((data->need_update_dpm_table & DPMTABLE_UPDATE_MCLK) ||
3253                         (data->apply_overdrive_next_settings_mask &
3254                                         DPMTABLE_OD_UPDATE_MCLK)){
3255                         result = vega10_populate_all_memory_levels(hwmgr);
3256                         PP_ASSERT_WITH_CODE(!result,
3257                                         "Failed to populate MCLK during \
3258                                         PopulateNewDPMClocksStates Function!",
3259                                         return result);
3260                 }
3261         } else {
3262                 if (!data->need_update_dpm_table &&
3263                                 !data->apply_optimized_settings)
3264                         return 0;
3265
3266                 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK &&
3267                                 data->smu_features[GNLD_DPM_GFXCLK].supported) {
3268                                 dpm_table->
3269                                 gfx_table.dpm_levels[dpm_table->gfx_table.count - 1].
3270                                 value = sclk;
3271
3272                                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3273                                                 PHM_PlatformCaps_OD6PlusinACSupport) ||
3274                                         phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3275                                                         PHM_PlatformCaps_OD6PlusinDCSupport)) {
3276                                         /* Need to do calculation based on the golden DPM table
3277                                          * as the Heatmap GPU Clock axis is also based on
3278                                          * the default values
3279                                          */
3280                                         PP_ASSERT_WITH_CODE(
3281                                                         golden_dpm_table->gfx_table.dpm_levels
3282                                                         [golden_dpm_table->gfx_table.count - 1].value,
3283                                                         "Divide by 0!",
3284                                                         return -1);
3285
3286                                         dpm_count = dpm_table->gfx_table.count < 2 ?
3287                                                         0 : dpm_table->gfx_table.count - 2;
3288                                         for (i = dpm_count; i > 1; i--) {
3289                                                 if (sclk > golden_dpm_table->gfx_table.dpm_levels
3290                                                         [golden_dpm_table->gfx_table.count - 1].value) {
3291                                                         clock_percent =
3292                                                                 ((sclk - golden_dpm_table->gfx_table.dpm_levels
3293                                                                 [golden_dpm_table->gfx_table.count - 1].value) *
3294                                                                 100) /
3295                                                                 golden_dpm_table->gfx_table.dpm_levels
3296                                                                 [golden_dpm_table->gfx_table.count - 1].value;
3297
3298                                                         dpm_table->gfx_table.dpm_levels[i].value =
3299                                                                 golden_dpm_table->gfx_table.dpm_levels[i].value +
3300                                                                 (golden_dpm_table->gfx_table.dpm_levels[i].value *
3301                                                                 clock_percent) / 100;
3302                                                 } else if (golden_dpm_table->
3303                                                                 gfx_table.dpm_levels[dpm_table->gfx_table.count-1].value >
3304                                                                 sclk) {
3305                                                         clock_percent =
3306                                                                 ((golden_dpm_table->gfx_table.dpm_levels
3307                                                                 [golden_dpm_table->gfx_table.count - 1].value -
3308                                                                 sclk) * 100) /
3309                                                                 golden_dpm_table->gfx_table.dpm_levels
3310                                                                 [golden_dpm_table->gfx_table.count-1].value;
3311
3312                                                         dpm_table->gfx_table.dpm_levels[i].value =
3313                                                                 golden_dpm_table->gfx_table.dpm_levels[i].value -
3314                                                                 (golden_dpm_table->gfx_table.dpm_levels[i].value *
3315                                                                 clock_percent) / 100;
3316                                                 } else
3317                                                         dpm_table->gfx_table.dpm_levels[i].value =
3318                                                                 golden_dpm_table->gfx_table.dpm_levels[i].value;
3319                                         }
3320                                 }
3321                         }
3322
3323                 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK &&
3324                                 data->smu_features[GNLD_DPM_UCLK].supported) {
3325                         dpm_table->
3326                         mem_table.dpm_levels[dpm_table->mem_table.count - 1].
3327                         value = mclk;
3328
3329                         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3330                                         PHM_PlatformCaps_OD6PlusinACSupport) ||
3331                                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3332                                                 PHM_PlatformCaps_OD6PlusinDCSupport)) {
3333
3334                                 PP_ASSERT_WITH_CODE(
3335                                         golden_dpm_table->mem_table.dpm_levels
3336                                         [golden_dpm_table->mem_table.count - 1].value,
3337                                         "Divide by 0!",
3338                                         return -1);
3339
3340                                 dpm_count = dpm_table->mem_table.count < 2 ?
3341                                                 0 : dpm_table->mem_table.count - 2;
3342                                 for (i = dpm_count; i > 1; i--) {
3343                                         if (mclk > golden_dpm_table->mem_table.dpm_levels
3344                                                 [golden_dpm_table->mem_table.count-1].value) {
3345                                                 clock_percent = ((mclk -
3346                                                         golden_dpm_table->mem_table.dpm_levels
3347                                                         [golden_dpm_table->mem_table.count-1].value) *
3348                                                         100) /
3349                                                         golden_dpm_table->mem_table.dpm_levels
3350                                                         [golden_dpm_table->mem_table.count-1].value;
3351
3352                                                 dpm_table->mem_table.dpm_levels[i].value =
3353                                                         golden_dpm_table->mem_table.dpm_levels[i].value +
3354                                                         (golden_dpm_table->mem_table.dpm_levels[i].value *
3355                                                         clock_percent) / 100;
3356                                         } else if (golden_dpm_table->mem_table.dpm_levels
3357                                                         [dpm_table->mem_table.count-1].value > mclk) {
3358                                                 clock_percent = ((golden_dpm_table->mem_table.dpm_levels
3359                                                         [golden_dpm_table->mem_table.count-1].value - mclk) *
3360                                                         100) /
3361                                                         golden_dpm_table->mem_table.dpm_levels
3362                                                         [golden_dpm_table->mem_table.count-1].value;
3363
3364                                                 dpm_table->mem_table.dpm_levels[i].value =
3365                                                         golden_dpm_table->mem_table.dpm_levels[i].value -
3366                                                         (golden_dpm_table->mem_table.dpm_levels[i].value *
3367                                                         clock_percent) / 100;
3368                                         } else
3369                                                 dpm_table->mem_table.dpm_levels[i].value =
3370                                                         golden_dpm_table->mem_table.dpm_levels[i].value;
3371                                 }
3372                         }
3373                 }
3374
3375                 if ((data->need_update_dpm_table &
3376                         (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) ||
3377                         data->apply_optimized_settings) {
3378                         result = vega10_populate_all_graphic_levels(hwmgr);
3379                         PP_ASSERT_WITH_CODE(!result,
3380                                         "Failed to populate SCLK during \
3381                                         PopulateNewDPMClocksStates Function!",
3382                                         return result);
3383                 }
3384
3385                 if (data->need_update_dpm_table &
3386                                 (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
3387                         result = vega10_populate_all_memory_levels(hwmgr);
3388                         PP_ASSERT_WITH_CODE(!result,
3389                                         "Failed to populate MCLK during \
3390                                         PopulateNewDPMClocksStates Function!",
3391                                         return result);
3392                 }
3393         }
3394
3395         return result;
3396 }
3397
3398 static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
3399                 struct vega10_single_dpm_table *dpm_table,
3400                 uint32_t low_limit, uint32_t high_limit)
3401 {
3402         uint32_t i;
3403
3404         for (i = 0; i < dpm_table->count; i++) {
3405                 if ((dpm_table->dpm_levels[i].value < low_limit) ||
3406                     (dpm_table->dpm_levels[i].value > high_limit))
3407                         dpm_table->dpm_levels[i].enabled = false;
3408                 else
3409                         dpm_table->dpm_levels[i].enabled = true;
3410         }
3411         return 0;
3412 }
3413
3414 static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr,
3415                 struct vega10_single_dpm_table *dpm_table,
3416                 uint32_t low_limit, uint32_t high_limit,
3417                 uint32_t disable_dpm_mask)
3418 {
3419         uint32_t i;
3420
3421         for (i = 0; i < dpm_table->count; i++) {
3422                 if ((dpm_table->dpm_levels[i].value < low_limit) ||
3423                     (dpm_table->dpm_levels[i].value > high_limit))
3424                         dpm_table->dpm_levels[i].enabled = false;
3425                 else if (!((1 << i) & disable_dpm_mask))
3426                         dpm_table->dpm_levels[i].enabled = false;
3427                 else
3428                         dpm_table->dpm_levels[i].enabled = true;
3429         }
3430         return 0;
3431 }
3432
3433 static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr,
3434                 const struct vega10_power_state *vega10_ps)
3435 {
3436         struct vega10_hwmgr *data =
3437                         (struct vega10_hwmgr *)(hwmgr->backend);
3438         uint32_t high_limit_count;
3439
3440         PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1),
3441                         "power state did not have any performance level",
3442                         return -1);
3443
3444         high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1;
3445
3446         vega10_trim_single_dpm_states(hwmgr,
3447                         &(data->dpm_table.soc_table),
3448                         vega10_ps->performance_levels[0].soc_clock,
3449                         vega10_ps->performance_levels[high_limit_count].soc_clock);
3450
3451         vega10_trim_single_dpm_states_with_mask(hwmgr,
3452                         &(data->dpm_table.gfx_table),
3453                         vega10_ps->performance_levels[0].gfx_clock,
3454                         vega10_ps->performance_levels[high_limit_count].gfx_clock,
3455                         data->disable_dpm_mask);
3456
3457         vega10_trim_single_dpm_states(hwmgr,
3458                         &(data->dpm_table.mem_table),
3459                         vega10_ps->performance_levels[0].mem_clock,
3460                         vega10_ps->performance_levels[high_limit_count].mem_clock);
3461
3462         return 0;
3463 }
3464
3465 static uint32_t vega10_find_lowest_dpm_level(
3466                 struct vega10_single_dpm_table *table)
3467 {
3468         uint32_t i;
3469
3470         for (i = 0; i < table->count; i++) {
3471                 if (table->dpm_levels[i].enabled)
3472                         break;
3473         }
3474
3475         return i;
3476 }
3477
3478 static uint32_t vega10_find_highest_dpm_level(
3479                 struct vega10_single_dpm_table *table)
3480 {
3481         uint32_t i = 0;
3482
3483         if (table->count <= MAX_REGULAR_DPM_NUMBER) {
3484                 for (i = table->count; i > 0; i--) {
3485                         if (table->dpm_levels[i - 1].enabled)
3486                                 return i - 1;
3487                 }
3488         } else {
3489                 pr_info("DPM Table Has Too Many Entries!");
3490                 return MAX_REGULAR_DPM_NUMBER - 1;
3491         }
3492
3493         return i;
3494 }
3495
3496 static void vega10_apply_dal_minimum_voltage_request(
3497                 struct pp_hwmgr *hwmgr)
3498 {
3499         return;
3500 }
3501
3502 static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
3503 {
3504         struct vega10_hwmgr *data =
3505                         (struct vega10_hwmgr *)(hwmgr->backend);
3506
3507         vega10_apply_dal_minimum_voltage_request(hwmgr);
3508
3509         if (!data->registry_data.sclk_dpm_key_disabled) {
3510                 if (data->smc_state_table.gfx_boot_level !=
3511                                 data->dpm_table.gfx_table.dpm_state.soft_min_level) {
3512                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3513                                 hwmgr->smumgr,
3514                                 PPSMC_MSG_SetSoftMinGfxclkByIndex,
3515                                 data->smc_state_table.gfx_boot_level),
3516                                 "Failed to set soft min sclk index!",
3517                                 return -EINVAL);
3518                         data->dpm_table.gfx_table.dpm_state.soft_min_level =
3519                                         data->smc_state_table.gfx_boot_level;
3520                 }
3521         }
3522
3523         if (!data->registry_data.mclk_dpm_key_disabled) {
3524                 if (data->smc_state_table.mem_boot_level !=
3525                                 data->dpm_table.mem_table.dpm_state.soft_min_level) {
3526                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3527                                 hwmgr->smumgr,
3528                                  PPSMC_MSG_SetSoftMinUclkByIndex,
3529                                 data->smc_state_table.mem_boot_level),
3530                                 "Failed to set soft min mclk index!",
3531                                 return -EINVAL);
3532
3533                         data->dpm_table.mem_table.dpm_state.soft_min_level =
3534                                         data->smc_state_table.mem_boot_level;
3535                 }
3536         }
3537
3538         return 0;
3539 }
3540
3541 static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
3542 {
3543         struct vega10_hwmgr *data =
3544                         (struct vega10_hwmgr *)(hwmgr->backend);
3545
3546         vega10_apply_dal_minimum_voltage_request(hwmgr);
3547
3548         if (!data->registry_data.sclk_dpm_key_disabled) {
3549                 if (data->smc_state_table.gfx_max_level !=
3550                                 data->dpm_table.gfx_table.dpm_state.soft_max_level) {
3551                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3552                                 hwmgr->smumgr,
3553                                 PPSMC_MSG_SetSoftMaxGfxclkByIndex,
3554                                 data->smc_state_table.gfx_max_level),
3555                                 "Failed to set soft max sclk index!",
3556                                 return -EINVAL);
3557                         data->dpm_table.gfx_table.dpm_state.soft_max_level =
3558                                         data->smc_state_table.gfx_max_level;
3559                 }
3560         }
3561
3562         if (!data->registry_data.mclk_dpm_key_disabled) {
3563                 if (data->smc_state_table.mem_max_level !=
3564                                 data->dpm_table.mem_table.dpm_state.soft_max_level) {
3565                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3566                                 hwmgr->smumgr,
3567                                 PPSMC_MSG_SetSoftMaxUclkByIndex,
3568                                 data->smc_state_table.mem_max_level),
3569                                 "Failed to set soft max mclk index!",
3570                                 return -EINVAL);
3571                         data->dpm_table.mem_table.dpm_state.soft_max_level =
3572                                         data->smc_state_table.mem_max_level;
3573                 }
3574         }
3575
3576         return 0;
3577 }
3578
3579 static int vega10_generate_dpm_level_enable_mask(
3580                 struct pp_hwmgr *hwmgr, const void *input)
3581 {
3582         struct vega10_hwmgr *data =
3583                         (struct vega10_hwmgr *)(hwmgr->backend);
3584         const struct phm_set_power_state_input *states =
3585                         (const struct phm_set_power_state_input *)input;
3586         const struct vega10_power_state *vega10_ps =
3587                         cast_const_phw_vega10_power_state(states->pnew_state);
3588         int i;
3589
3590         PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps),
3591                         "Attempt to Trim DPM States Failed!",
3592                         return -1);
3593
3594         data->smc_state_table.gfx_boot_level =
3595                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3596         data->smc_state_table.gfx_max_level =
3597                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3598         data->smc_state_table.mem_boot_level =
3599                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3600         data->smc_state_table.mem_max_level =
3601                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3602
3603         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3604                         "Attempt to upload DPM Bootup Levels Failed!",
3605                         return -1);
3606         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3607                         "Attempt to upload DPM Max Levels Failed!",
3608                         return -1);
3609         for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++)
3610                 data->dpm_table.gfx_table.dpm_levels[i].enabled = true;
3611
3612
3613         for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++)
3614                 data->dpm_table.mem_table.dpm_levels[i].enabled = true;
3615
3616         return 0;
3617 }
3618
3619 int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
3620 {
3621         struct vega10_hwmgr *data =
3622                         (struct vega10_hwmgr *)(hwmgr->backend);
3623
3624         if (data->smu_features[GNLD_DPM_VCE].supported) {
3625                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
3626                                 enable,
3627                                 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap),
3628                                 "Attempt to Enable/Disable DPM VCE Failed!",
3629                                 return -1);
3630                 data->smu_features[GNLD_DPM_VCE].enabled = enable;
3631         }
3632
3633         return 0;
3634 }
3635
3636 static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
3637 {
3638         struct vega10_hwmgr *data =
3639                         (struct vega10_hwmgr *)(hwmgr->backend);
3640         int result = 0;
3641         uint32_t low_sclk_interrupt_threshold = 0;
3642
3643         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3644                         PHM_PlatformCaps_SclkThrottleLowNotification)
3645                 && (hwmgr->gfx_arbiter.sclk_threshold !=
3646                                 data->low_sclk_interrupt_threshold)) {
3647                 data->low_sclk_interrupt_threshold =
3648                                 hwmgr->gfx_arbiter.sclk_threshold;
3649                 low_sclk_interrupt_threshold =
3650                                 data->low_sclk_interrupt_threshold;
3651
3652                 data->smc_state_table.pp_table.LowGfxclkInterruptThreshold =
3653                                 cpu_to_le32(low_sclk_interrupt_threshold);
3654
3655                 /* This message will also enable SmcToHost Interrupt */
3656                 result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
3657                                 PPSMC_MSG_SetLowGfxclkInterruptThreshold,
3658                                 (uint32_t)low_sclk_interrupt_threshold);
3659         }
3660
3661         return result;
3662 }
3663
3664 static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
3665                 const void *input)
3666 {
3667         int tmp_result, result = 0;
3668         struct vega10_hwmgr *data =
3669                         (struct vega10_hwmgr *)(hwmgr->backend);
3670         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
3671
3672         tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
3673         PP_ASSERT_WITH_CODE(!tmp_result,
3674                         "Failed to find DPM states clocks in DPM table!",
3675                         result = tmp_result);
3676
3677         tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
3678         PP_ASSERT_WITH_CODE(!tmp_result,
3679                         "Failed to populate and upload SCLK MCLK DPM levels!",
3680                         result = tmp_result);
3681
3682         tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input);
3683         PP_ASSERT_WITH_CODE(!tmp_result,
3684                         "Failed to generate DPM level enabled mask!",
3685                         result = tmp_result);
3686
3687         tmp_result = vega10_update_sclk_threshold(hwmgr);
3688         PP_ASSERT_WITH_CODE(!tmp_result,
3689                         "Failed to update SCLK threshold!",
3690                         result = tmp_result);
3691
3692         result = vega10_copy_table_to_smc(hwmgr->smumgr,
3693                         (uint8_t *)pp_table, PPTABLE);
3694         PP_ASSERT_WITH_CODE(!result,
3695                         "Failed to upload PPtable!", return result);
3696
3697         data->apply_optimized_settings = false;
3698         data->apply_overdrive_next_settings_mask = 0;
3699
3700         return 0;
3701 }
3702
3703 static int vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
3704 {
3705         struct pp_power_state *ps;
3706         struct vega10_power_state *vega10_ps;
3707
3708         if (hwmgr == NULL)
3709                 return -EINVAL;
3710
3711         ps = hwmgr->request_ps;
3712
3713         if (ps == NULL)
3714                 return -EINVAL;
3715
3716         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
3717
3718         if (low)
3719                 return vega10_ps->performance_levels[0].gfx_clock;
3720         else
3721                 return vega10_ps->performance_levels
3722                                 [vega10_ps->performance_level_count - 1].gfx_clock;
3723 }
3724
3725 static int vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
3726 {
3727         struct pp_power_state *ps;
3728         struct vega10_power_state *vega10_ps;
3729
3730         if (hwmgr == NULL)
3731                 return -EINVAL;
3732
3733         ps = hwmgr->request_ps;
3734
3735         if (ps == NULL)
3736                 return -EINVAL;
3737
3738         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
3739
3740         if (low)
3741                 return vega10_ps->performance_levels[0].mem_clock;
3742         else
3743                 return vega10_ps->performance_levels
3744                                 [vega10_ps->performance_level_count-1].mem_clock;
3745 }
3746
3747 static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
3748                               void *value, int *size)
3749 {
3750         uint32_t sclk_idx, mclk_idx, activity_percent = 0;
3751         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
3752         struct vega10_dpm_table *dpm_table = &data->dpm_table;
3753         int ret = 0;
3754
3755         switch (idx) {
3756         case AMDGPU_PP_SENSOR_GFX_SCLK:
3757                 ret = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetCurrentGfxclkIndex);
3758                 if (!ret) {
3759                         vega10_read_arg_from_smc(hwmgr->smumgr, &sclk_idx);
3760                         *((uint32_t *)value) = dpm_table->gfx_table.dpm_levels[sclk_idx].value;
3761                         *size = 4;
3762                 }
3763                 break;
3764         case AMDGPU_PP_SENSOR_GFX_MCLK:
3765                 ret = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetCurrentUclkIndex);
3766                 if (!ret) {
3767                         vega10_read_arg_from_smc(hwmgr->smumgr, &mclk_idx);
3768                         *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value;
3769                         *size = 4;
3770                 }
3771                 break;
3772         case AMDGPU_PP_SENSOR_GPU_LOAD:
3773                 ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_GetAverageGfxActivity, 0);
3774                 if (!ret) {
3775                         vega10_read_arg_from_smc(hwmgr->smumgr, &activity_percent);
3776                         *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
3777                         *size = 4;
3778                 }
3779                 break;
3780         case AMDGPU_PP_SENSOR_GPU_TEMP:
3781                 *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr);
3782                 *size = 4;
3783                 break;
3784         case AMDGPU_PP_SENSOR_UVD_POWER:
3785                 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
3786                 *size = 4;
3787                 break;
3788         case AMDGPU_PP_SENSOR_VCE_POWER:
3789                 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
3790                 *size = 4;
3791                 break;
3792         default:
3793                 ret = -EINVAL;
3794                 break;
3795         }
3796         return ret;
3797 }
3798
3799 static int vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr,
3800                 bool has_disp)
3801 {
3802         return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
3803                         PPSMC_MSG_SetUclkFastSwitch,
3804                         has_disp ? 0 : 1);
3805 }
3806
3807 int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
3808                 struct pp_display_clock_request *clock_req)
3809 {
3810         int result = 0;
3811         enum amd_pp_clock_type clk_type = clock_req->clock_type;
3812         uint32_t clk_freq = clock_req->clock_freq_in_khz / 100;
3813         DSPCLK_e clk_select = 0;
3814         uint32_t clk_request = 0;
3815
3816         switch (clk_type) {
3817         case amd_pp_dcef_clock:
3818                 clk_select = DSPCLK_DCEFCLK;
3819                 break;
3820         case amd_pp_disp_clock:
3821                 clk_select = DSPCLK_DISPCLK;
3822                 break;
3823         case amd_pp_pixel_clock:
3824                 clk_select = DSPCLK_PIXCLK;
3825                 break;
3826         case amd_pp_phy_clock:
3827                 clk_select = DSPCLK_PHYCLK;
3828                 break;
3829         default:
3830                 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
3831                 result = -1;
3832                 break;
3833         }
3834
3835         if (!result) {
3836                 clk_request = (clk_freq << 16) | clk_select;
3837                 result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
3838                                 PPSMC_MSG_RequestDisplayClockByFreq,
3839                                 clk_request);
3840         }
3841
3842         return result;
3843 }
3844
3845 static int vega10_notify_smc_display_config_after_ps_adjustment(
3846                 struct pp_hwmgr *hwmgr)
3847 {
3848         struct vega10_hwmgr *data =
3849                         (struct vega10_hwmgr *)(hwmgr->backend);
3850         struct vega10_single_dpm_table *dpm_table =
3851                         &data->dpm_table.dcef_table;
3852         uint32_t num_active_disps = 0;
3853         struct cgs_display_info info = {0};
3854         struct PP_Clocks min_clocks = {0};
3855         uint32_t i;
3856         struct pp_display_clock_request clock_req;
3857
3858         info.mode_info = NULL;
3859
3860         cgs_get_active_displays_info(hwmgr->device, &info);
3861
3862         num_active_disps = info.display_count;
3863
3864         if (num_active_disps > 1)
3865                 vega10_notify_smc_display_change(hwmgr, false);
3866         else
3867                 vega10_notify_smc_display_change(hwmgr, true);
3868
3869         min_clocks.dcefClock = hwmgr->display_config.min_dcef_set_clk;
3870         min_clocks.dcefClockInSR = hwmgr->display_config.min_dcef_deep_sleep_set_clk;
3871
3872         for (i = 0; i < dpm_table->count; i++) {
3873                 if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock)
3874                         break;
3875         }
3876
3877         if (i < dpm_table->count) {
3878                 clock_req.clock_type = amd_pp_dcef_clock;
3879                 clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value;
3880                 if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) {
3881                         PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3882                                         hwmgr->smumgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
3883                                         min_clocks.dcefClockInSR),
3884                                         "Attempt to set divider for DCEFCLK Failed!",);
3885                 } else
3886                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
3887         } else
3888                 pr_info("Cannot find requested DCEFCLK!");
3889
3890         return 0;
3891 }
3892
3893 static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr)
3894 {
3895         struct vega10_hwmgr *data =
3896                         (struct vega10_hwmgr *)(hwmgr->backend);
3897
3898         data->smc_state_table.gfx_boot_level =
3899         data->smc_state_table.gfx_max_level =
3900                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3901         data->smc_state_table.mem_boot_level =
3902         data->smc_state_table.mem_max_level =
3903                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3904
3905         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3906                         "Failed to upload boot level to highest!",
3907                         return -1);
3908
3909         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3910                         "Failed to upload dpm max level to highest!",
3911                         return -1);
3912
3913         return 0;
3914 }
3915
3916 static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3917 {
3918         struct vega10_hwmgr *data =
3919                         (struct vega10_hwmgr *)(hwmgr->backend);
3920
3921         data->smc_state_table.gfx_boot_level =
3922         data->smc_state_table.gfx_max_level =
3923                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3924         data->smc_state_table.mem_boot_level =
3925         data->smc_state_table.mem_max_level =
3926                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3927
3928         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3929                         "Failed to upload boot level to highest!",
3930                         return -1);
3931
3932         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3933                         "Failed to upload dpm max level to highest!",
3934                         return -1);
3935
3936         return 0;
3937
3938 }
3939
3940 static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
3941 {
3942         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
3943
3944         data->smc_state_table.gfx_boot_level =
3945                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3946         data->smc_state_table.gfx_max_level =
3947                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3948         data->smc_state_table.mem_boot_level =
3949                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3950         data->smc_state_table.mem_max_level =
3951                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3952
3953         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3954                         "Failed to upload DPM Bootup Levels!",
3955                         return -1);
3956
3957         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3958                         "Failed to upload DPM Max Levels!",
3959                         return -1);
3960         return 0;
3961 }
3962
3963 static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
3964                                 enum amd_dpm_forced_level level)
3965 {
3966         int ret = 0;
3967
3968         switch (level) {
3969         case AMD_DPM_FORCED_LEVEL_HIGH:
3970                 ret = vega10_force_dpm_highest(hwmgr);
3971                 if (ret)
3972                         return ret;
3973                 break;
3974         case AMD_DPM_FORCED_LEVEL_LOW:
3975                 ret = vega10_force_dpm_lowest(hwmgr);
3976                 if (ret)
3977                         return ret;
3978                 break;
3979         case AMD_DPM_FORCED_LEVEL_AUTO:
3980                 ret = vega10_unforce_dpm_levels(hwmgr);
3981                 if (ret)
3982                         return ret;
3983                 break;
3984         default:
3985                 break;
3986         }
3987
3988         hwmgr->dpm_level = level;
3989
3990         return ret;
3991 }
3992
3993 static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
3994 {
3995         int result = 0;
3996
3997         switch (mode) {
3998         case AMD_FAN_CTRL_NONE:
3999                 result = vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
4000                 break;
4001         case AMD_FAN_CTRL_MANUAL:
4002                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4003                         PHM_PlatformCaps_MicrocodeFanControl))
4004                         result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
4005                 break;
4006         case AMD_FAN_CTRL_AUTO:
4007                 result = vega10_fan_ctrl_set_static_mode(hwmgr, mode);
4008                 if (!result)
4009                         result = vega10_fan_ctrl_start_smc_fan_control(hwmgr);
4010                 break;
4011         default:
4012                 break;
4013         }
4014         return result;
4015 }
4016
4017 static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr)
4018 {
4019         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4020
4021         if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
4022                 return AMD_FAN_CTRL_MANUAL;
4023         else
4024                 return AMD_FAN_CTRL_AUTO;
4025 }
4026
4027 static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr,
4028                 struct amd_pp_simple_clock_info *info)
4029 {
4030         struct phm_ppt_v2_information *table_info =
4031                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4032         struct phm_clock_and_voltage_limits *max_limits =
4033                         &table_info->max_clock_voltage_on_ac;
4034
4035         info->engine_max_clock = max_limits->sclk;
4036         info->memory_max_clock = max_limits->mclk;
4037
4038         return 0;
4039 }
4040
4041 static void vega10_get_sclks(struct pp_hwmgr *hwmgr,
4042                 struct pp_clock_levels_with_latency *clocks)
4043 {
4044         struct phm_ppt_v2_information *table_info =
4045                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4046         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4047                         table_info->vdd_dep_on_sclk;
4048         uint32_t i;
4049
4050         for (i = 0; i < dep_table->count; i++) {
4051                 if (dep_table->entries[i].clk) {
4052                         clocks->data[clocks->num_levels].clocks_in_khz =
4053                                         dep_table->entries[i].clk;
4054                         clocks->num_levels++;
4055                 }
4056         }
4057
4058 }
4059
4060 static uint32_t vega10_get_mem_latency(struct pp_hwmgr *hwmgr,
4061                 uint32_t clock)
4062 {
4063         if (clock >= MEM_FREQ_LOW_LATENCY &&
4064                         clock < MEM_FREQ_HIGH_LATENCY)
4065                 return MEM_LATENCY_HIGH;
4066         else if (clock >= MEM_FREQ_HIGH_LATENCY)
4067                 return MEM_LATENCY_LOW;
4068         else
4069                 return MEM_LATENCY_ERR;
4070 }
4071
4072 static void vega10_get_memclocks(struct pp_hwmgr *hwmgr,
4073                 struct pp_clock_levels_with_latency *clocks)
4074 {
4075         struct phm_ppt_v2_information *table_info =
4076                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4077         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4078                         table_info->vdd_dep_on_mclk;
4079         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4080         uint32_t i;
4081
4082         clocks->num_levels = 0;
4083         data->mclk_latency_table.count = 0;
4084
4085         for (i = 0; i < dep_table->count; i++) {
4086                 if (dep_table->entries[i].clk) {
4087                         clocks->data[clocks->num_levels].clocks_in_khz =
4088                         data->mclk_latency_table.entries
4089                         [data->mclk_latency_table.count].frequency =
4090                                         dep_table->entries[i].clk;
4091                         clocks->data[clocks->num_levels].latency_in_us =
4092                         data->mclk_latency_table.entries
4093                         [data->mclk_latency_table.count].latency =
4094                                         vega10_get_mem_latency(hwmgr,
4095                                                 dep_table->entries[i].clk);
4096                         clocks->num_levels++;
4097                         data->mclk_latency_table.count++;
4098                 }
4099         }
4100 }
4101
4102 static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr,
4103                 struct pp_clock_levels_with_latency *clocks)
4104 {
4105         struct phm_ppt_v2_information *table_info =
4106                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4107         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4108                         table_info->vdd_dep_on_dcefclk;
4109         uint32_t i;
4110
4111         for (i = 0; i < dep_table->count; i++) {
4112                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk;
4113                 clocks->data[i].latency_in_us = 0;
4114                 clocks->num_levels++;
4115         }
4116 }
4117
4118 static void vega10_get_socclocks(struct pp_hwmgr *hwmgr,
4119                 struct pp_clock_levels_with_latency *clocks)
4120 {
4121         struct phm_ppt_v2_information *table_info =
4122                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4123         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
4124                         table_info->vdd_dep_on_socclk;
4125         uint32_t i;
4126
4127         for (i = 0; i < dep_table->count; i++) {
4128                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk;
4129                 clocks->data[i].latency_in_us = 0;
4130                 clocks->num_levels++;
4131         }
4132 }
4133
4134 static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
4135                 enum amd_pp_clock_type type,
4136                 struct pp_clock_levels_with_latency *clocks)
4137 {
4138         switch (type) {
4139         case amd_pp_sys_clock:
4140                 vega10_get_sclks(hwmgr, clocks);
4141                 break;
4142         case amd_pp_mem_clock:
4143                 vega10_get_memclocks(hwmgr, clocks);
4144                 break;
4145         case amd_pp_dcef_clock:
4146                 vega10_get_dcefclocks(hwmgr, clocks);
4147                 break;
4148         case amd_pp_soc_clock:
4149                 vega10_get_socclocks(hwmgr, clocks);
4150                 break;
4151         default:
4152                 return -1;
4153         }
4154
4155         return 0;
4156 }
4157
4158 static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
4159                 enum amd_pp_clock_type type,
4160                 struct pp_clock_levels_with_voltage *clocks)
4161 {
4162         struct phm_ppt_v2_information *table_info =
4163                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4164         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
4165         uint32_t i;
4166
4167         switch (type) {
4168         case amd_pp_mem_clock:
4169                 dep_table = table_info->vdd_dep_on_mclk;
4170                 break;
4171         case amd_pp_dcef_clock:
4172                 dep_table = table_info->vdd_dep_on_dcefclk;
4173                 break;
4174         case amd_pp_disp_clock:
4175                 dep_table = table_info->vdd_dep_on_dispclk;
4176                 break;
4177         case amd_pp_pixel_clock:
4178                 dep_table = table_info->vdd_dep_on_pixclk;
4179                 break;
4180         case amd_pp_phy_clock:
4181                 dep_table = table_info->vdd_dep_on_phyclk;
4182                 break;
4183         default:
4184                 return -1;
4185         }
4186
4187         for (i = 0; i < dep_table->count; i++) {
4188                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk;
4189                 clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table->
4190                                 entries[dep_table->entries[i].vddInd].us_vdd);
4191                 clocks->num_levels++;
4192         }
4193
4194         if (i < dep_table->count)
4195                 return -1;
4196
4197         return 0;
4198 }
4199
4200 static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
4201                 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
4202 {
4203         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4204         Watermarks_t *table = &(data->smc_state_table.water_marks_table);
4205         int result = 0;
4206         uint32_t i;
4207
4208         if (!data->registry_data.disable_water_mark) {
4209                 for (i = 0; i < wm_with_clock_ranges->num_wm_sets_dmif; i++) {
4210                         table->WatermarkRow[WM_DCEFCLK][i].MinClock =
4211                                 cpu_to_le16((uint16_t)
4212                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_min_dcefclk_in_khz) /
4213                                 100);
4214                         table->WatermarkRow[WM_DCEFCLK][i].MaxClock =
4215                                 cpu_to_le16((uint16_t)
4216                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_max_dcefclk_in_khz) /
4217                                 100);
4218                         table->WatermarkRow[WM_DCEFCLK][i].MinUclk =
4219                                 cpu_to_le16((uint16_t)
4220                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_min_memclk_in_khz) /
4221                                 100);
4222                         table->WatermarkRow[WM_DCEFCLK][i].MaxUclk =
4223                                 cpu_to_le16((uint16_t)
4224                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_max_memclk_in_khz) /
4225                                 100);
4226                         table->WatermarkRow[WM_DCEFCLK][i].WmSetting = (uint8_t)
4227                                         wm_with_clock_ranges->wm_sets_dmif[i].wm_set_id;
4228                 }
4229
4230                 for (i = 0; i < wm_with_clock_ranges->num_wm_sets_mcif; i++) {
4231                         table->WatermarkRow[WM_SOCCLK][i].MinClock =
4232                                 cpu_to_le16((uint16_t)
4233                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_min_socclk_in_khz) /
4234                                 100);
4235                         table->WatermarkRow[WM_SOCCLK][i].MaxClock =
4236                                 cpu_to_le16((uint16_t)
4237                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_max_socclk_in_khz) /
4238                                 100);
4239                         table->WatermarkRow[WM_SOCCLK][i].MinUclk =
4240                                 cpu_to_le16((uint16_t)
4241                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_min_memclk_in_khz) /
4242                                 100);
4243                         table->WatermarkRow[WM_SOCCLK][i].MaxUclk =
4244                                 cpu_to_le16((uint16_t)
4245                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_max_memclk_in_khz) /
4246                                 100);
4247                         table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t)
4248                                         wm_with_clock_ranges->wm_sets_mcif[i].wm_set_id;
4249                 }
4250                 data->water_marks_bitmap = WaterMarksExist;
4251         }
4252
4253         return result;
4254 }
4255
4256 static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
4257                 enum pp_clock_type type, uint32_t mask)
4258 {
4259         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4260         int i;
4261
4262         if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
4263                 return -EINVAL;
4264
4265         switch (type) {
4266         case PP_SCLK:
4267                 for (i = 0; i < 32; i++) {
4268                         if (mask & (1 << i))
4269                                 break;
4270                 }
4271                 data->smc_state_table.gfx_boot_level = i;
4272
4273                 for (i = 31; i >= 0; i--) {
4274                         if (mask & (1 << i))
4275                                 break;
4276                 }
4277                 data->smc_state_table.gfx_max_level = i;
4278
4279                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
4280                         "Failed to upload boot level to lowest!",
4281                         return -EINVAL);
4282
4283                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4284                         "Failed to upload dpm max level to highest!",
4285                         return -EINVAL);
4286                 break;
4287
4288         case PP_MCLK:
4289                 for (i = 0; i < 32; i++) {
4290                         if (mask & (1 << i))
4291                                 break;
4292                 }
4293
4294                 for (i = 0; i < 32; i++) {
4295                         if (mask & (1 << i))
4296                                 break;
4297                 }
4298                 data->smc_state_table.mem_boot_level = i;
4299
4300                 for (i = 31; i >= 0; i--) {
4301                         if (mask & (1 << i))
4302                                 break;
4303                 }
4304                 data->smc_state_table.mem_max_level = i;
4305
4306                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
4307                         "Failed to upload boot level to lowest!",
4308                         return -EINVAL);
4309
4310                 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
4311                         "Failed to upload dpm max level to highest!",
4312                         return -EINVAL);
4313
4314                 break;
4315
4316         case PP_PCIE:
4317         default:
4318                 break;
4319         }
4320
4321         return 0;
4322 }
4323
4324 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
4325                 enum pp_clock_type type, char *buf)
4326 {
4327         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4328         struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
4329         struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
4330         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
4331         int i, now, size = 0;
4332
4333         switch (type) {
4334         case PP_SCLK:
4335                 if (data->registry_data.sclk_dpm_key_disabled)
4336                         break;
4337
4338                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr,
4339                                 PPSMC_MSG_GetCurrentGfxclkIndex),
4340                                 "Attempt to get current sclk index Failed!",
4341                                 return -1);
4342                 PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr,
4343                                 &now),
4344                                 "Attempt to read sclk index Failed!",
4345                                 return -1);
4346
4347                 for (i = 0; i < sclk_table->count; i++)
4348                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4349                                         i, sclk_table->dpm_levels[i].value / 100,
4350                                         (i == now) ? "*" : "");
4351                 break;
4352         case PP_MCLK:
4353                 if (data->registry_data.mclk_dpm_key_disabled)
4354                         break;
4355
4356                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr,
4357                                 PPSMC_MSG_GetCurrentUclkIndex),
4358                                 "Attempt to get current mclk index Failed!",
4359                                 return -1);
4360                 PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr,
4361                                 &now),
4362                                 "Attempt to read mclk index Failed!",
4363                                 return -1);
4364
4365                 for (i = 0; i < mclk_table->count; i++)
4366                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4367                                         i, mclk_table->dpm_levels[i].value / 100,
4368                                         (i == now) ? "*" : "");
4369                 break;
4370         case PP_PCIE:
4371                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr,
4372                                 PPSMC_MSG_GetCurrentLinkIndex),
4373                                 "Attempt to get current mclk index Failed!",
4374                                 return -1);
4375                 PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr,
4376                                 &now),
4377                                 "Attempt to read mclk index Failed!",
4378                                 return -1);
4379
4380                 for (i = 0; i < pcie_table->count; i++)
4381                         size += sprintf(buf + size, "%d: %s %s\n", i,
4382                                         (pcie_table->pcie_gen[i] == 0) ? "2.5GB, x1" :
4383                                         (pcie_table->pcie_gen[i] == 1) ? "5.0GB, x16" :
4384                                         (pcie_table->pcie_gen[i] == 2) ? "8.0GB, x16" : "",
4385                                         (i == now) ? "*" : "");
4386                 break;
4387         default:
4388                 break;
4389         }
4390         return size;
4391 }
4392
4393 static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
4394 {
4395         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4396         int result = 0;
4397         uint32_t num_turned_on_displays = 1;
4398         Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
4399         struct cgs_display_info info = {0};
4400
4401         if ((data->water_marks_bitmap & WaterMarksExist) &&
4402                         !(data->water_marks_bitmap & WaterMarksLoaded)) {
4403                 result = vega10_copy_table_to_smc(hwmgr->smumgr,
4404                         (uint8_t *)wm_table, WMTABLE);
4405                 PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL);
4406                 data->water_marks_bitmap |= WaterMarksLoaded;
4407         }
4408
4409         if (data->water_marks_bitmap & WaterMarksLoaded) {
4410                 cgs_get_active_displays_info(hwmgr->device, &info);
4411                 num_turned_on_displays = info.display_count;
4412                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
4413                         PPSMC_MSG_NumOfDisplays, num_turned_on_displays);
4414         }
4415
4416         return result;
4417 }
4418
4419 int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
4420 {
4421         struct vega10_hwmgr *data =
4422                         (struct vega10_hwmgr *)(hwmgr->backend);
4423
4424         if (data->smu_features[GNLD_DPM_UVD].supported) {
4425                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
4426                                 enable,
4427                                 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap),
4428                                 "Attempt to Enable/Disable DPM UVD Failed!",
4429                                 return -1);
4430                 data->smu_features[GNLD_DPM_UVD].enabled = enable;
4431         }
4432         return 0;
4433 }
4434
4435 static int vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
4436 {
4437         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4438
4439         data->vce_power_gated = bgate;
4440         return vega10_enable_disable_vce_dpm(hwmgr, !bgate);
4441 }
4442
4443 static int vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
4444 {
4445         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4446
4447         data->uvd_power_gated = bgate;
4448         return vega10_enable_disable_uvd_dpm(hwmgr, !bgate);
4449 }
4450
4451 static inline bool vega10_are_power_levels_equal(
4452                                 const struct vega10_performance_level *pl1,
4453                                 const struct vega10_performance_level *pl2)
4454 {
4455         return ((pl1->soc_clock == pl2->soc_clock) &&
4456                         (pl1->gfx_clock == pl2->gfx_clock) &&
4457                         (pl1->mem_clock == pl2->mem_clock));
4458 }
4459
4460 static int vega10_check_states_equal(struct pp_hwmgr *hwmgr,
4461                                 const struct pp_hw_power_state *pstate1,
4462                         const struct pp_hw_power_state *pstate2, bool *equal)
4463 {
4464         const struct vega10_power_state *psa;
4465         const struct vega10_power_state *psb;
4466         int i;
4467
4468         if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
4469                 return -EINVAL;
4470
4471         psa = cast_const_phw_vega10_power_state(pstate1);
4472         psb = cast_const_phw_vega10_power_state(pstate2);
4473         /* If the two states don't even have the same number of performance levels they cannot be the same state. */
4474         if (psa->performance_level_count != psb->performance_level_count) {
4475                 *equal = false;
4476                 return 0;
4477         }
4478
4479         for (i = 0; i < psa->performance_level_count; i++) {
4480                 if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
4481                         /* If we have found even one performance level pair that is different the states are different. */
4482                         *equal = false;
4483                         return 0;
4484                 }
4485         }
4486
4487         /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
4488         *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
4489         *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
4490         *equal &= (psa->sclk_threshold == psb->sclk_threshold);
4491
4492         return 0;
4493 }
4494
4495 static bool
4496 vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
4497 {
4498         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4499         bool is_update_required = false;
4500         struct cgs_display_info info = {0, 0, NULL};
4501
4502         cgs_get_active_displays_info(hwmgr->device, &info);
4503
4504         if (data->display_timing.num_existing_displays != info.display_count)
4505                 is_update_required = true;
4506
4507         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
4508                 if (data->display_timing.min_clock_in_sr != hwmgr->display_config.min_core_set_clock_in_sr)
4509                         is_update_required = true;
4510         }
4511
4512         return is_update_required;
4513 }
4514
4515 static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
4516 {
4517         int tmp_result, result = 0;
4518
4519         tmp_result = (vega10_is_dpm_running(hwmgr)) ? 0 : -1;
4520         PP_ASSERT_WITH_CODE(tmp_result == 0,
4521                         "DPM is not running right now, no need to disable DPM!",
4522                         return 0);
4523
4524         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
4525                         PHM_PlatformCaps_ThermalController))
4526                 vega10_disable_thermal_protection(hwmgr);
4527
4528         tmp_result = vega10_disable_power_containment(hwmgr);
4529         PP_ASSERT_WITH_CODE((tmp_result == 0),
4530                         "Failed to disable power containment!", result = tmp_result);
4531
4532         tmp_result = vega10_avfs_enable(hwmgr, false);
4533         PP_ASSERT_WITH_CODE((tmp_result == 0),
4534                         "Failed to disable AVFS!", result = tmp_result);
4535
4536         tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES);
4537         PP_ASSERT_WITH_CODE((tmp_result == 0),
4538                         "Failed to stop DPM!", result = tmp_result);
4539
4540         return result;
4541 }
4542
4543 static int vega10_power_off_asic(struct pp_hwmgr *hwmgr)
4544 {
4545         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4546         int result;
4547
4548         result = vega10_disable_dpm_tasks(hwmgr);
4549         PP_ASSERT_WITH_CODE((0 == result),
4550                         "[disable_dpm_tasks] Failed to disable DPM!",
4551                         );
4552         data->water_marks_bitmap &= ~(WaterMarksLoaded);
4553
4554         return result;
4555 }
4556
4557 static void vega10_find_min_clock_index(struct pp_hwmgr *hwmgr,
4558                 uint32_t *sclk_idx, uint32_t *mclk_idx,
4559                 uint32_t min_sclk, uint32_t min_mclk)
4560 {
4561         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4562         struct vega10_dpm_table *dpm_table = &(data->dpm_table);
4563         uint32_t i;
4564
4565         for (i = 0; i < dpm_table->gfx_table.count; i++) {
4566                 if (dpm_table->gfx_table.dpm_levels[i].enabled &&
4567                         dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) {
4568                         *sclk_idx = i;
4569                         break;
4570                 }
4571         }
4572
4573         for (i = 0; i < dpm_table->mem_table.count; i++) {
4574                 if (dpm_table->mem_table.dpm_levels[i].enabled &&
4575                         dpm_table->mem_table.dpm_levels[i].value >= min_mclk) {
4576                         *mclk_idx = i;
4577                         break;
4578                 }
4579         }
4580 }
4581
4582 static int vega10_set_power_profile_state(struct pp_hwmgr *hwmgr,
4583                 struct amd_pp_profile *request)
4584 {
4585         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4586         uint32_t sclk_idx = 0, mclk_idx = 0;
4587
4588         if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)
4589                 return -EINVAL;
4590
4591         vega10_find_min_clock_index(hwmgr, &sclk_idx, &mclk_idx,
4592                         request->min_sclk, request->min_mclk);
4593
4594         if (sclk_idx) {
4595                 if (!data->registry_data.sclk_dpm_key_disabled)
4596                         PP_ASSERT_WITH_CODE(
4597                                         !smum_send_msg_to_smc_with_parameter(
4598                                         hwmgr->smumgr,
4599                                         PPSMC_MSG_SetSoftMinGfxclkByIndex,
4600                                         sclk_idx),
4601                                         "Failed to set soft min sclk index!",
4602                                         return -EINVAL);
4603         }
4604
4605         if (mclk_idx) {
4606                 if (!data->registry_data.mclk_dpm_key_disabled)
4607                         PP_ASSERT_WITH_CODE(
4608                                         !smum_send_msg_to_smc_with_parameter(
4609                                         hwmgr->smumgr,
4610                                         PPSMC_MSG_SetSoftMinUclkByIndex,
4611                                         mclk_idx),
4612                                         "Failed to set soft min mclk index!",
4613                                         return -EINVAL);
4614         }
4615
4616         return 0;
4617 }
4618
4619 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
4620         .backend_init = vega10_hwmgr_backend_init,
4621         .backend_fini = vega10_hwmgr_backend_fini,
4622         .asic_setup = vega10_setup_asic_task,
4623         .dynamic_state_management_enable = vega10_enable_dpm_tasks,
4624         .dynamic_state_management_disable = vega10_disable_dpm_tasks,
4625         .get_num_of_pp_table_entries =
4626                         vega10_get_number_of_powerplay_table_entries,
4627         .get_power_state_size = vega10_get_power_state_size,
4628         .get_pp_table_entry = vega10_get_pp_table_entry,
4629         .patch_boot_state = vega10_patch_boot_state,
4630         .apply_state_adjust_rules = vega10_apply_state_adjust_rules,
4631         .power_state_set = vega10_set_power_state_tasks,
4632         .get_sclk = vega10_dpm_get_sclk,
4633         .get_mclk = vega10_dpm_get_mclk,
4634         .notify_smc_display_config_after_ps_adjustment =
4635                         vega10_notify_smc_display_config_after_ps_adjustment,
4636         .force_dpm_level = vega10_dpm_force_dpm_level,
4637         .get_temperature = vega10_thermal_get_temperature,
4638         .stop_thermal_controller = vega10_thermal_stop_thermal_controller,
4639         .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info,
4640         .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent,
4641         .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent,
4642         .reset_fan_speed_to_default =
4643                         vega10_fan_ctrl_reset_fan_speed_to_default,
4644         .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm,
4645         .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm,
4646         .uninitialize_thermal_controller =
4647                         vega10_thermal_ctrl_uninitialize_thermal_controller,
4648         .set_fan_control_mode = vega10_set_fan_control_mode,
4649         .get_fan_control_mode = vega10_get_fan_control_mode,
4650         .read_sensor = vega10_read_sensor,
4651         .get_dal_power_level = vega10_get_dal_power_level,
4652         .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency,
4653         .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage,
4654         .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges,
4655         .display_clock_voltage_request = vega10_display_clock_voltage_request,
4656         .force_clock_level = vega10_force_clock_level,
4657         .print_clock_levels = vega10_print_clock_levels,
4658         .display_config_changed = vega10_display_configuration_changed_task,
4659         .powergate_uvd = vega10_power_gate_uvd,
4660         .powergate_vce = vega10_power_gate_vce,
4661         .check_states_equal = vega10_check_states_equal,
4662         .check_smc_update_required_for_display_configuration =
4663                         vega10_check_smc_update_required_for_display_configuration,
4664         .power_off_asic = vega10_power_off_asic,
4665         .disable_smc_firmware_ctf = vega10_thermal_disable_alert,
4666         .set_power_profile_state = vega10_set_power_profile_state,
4667 };
4668
4669 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
4670 {
4671         hwmgr->hwmgr_func = &vega10_hwmgr_funcs;
4672         hwmgr->pptable_func = &vega10_pptable_funcs;
4673         pp_vega10_thermal_initialize(hwmgr);
4674         return 0;
4675 }