drm/amd/powerplay: implement register thermal interrupt for Vega10
[muen/linux.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
24 #include <linux/delay.h>
25 #include <linux/fb.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28
29 #include "hwmgr.h"
30 #include "amd_powerplay.h"
31 #include "vega10_smumgr.h"
32 #include "hardwaremanager.h"
33 #include "ppatomfwctrl.h"
34 #include "atomfirmware.h"
35 #include "cgs_common.h"
36 #include "vega10_powertune.h"
37 #include "smu9.h"
38 #include "smu9_driver_if.h"
39 #include "vega10_inc.h"
40 #include "pp_soc15.h"
41 #include "pppcielanes.h"
42 #include "vega10_hwmgr.h"
43 #include "vega10_processpptables.h"
44 #include "vega10_pptable.h"
45 #include "vega10_thermal.h"
46 #include "pp_debug.h"
47 #include "pp_acpi.h"
48 #include "amd_pcie_helpers.h"
49 #include "cgs_linux.h"
50 #include "ppinterrupt.h"
51 #include "pp_overdriver.h"
52
53 #define VOLTAGE_SCALE  4
54 #define VOLTAGE_VID_OFFSET_SCALE1   625
55 #define VOLTAGE_VID_OFFSET_SCALE2   100
56
57 #define HBM_MEMORY_CHANNEL_WIDTH    128
58
59 uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2};
60
61 #define MEM_FREQ_LOW_LATENCY        25000
62 #define MEM_FREQ_HIGH_LATENCY       80000
63 #define MEM_LATENCY_HIGH            245
64 #define MEM_LATENCY_LOW             35
65 #define MEM_LATENCY_ERR             0xFFFF
66
67 #define mmDF_CS_AON0_DramBaseAddress0                                                                  0x0044
68 #define mmDF_CS_AON0_DramBaseAddress0_BASE_IDX                                                         0
69
70 //DF_CS_AON0_DramBaseAddress0
71 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal__SHIFT                                                        0x0
72 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT                                                    0x1
73 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT                                                      0x4
74 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT                                                      0x8
75 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr__SHIFT                                                      0xc
76 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal_MASK                                                          0x00000001L
77 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK                                                      0x00000002L
78 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK                                                        0x000000F0L
79 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK                                                        0x00000700L
80 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK                                                        0xFFFFF000L
81 static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
82                 enum pp_clock_type type, uint32_t mask);
83
84 const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic);
85
86 struct vega10_power_state *cast_phw_vega10_power_state(
87                                   struct pp_hw_power_state *hw_ps)
88 {
89         PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic),
90                                 "Invalid Powerstate Type!",
91                                  return NULL;);
92
93         return (struct vega10_power_state *)hw_ps;
94 }
95
96 const struct vega10_power_state *cast_const_phw_vega10_power_state(
97                                  const struct pp_hw_power_state *hw_ps)
98 {
99         PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic),
100                                 "Invalid Powerstate Type!",
101                                  return NULL;);
102
103         return (const struct vega10_power_state *)hw_ps;
104 }
105
106 static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr)
107 {
108         struct vega10_hwmgr *data =
109                         (struct vega10_hwmgr *)(hwmgr->backend);
110
111         data->registry_data.sclk_dpm_key_disabled =
112                         hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
113         data->registry_data.socclk_dpm_key_disabled =
114                         hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true;
115         data->registry_data.mclk_dpm_key_disabled =
116                         hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
117         data->registry_data.pcie_dpm_key_disabled =
118                         hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
119
120         data->registry_data.dcefclk_dpm_key_disabled =
121                         hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true;
122
123         if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
124                 data->registry_data.power_containment_support = 1;
125                 data->registry_data.enable_pkg_pwr_tracking_feature = 1;
126                 data->registry_data.enable_tdc_limit_feature = 1;
127         }
128
129         data->registry_data.clock_stretcher_support =
130                         hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false;
131
132         data->registry_data.ulv_support =
133                         hwmgr->feature_mask & PP_ULV_MASK ? true : false;
134
135         data->registry_data.sclk_deep_sleep_support =
136                         hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK ? true : false;
137
138         data->registry_data.disable_water_mark = 0;
139
140         data->registry_data.fan_control_support = 1;
141         data->registry_data.thermal_support = 1;
142         data->registry_data.fw_ctf_enabled = 1;
143
144         data->registry_data.avfs_support = 1;
145         data->registry_data.led_dpm_enabled = 1;
146
147         data->registry_data.vr0hot_enabled = 1;
148         data->registry_data.vr1hot_enabled = 1;
149         data->registry_data.regulator_hot_gpio_support = 1;
150
151         data->registry_data.didt_support = 1;
152         if (data->registry_data.didt_support) {
153                 data->registry_data.didt_mode = 6;
154                 data->registry_data.sq_ramping_support = 1;
155                 data->registry_data.db_ramping_support = 0;
156                 data->registry_data.td_ramping_support = 0;
157                 data->registry_data.tcp_ramping_support = 0;
158                 data->registry_data.dbr_ramping_support = 0;
159                 data->registry_data.edc_didt_support = 1;
160                 data->registry_data.gc_didt_support = 0;
161                 data->registry_data.psm_didt_support = 0;
162         }
163
164         data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT;
165         data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
166         data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
167         data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
168         data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
169         data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
170         data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
171         data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
172         data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
173         data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
174         data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
175         data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
176         data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT;
177
178         data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT;
179         data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT;
180         data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT;
181         data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT;
182 }
183
184 static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
185 {
186         struct vega10_hwmgr *data =
187                         (struct vega10_hwmgr *)(hwmgr->backend);
188         struct phm_ppt_v2_information *table_info =
189                         (struct phm_ppt_v2_information *)hwmgr->pptable;
190         struct cgs_system_info sys_info = {0};
191         int result;
192
193         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
194                         PHM_PlatformCaps_SclkDeepSleep);
195
196         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
197                         PHM_PlatformCaps_DynamicPatchPowerState);
198
199         if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE)
200                 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
201                                 PHM_PlatformCaps_ControlVDDCI);
202
203         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
204                         PHM_PlatformCaps_EnableSMU7ThermalManagement);
205
206         sys_info.size = sizeof(struct cgs_system_info);
207         sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
208         result = cgs_query_system_info(hwmgr->device, &sys_info);
209
210         if (!result && (sys_info.value & AMD_PG_SUPPORT_UVD))
211                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
212                                 PHM_PlatformCaps_UVDPowerGating);
213
214         if (!result && (sys_info.value & AMD_PG_SUPPORT_VCE))
215                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
216                                 PHM_PlatformCaps_VCEPowerGating);
217
218         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
219                         PHM_PlatformCaps_UnTabledHardwareInterface);
220
221         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
222                         PHM_PlatformCaps_FanSpeedInTableIsRPM);
223
224         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
225                         PHM_PlatformCaps_ODFuzzyFanControlSupport);
226
227         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
228                                 PHM_PlatformCaps_DynamicPowerManagement);
229
230         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
231                         PHM_PlatformCaps_SMC);
232
233         /* power tune caps */
234         /* assume disabled */
235         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
236                         PHM_PlatformCaps_PowerContainment);
237         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
238                         PHM_PlatformCaps_DiDtSupport);
239         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
240                         PHM_PlatformCaps_SQRamping);
241         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
242                         PHM_PlatformCaps_DBRamping);
243         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
244                         PHM_PlatformCaps_TDRamping);
245         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
246                         PHM_PlatformCaps_TCPRamping);
247         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
248                         PHM_PlatformCaps_DBRRamping);
249         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
250                         PHM_PlatformCaps_DiDtEDCEnable);
251         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
252                         PHM_PlatformCaps_GCEDC);
253         phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
254                         PHM_PlatformCaps_PSM);
255
256         if (data->registry_data.didt_support) {
257                 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport);
258                 if (data->registry_data.sq_ramping_support)
259                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping);
260                 if (data->registry_data.db_ramping_support)
261                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping);
262                 if (data->registry_data.td_ramping_support)
263                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping);
264                 if (data->registry_data.tcp_ramping_support)
265                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping);
266                 if (data->registry_data.dbr_ramping_support)
267                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping);
268                 if (data->registry_data.edc_didt_support)
269                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable);
270                 if (data->registry_data.gc_didt_support)
271                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC);
272                 if (data->registry_data.psm_didt_support)
273                         phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM);
274         }
275
276         if (data->registry_data.power_containment_support)
277                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
278                                 PHM_PlatformCaps_PowerContainment);
279         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
280                         PHM_PlatformCaps_CAC);
281
282         if (table_info->tdp_table->usClockStretchAmount &&
283                         data->registry_data.clock_stretcher_support)
284                 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
285                                 PHM_PlatformCaps_ClockStretcher);
286
287         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
288                         PHM_PlatformCaps_RegulatorHot);
289         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
290                         PHM_PlatformCaps_AutomaticDCTransition);
291
292         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
293                         PHM_PlatformCaps_UVDDPM);
294         phm_cap_set(hwmgr->platform_descriptor.platformCaps,
295                         PHM_PlatformCaps_VCEDPM);
296
297         return 0;
298 }
299
300 static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
301 {
302         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
303         int i;
304
305         vega10_initialize_power_tune_defaults(hwmgr);
306
307         for (i = 0; i < GNLD_FEATURES_MAX; i++) {
308                 data->smu_features[i].smu_feature_id = 0xffff;
309                 data->smu_features[i].smu_feature_bitmap = 1 << i;
310                 data->smu_features[i].enabled = false;
311                 data->smu_features[i].supported = false;
312         }
313
314         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
315                         FEATURE_DPM_PREFETCHER_BIT;
316         data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
317                         FEATURE_DPM_GFXCLK_BIT;
318         data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
319                         FEATURE_DPM_UCLK_BIT;
320         data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
321                         FEATURE_DPM_SOCCLK_BIT;
322         data->smu_features[GNLD_DPM_UVD].smu_feature_id =
323                         FEATURE_DPM_UVD_BIT;
324         data->smu_features[GNLD_DPM_VCE].smu_feature_id =
325                         FEATURE_DPM_VCE_BIT;
326         data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
327                         FEATURE_DPM_MP0CLK_BIT;
328         data->smu_features[GNLD_DPM_LINK].smu_feature_id =
329                         FEATURE_DPM_LINK_BIT;
330         data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
331                         FEATURE_DPM_DCEFCLK_BIT;
332         data->smu_features[GNLD_ULV].smu_feature_id =
333                         FEATURE_ULV_BIT;
334         data->smu_features[GNLD_AVFS].smu_feature_id =
335                         FEATURE_AVFS_BIT;
336         data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
337                         FEATURE_DS_GFXCLK_BIT;
338         data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
339                         FEATURE_DS_SOCCLK_BIT;
340         data->smu_features[GNLD_DS_LCLK].smu_feature_id =
341                         FEATURE_DS_LCLK_BIT;
342         data->smu_features[GNLD_PPT].smu_feature_id =
343                         FEATURE_PPT_BIT;
344         data->smu_features[GNLD_TDC].smu_feature_id =
345                         FEATURE_TDC_BIT;
346         data->smu_features[GNLD_THERMAL].smu_feature_id =
347                         FEATURE_THERMAL_BIT;
348         data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
349                         FEATURE_GFX_PER_CU_CG_BIT;
350         data->smu_features[GNLD_RM].smu_feature_id =
351                         FEATURE_RM_BIT;
352         data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
353                         FEATURE_DS_DCEFCLK_BIT;
354         data->smu_features[GNLD_ACDC].smu_feature_id =
355                         FEATURE_ACDC_BIT;
356         data->smu_features[GNLD_VR0HOT].smu_feature_id =
357                         FEATURE_VR0HOT_BIT;
358         data->smu_features[GNLD_VR1HOT].smu_feature_id =
359                         FEATURE_VR1HOT_BIT;
360         data->smu_features[GNLD_FW_CTF].smu_feature_id =
361                         FEATURE_FW_CTF_BIT;
362         data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
363                         FEATURE_LED_DISPLAY_BIT;
364         data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
365                         FEATURE_FAN_CONTROL_BIT;
366         data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT;
367         data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
368
369         if (!data->registry_data.prefetcher_dpm_key_disabled)
370                 data->smu_features[GNLD_DPM_PREFETCHER].supported = true;
371
372         if (!data->registry_data.sclk_dpm_key_disabled)
373                 data->smu_features[GNLD_DPM_GFXCLK].supported = true;
374
375         if (!data->registry_data.mclk_dpm_key_disabled)
376                 data->smu_features[GNLD_DPM_UCLK].supported = true;
377
378         if (!data->registry_data.socclk_dpm_key_disabled)
379                 data->smu_features[GNLD_DPM_SOCCLK].supported = true;
380
381         if (PP_CAP(PHM_PlatformCaps_UVDDPM))
382                 data->smu_features[GNLD_DPM_UVD].supported = true;
383
384         if (PP_CAP(PHM_PlatformCaps_VCEDPM))
385                 data->smu_features[GNLD_DPM_VCE].supported = true;
386
387         if (!data->registry_data.pcie_dpm_key_disabled)
388                 data->smu_features[GNLD_DPM_LINK].supported = true;
389
390         if (!data->registry_data.dcefclk_dpm_key_disabled)
391                 data->smu_features[GNLD_DPM_DCEFCLK].supported = true;
392
393         if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) &&
394             data->registry_data.sclk_deep_sleep_support) {
395                 data->smu_features[GNLD_DS_GFXCLK].supported = true;
396                 data->smu_features[GNLD_DS_SOCCLK].supported = true;
397                 data->smu_features[GNLD_DS_LCLK].supported = true;
398                 data->smu_features[GNLD_DS_DCEFCLK].supported = true;
399         }
400
401         if (data->registry_data.enable_pkg_pwr_tracking_feature)
402                 data->smu_features[GNLD_PPT].supported = true;
403
404         if (data->registry_data.enable_tdc_limit_feature)
405                 data->smu_features[GNLD_TDC].supported = true;
406
407         if (data->registry_data.thermal_support)
408                 data->smu_features[GNLD_THERMAL].supported = true;
409
410         if (data->registry_data.fan_control_support)
411                 data->smu_features[GNLD_FAN_CONTROL].supported = true;
412
413         if (data->registry_data.fw_ctf_enabled)
414                 data->smu_features[GNLD_FW_CTF].supported = true;
415
416         if (data->registry_data.avfs_support)
417                 data->smu_features[GNLD_AVFS].supported = true;
418
419         if (data->registry_data.led_dpm_enabled)
420                 data->smu_features[GNLD_LED_DISPLAY].supported = true;
421
422         if (data->registry_data.vr1hot_enabled)
423                 data->smu_features[GNLD_VR1HOT].supported = true;
424
425         if (data->registry_data.vr0hot_enabled)
426                 data->smu_features[GNLD_VR0HOT].supported = true;
427
428         smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetSmuVersion);
429         vega10_read_arg_from_smc(hwmgr->smumgr, &(data->smu_version));
430                 /* ACG firmware has major version 5 */
431         if ((data->smu_version & 0xff000000) == 0x5000000)
432                 data->smu_features[GNLD_ACG].supported = true;
433
434         if (data->registry_data.didt_support)
435                 data->smu_features[GNLD_DIDT].supported = true;
436
437 }
438
439 #ifdef PPLIB_VEGA10_EVV_SUPPORT
440 static int vega10_get_socclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
441         phm_ppt_v1_voltage_lookup_table *lookup_table,
442         uint16_t virtual_voltage_id, int32_t *socclk)
443 {
444         uint8_t entry_id;
445         uint8_t voltage_id;
446         struct phm_ppt_v2_information *table_info =
447                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
448
449         PP_ASSERT_WITH_CODE(lookup_table->count != 0,
450                         "Lookup table is empty",
451                         return -EINVAL);
452
453         /* search for leakage voltage ID 0xff01 ~ 0xff08 and sclk */
454         for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) {
455                 voltage_id = table_info->vdd_dep_on_socclk->entries[entry_id].vddInd;
456                 if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id)
457                         break;
458         }
459
460         PP_ASSERT_WITH_CODE(entry_id < table_info->vdd_dep_on_socclk->count,
461                         "Can't find requested voltage id in vdd_dep_on_socclk table!",
462                         return -EINVAL);
463
464         *socclk = table_info->vdd_dep_on_socclk->entries[entry_id].clk;
465
466         return 0;
467 }
468
469 #define ATOM_VIRTUAL_VOLTAGE_ID0             0xff01
470 /**
471 * Get Leakage VDDC based on leakage ID.
472 *
473 * @param    hwmgr  the address of the powerplay hardware manager.
474 * @return   always 0.
475 */
476 static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr)
477 {
478         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
479         uint16_t vv_id;
480         uint32_t vddc = 0;
481         uint16_t i, j;
482         uint32_t sclk = 0;
483         struct phm_ppt_v2_information *table_info =
484                         (struct phm_ppt_v2_information *)hwmgr->pptable;
485         struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table =
486                         table_info->vdd_dep_on_socclk;
487         int result;
488
489         for (i = 0; i < VEGA10_MAX_LEAKAGE_COUNT; i++) {
490                 vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
491
492                 if (!vega10_get_socclk_for_voltage_evv(hwmgr,
493                                 table_info->vddc_lookup_table, vv_id, &sclk)) {
494                         if (PP_CAP(PHM_PlatformCaps_ClockStretcher)) {
495                                 for (j = 1; j < socclk_table->count; j++) {
496                                         if (socclk_table->entries[j].clk == sclk &&
497                                                         socclk_table->entries[j].cks_enable == 0) {
498                                                 sclk += 5000;
499                                                 break;
500                                         }
501                                 }
502                         }
503
504                         PP_ASSERT_WITH_CODE(!atomctrl_get_voltage_evv_on_sclk_ai(hwmgr,
505                                         VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc),
506                                         "Error retrieving EVV voltage value!",
507                                         continue);
508
509
510                         /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
511                         PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0),
512                                         "Invalid VDDC value", result = -EINVAL;);
513
514                         /* the voltage should not be zero nor equal to leakage ID */
515                         if (vddc != 0 && vddc != vv_id) {
516                                 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100);
517                                 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
518                                 data->vddc_leakage.count++;
519                         }
520                 }
521         }
522
523         return 0;
524 }
525
526 /**
527  * Change virtual leakage voltage to actual value.
528  *
529  * @param     hwmgr  the address of the powerplay hardware manager.
530  * @param     pointer to changing voltage
531  * @param     pointer to leakage table
532  */
533 static void vega10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
534                 uint16_t *voltage, struct vega10_leakage_voltage *leakage_table)
535 {
536         uint32_t index;
537
538         /* search for leakage voltage ID 0xff01 ~ 0xff08 */
539         for (index = 0; index < leakage_table->count; index++) {
540                 /* if this voltage matches a leakage voltage ID */
541                 /* patch with actual leakage voltage */
542                 if (leakage_table->leakage_id[index] == *voltage) {
543                         *voltage = leakage_table->actual_voltage[index];
544                         break;
545                 }
546         }
547
548         if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
549                 pr_info("Voltage value looks like a Leakage ID \
550                                 but it's not patched\n");
551 }
552
553 /**
554 * Patch voltage lookup table by EVV leakages.
555 *
556 * @param     hwmgr  the address of the powerplay hardware manager.
557 * @param     pointer to voltage lookup table
558 * @param     pointer to leakage table
559 * @return     always 0
560 */
561 static int vega10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
562                 phm_ppt_v1_voltage_lookup_table *lookup_table,
563                 struct vega10_leakage_voltage *leakage_table)
564 {
565         uint32_t i;
566
567         for (i = 0; i < lookup_table->count; i++)
568                 vega10_patch_with_vdd_leakage(hwmgr,
569                                 &lookup_table->entries[i].us_vdd, leakage_table);
570
571         return 0;
572 }
573
574 static int vega10_patch_clock_voltage_limits_with_vddc_leakage(
575                 struct pp_hwmgr *hwmgr, struct vega10_leakage_voltage *leakage_table,
576                 uint16_t *vddc)
577 {
578         vega10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
579
580         return 0;
581 }
582 #endif
583
584 static int vega10_patch_voltage_dependency_tables_with_lookup_table(
585                 struct pp_hwmgr *hwmgr)
586 {
587         uint8_t entry_id, voltage_id;
588         unsigned i;
589         struct phm_ppt_v2_information *table_info =
590                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
591         struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
592                         table_info->mm_dep_table;
593         struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
594                         table_info->vdd_dep_on_mclk;
595
596         for (i = 0; i < 6; i++) {
597                 struct phm_ppt_v1_clock_voltage_dependency_table *vdt;
598                 switch (i) {
599                         case 0: vdt = table_info->vdd_dep_on_socclk; break;
600                         case 1: vdt = table_info->vdd_dep_on_sclk; break;
601                         case 2: vdt = table_info->vdd_dep_on_dcefclk; break;
602                         case 3: vdt = table_info->vdd_dep_on_pixclk; break;
603                         case 4: vdt = table_info->vdd_dep_on_dispclk; break;
604                         case 5: vdt = table_info->vdd_dep_on_phyclk; break;
605                 }
606
607                 for (entry_id = 0; entry_id < vdt->count; entry_id++) {
608                         voltage_id = vdt->entries[entry_id].vddInd;
609                         vdt->entries[entry_id].vddc =
610                                         table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
611                 }
612         }
613
614         for (entry_id = 0; entry_id < mm_table->count; ++entry_id) {
615                 voltage_id = mm_table->entries[entry_id].vddcInd;
616                 mm_table->entries[entry_id].vddc =
617                         table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
618         }
619
620         for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) {
621                 voltage_id = mclk_table->entries[entry_id].vddInd;
622                 mclk_table->entries[entry_id].vddc =
623                                 table_info->vddc_lookup_table->entries[voltage_id].us_vdd;
624                 voltage_id = mclk_table->entries[entry_id].vddciInd;
625                 mclk_table->entries[entry_id].vddci =
626                                 table_info->vddci_lookup_table->entries[voltage_id].us_vdd;
627                 voltage_id = mclk_table->entries[entry_id].mvddInd;
628                 mclk_table->entries[entry_id].mvdd =
629                                 table_info->vddmem_lookup_table->entries[voltage_id].us_vdd;
630         }
631
632
633         return 0;
634
635 }
636
637 static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr,
638                 struct phm_ppt_v1_voltage_lookup_table *lookup_table)
639 {
640         uint32_t table_size, i, j;
641         struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
642
643         PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count,
644                 "Lookup table is empty", return -EINVAL);
645
646         table_size = lookup_table->count;
647
648         /* Sorting voltages */
649         for (i = 0; i < table_size - 1; i++) {
650                 for (j = i + 1; j > 0; j--) {
651                         if (lookup_table->entries[j].us_vdd <
652                                         lookup_table->entries[j - 1].us_vdd) {
653                                 tmp_voltage_lookup_record = lookup_table->entries[j - 1];
654                                 lookup_table->entries[j - 1] = lookup_table->entries[j];
655                                 lookup_table->entries[j] = tmp_voltage_lookup_record;
656                         }
657                 }
658         }
659
660         return 0;
661 }
662
663 static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr)
664 {
665         int result = 0;
666         int tmp_result;
667         struct phm_ppt_v2_information *table_info =
668                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
669 #ifdef PPLIB_VEGA10_EVV_SUPPORT
670         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
671
672         tmp_result = vega10_patch_lookup_table_with_leakage(hwmgr,
673                         table_info->vddc_lookup_table, &(data->vddc_leakage));
674         if (tmp_result)
675                 result = tmp_result;
676
677         tmp_result = vega10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
678                         &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
679         if (tmp_result)
680                 result = tmp_result;
681 #endif
682
683         tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
684         if (tmp_result)
685                 result = tmp_result;
686
687         tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
688         if (tmp_result)
689                 result = tmp_result;
690
691         return result;
692 }
693
694 static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
695 {
696         struct phm_ppt_v2_information *table_info =
697                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
698         struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
699                         table_info->vdd_dep_on_socclk;
700         struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
701                         table_info->vdd_dep_on_mclk;
702
703         PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table,
704                 "VDD dependency on SCLK table is missing. \
705                 This table is mandatory", return -EINVAL);
706         PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
707                 "VDD dependency on SCLK table is empty. \
708                 This table is mandatory", return -EINVAL);
709
710         PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table,
711                 "VDD dependency on MCLK table is missing. \
712                 This table is mandatory", return -EINVAL);
713         PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
714                 "VDD dependency on MCLK table is empty. \
715                 This table is mandatory", return -EINVAL);
716
717         table_info->max_clock_voltage_on_ac.sclk =
718                 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
719         table_info->max_clock_voltage_on_ac.mclk =
720                 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
721         table_info->max_clock_voltage_on_ac.vddc =
722                 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
723         table_info->max_clock_voltage_on_ac.vddci =
724                 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
725
726         hwmgr->dyn_state.max_clock_voltage_on_ac.sclk =
727                 table_info->max_clock_voltage_on_ac.sclk;
728         hwmgr->dyn_state.max_clock_voltage_on_ac.mclk =
729                 table_info->max_clock_voltage_on_ac.mclk;
730         hwmgr->dyn_state.max_clock_voltage_on_ac.vddc =
731                 table_info->max_clock_voltage_on_ac.vddc;
732         hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =
733                 table_info->max_clock_voltage_on_ac.vddci;
734
735         return 0;
736 }
737
738 static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
739 {
740         kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
741         hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
742
743         kfree(hwmgr->backend);
744         hwmgr->backend = NULL;
745
746         return 0;
747 }
748
749 static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
750 {
751         int result = 0;
752         struct vega10_hwmgr *data;
753         uint32_t config_telemetry = 0;
754         struct pp_atomfwctrl_voltage_table vol_table;
755         struct cgs_system_info sys_info = {0};
756
757         data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL);
758         if (data == NULL)
759                 return -ENOMEM;
760
761         hwmgr->backend = data;
762
763         vega10_set_default_registry_data(hwmgr);
764
765         data->disable_dpm_mask = 0xff;
766         data->workload_mask = 0xff;
767
768         /* need to set voltage control types before EVV patching */
769         data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
770         data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE;
771         data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE;
772
773         /* VDDCR_SOC */
774         if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
775                         VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
776                 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
777                                 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2,
778                                 &vol_table)) {
779                         config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) |
780                                         (vol_table.telemetry_offset & 0xff);
781                         data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
782                 }
783         } else {
784                 kfree(hwmgr->backend);
785                 hwmgr->backend = NULL;
786                 PP_ASSERT_WITH_CODE(false,
787                                 "VDDCR_SOC is not SVID2!",
788                                 return -1);
789         }
790
791         /* MVDDC */
792         if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
793                         VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) {
794                 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr,
795                                 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2,
796                                 &vol_table)) {
797                         config_telemetry |=
798                                         ((vol_table.telemetry_slope << 24) & 0xff000000) |
799                                         ((vol_table.telemetry_offset << 16) & 0xff0000);
800                         data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2;
801                 }
802         }
803
804          /* VDDCI_MEM */
805         if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) {
806                 if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr,
807                                 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
808                         data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO;
809         }
810
811         data->config_telemetry = config_telemetry;
812
813         vega10_set_features_platform_caps(hwmgr);
814
815         vega10_init_dpm_defaults(hwmgr);
816
817 #ifdef PPLIB_VEGA10_EVV_SUPPORT
818         /* Get leakage voltage based on leakage ID. */
819         PP_ASSERT_WITH_CODE(!vega10_get_evv_voltages(hwmgr),
820                         "Get EVV Voltage Failed.  Abort Driver loading!",
821                         return -1);
822 #endif
823
824         /* Patch our voltage dependency table with actual leakage voltage
825          * We need to perform leakage translation before it's used by other functions
826          */
827         vega10_complete_dependency_tables(hwmgr);
828
829         /* Parse pptable data read from VBIOS */
830         vega10_set_private_data_based_on_pptable(hwmgr);
831
832         data->is_tlu_enabled = false;
833
834         hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
835                         VEGA10_MAX_HARDWARE_POWERLEVELS;
836         hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
837         hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
838
839         hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
840         /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
841         hwmgr->platform_descriptor.clockStep.engineClock = 500;
842         hwmgr->platform_descriptor.clockStep.memoryClock = 500;
843
844         sys_info.size = sizeof(struct cgs_system_info);
845         sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
846         result = cgs_query_system_info(hwmgr->device, &sys_info);
847         data->total_active_cus = sys_info.value;
848         /* Setup default Overdrive Fan control settings */
849         data->odn_fan_table.target_fan_speed =
850                         hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
851         data->odn_fan_table.target_temperature =
852                         hwmgr->thermal_controller.
853                         advanceFanControlParameters.ucTargetTemperature;
854         data->odn_fan_table.min_performance_clock =
855                         hwmgr->thermal_controller.advanceFanControlParameters.
856                         ulMinFanSCLKAcousticLimit;
857         data->odn_fan_table.min_fan_limit =
858                         hwmgr->thermal_controller.
859                         advanceFanControlParameters.usFanPWMMinLimit *
860                         hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100;
861
862         return result;
863 }
864
865 static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr)
866 {
867         struct vega10_hwmgr *data =
868                         (struct vega10_hwmgr *)(hwmgr->backend);
869
870         data->low_sclk_interrupt_threshold = 0;
871
872         return 0;
873 }
874
875 static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
876 {
877         struct vega10_hwmgr *data =
878                         (struct vega10_hwmgr *)(hwmgr->backend);
879         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
880
881         struct pp_atomfwctrl_voltage_table table;
882         uint8_t i, j;
883         uint32_t mask = 0;
884         uint32_t tmp;
885         int32_t ret = 0;
886
887         ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM,
888                                                 VOLTAGE_OBJ_GPIO_LUT, &table);
889
890         if (!ret) {
891                 tmp = table.mask_low;
892                 for (i = 0, j = 0; i < 32; i++) {
893                         if (tmp & 1) {
894                                 mask |= (uint32_t)(i << (8 * j));
895                                 if (++j >= 3)
896                                         break;
897                         }
898                         tmp >>= 1;
899                 }
900         }
901
902         pp_table->LedPin0 = (uint8_t)(mask & 0xff);
903         pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff);
904         pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff);
905         return 0;
906 }
907
908 static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr)
909 {
910         PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr),
911                         "Failed to init sclk threshold!",
912                         return -EINVAL);
913
914         PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr),
915                         "Failed to set up led dpm config!",
916                         return -EINVAL);
917
918         return 0;
919 }
920
921 static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
922 {
923         uint32_t features_enabled;
924
925         if (!vega10_get_smc_features(hwmgr->smumgr, &features_enabled)) {
926                 if (features_enabled & SMC_DPM_FEATURES)
927                         return true;
928         }
929         return false;
930 }
931
932 /**
933 * Remove repeated voltage values and create table with unique values.
934 *
935 * @param    hwmgr  the address of the powerplay hardware manager.
936 * @param    vol_table  the pointer to changing voltage table
937 * @return    0 in success
938 */
939
940 static int vega10_trim_voltage_table(struct pp_hwmgr *hwmgr,
941                 struct pp_atomfwctrl_voltage_table *vol_table)
942 {
943         uint32_t i, j;
944         uint16_t vvalue;
945         bool found = false;
946         struct pp_atomfwctrl_voltage_table *table;
947
948         PP_ASSERT_WITH_CODE(vol_table,
949                         "Voltage Table empty.", return -EINVAL);
950         table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table),
951                         GFP_KERNEL);
952
953         if (!table)
954                 return -ENOMEM;
955
956         table->mask_low = vol_table->mask_low;
957         table->phase_delay = vol_table->phase_delay;
958
959         for (i = 0; i < vol_table->count; i++) {
960                 vvalue = vol_table->entries[i].value;
961                 found = false;
962
963                 for (j = 0; j < table->count; j++) {
964                         if (vvalue == table->entries[j].value) {
965                                 found = true;
966                                 break;
967                         }
968                 }
969
970                 if (!found) {
971                         table->entries[table->count].value = vvalue;
972                         table->entries[table->count].smio_low =
973                                         vol_table->entries[i].smio_low;
974                         table->count++;
975                 }
976         }
977
978         memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table));
979         kfree(table);
980
981         return 0;
982 }
983
984 static int vega10_get_mvdd_voltage_table(struct pp_hwmgr *hwmgr,
985                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
986                 struct pp_atomfwctrl_voltage_table *vol_table)
987 {
988         int i;
989
990         PP_ASSERT_WITH_CODE(dep_table->count,
991                         "Voltage Dependency Table empty.",
992                         return -EINVAL);
993
994         vol_table->mask_low = 0;
995         vol_table->phase_delay = 0;
996         vol_table->count = dep_table->count;
997
998         for (i = 0; i < vol_table->count; i++) {
999                 vol_table->entries[i].value = dep_table->entries[i].mvdd;
1000                 vol_table->entries[i].smio_low = 0;
1001         }
1002
1003         PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr,
1004                         vol_table),
1005                         "Failed to trim MVDD Table!",
1006                         return -1);
1007
1008         return 0;
1009 }
1010
1011 static int vega10_get_vddci_voltage_table(struct pp_hwmgr *hwmgr,
1012                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
1013                 struct pp_atomfwctrl_voltage_table *vol_table)
1014 {
1015         uint32_t i;
1016
1017         PP_ASSERT_WITH_CODE(dep_table->count,
1018                         "Voltage Dependency Table empty.",
1019                         return -EINVAL);
1020
1021         vol_table->mask_low = 0;
1022         vol_table->phase_delay = 0;
1023         vol_table->count = dep_table->count;
1024
1025         for (i = 0; i < dep_table->count; i++) {
1026                 vol_table->entries[i].value = dep_table->entries[i].vddci;
1027                 vol_table->entries[i].smio_low = 0;
1028         }
1029
1030         PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, vol_table),
1031                         "Failed to trim VDDCI table.",
1032                         return -1);
1033
1034         return 0;
1035 }
1036
1037 static int vega10_get_vdd_voltage_table(struct pp_hwmgr *hwmgr,
1038                 phm_ppt_v1_clock_voltage_dependency_table *dep_table,
1039                 struct pp_atomfwctrl_voltage_table *vol_table)
1040 {
1041         int i;
1042
1043         PP_ASSERT_WITH_CODE(dep_table->count,
1044                         "Voltage Dependency Table empty.",
1045                         return -EINVAL);
1046
1047         vol_table->mask_low = 0;
1048         vol_table->phase_delay = 0;
1049         vol_table->count = dep_table->count;
1050
1051         for (i = 0; i < vol_table->count; i++) {
1052                 vol_table->entries[i].value = dep_table->entries[i].vddc;
1053                 vol_table->entries[i].smio_low = 0;
1054         }
1055
1056         return 0;
1057 }
1058
1059 /* ---- Voltage Tables ----
1060  * If the voltage table would be bigger than
1061  * what will fit into the state table on
1062  * the SMC keep only the higher entries.
1063  */
1064 static void vega10_trim_voltage_table_to_fit_state_table(
1065                 struct pp_hwmgr *hwmgr,
1066                 uint32_t max_vol_steps,
1067                 struct pp_atomfwctrl_voltage_table *vol_table)
1068 {
1069         unsigned int i, diff;
1070
1071         if (vol_table->count <= max_vol_steps)
1072                 return;
1073
1074         diff = vol_table->count - max_vol_steps;
1075
1076         for (i = 0; i < max_vol_steps; i++)
1077                 vol_table->entries[i] = vol_table->entries[i + diff];
1078
1079         vol_table->count = max_vol_steps;
1080 }
1081
1082 /**
1083 * Create Voltage Tables.
1084 *
1085 * @param    hwmgr  the address of the powerplay hardware manager.
1086 * @return   always 0
1087 */
1088 static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr)
1089 {
1090         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
1091         struct phm_ppt_v2_information *table_info =
1092                         (struct phm_ppt_v2_information *)hwmgr->pptable;
1093         int result;
1094
1095         if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
1096                         data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1097                 result = vega10_get_mvdd_voltage_table(hwmgr,
1098                                 table_info->vdd_dep_on_mclk,
1099                                 &(data->mvdd_voltage_table));
1100                 PP_ASSERT_WITH_CODE(!result,
1101                                 "Failed to retrieve MVDDC table!",
1102                                 return result);
1103         }
1104
1105         if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1106                 result = vega10_get_vddci_voltage_table(hwmgr,
1107                                 table_info->vdd_dep_on_mclk,
1108                                 &(data->vddci_voltage_table));
1109                 PP_ASSERT_WITH_CODE(!result,
1110                                 "Failed to retrieve VDDCI_MEM table!",
1111                                 return result);
1112         }
1113
1114         if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 ||
1115                         data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) {
1116                 result = vega10_get_vdd_voltage_table(hwmgr,
1117                                 table_info->vdd_dep_on_sclk,
1118                                 &(data->vddc_voltage_table));
1119                 PP_ASSERT_WITH_CODE(!result,
1120                                 "Failed to retrieve VDDCR_SOC table!",
1121                                 return result);
1122         }
1123
1124         PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 16,
1125                         "Too many voltage values for VDDC. Trimming to fit state table.",
1126                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1127                                         16, &(data->vddc_voltage_table)));
1128
1129         PP_ASSERT_WITH_CODE(data->vddci_voltage_table.count <= 16,
1130                         "Too many voltage values for VDDCI. Trimming to fit state table.",
1131                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1132                                         16, &(data->vddci_voltage_table)));
1133
1134         PP_ASSERT_WITH_CODE(data->mvdd_voltage_table.count <= 16,
1135                         "Too many voltage values for MVDD. Trimming to fit state table.",
1136                         vega10_trim_voltage_table_to_fit_state_table(hwmgr,
1137                                         16, &(data->mvdd_voltage_table)));
1138
1139
1140         return 0;
1141 }
1142
1143 /*
1144  * @fn vega10_init_dpm_state
1145  * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
1146  *
1147  * @param    dpm_state - the address of the DPM Table to initiailize.
1148  * @return   None.
1149  */
1150 static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state)
1151 {
1152         dpm_state->soft_min_level = 0xff;
1153         dpm_state->soft_max_level = 0xff;
1154         dpm_state->hard_min_level = 0xff;
1155         dpm_state->hard_max_level = 0xff;
1156 }
1157
1158 static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr,
1159                 struct vega10_single_dpm_table *dpm_table,
1160                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
1161 {
1162         int i;
1163
1164         for (i = 0; i < dep_table->count; i++) {
1165                 if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <=
1166                                 dep_table->entries[i].clk) {
1167                         dpm_table->dpm_levels[dpm_table->count].value =
1168                                         dep_table->entries[i].clk;
1169                         dpm_table->dpm_levels[dpm_table->count].enabled = true;
1170                         dpm_table->count++;
1171                 }
1172         }
1173 }
1174 static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
1175 {
1176         struct vega10_hwmgr *data =
1177                         (struct vega10_hwmgr *)(hwmgr->backend);
1178         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
1179         struct phm_ppt_v2_information *table_info =
1180                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1181         struct phm_ppt_v1_pcie_table *bios_pcie_table =
1182                         table_info->pcie_table;
1183         uint32_t i;
1184
1185         PP_ASSERT_WITH_CODE(bios_pcie_table->count,
1186                         "Incorrect number of PCIE States from VBIOS!",
1187                         return -1);
1188
1189         for (i = 0; i < NUM_LINK_LEVELS; i++) {
1190                 if (data->registry_data.pcieSpeedOverride)
1191                         pcie_table->pcie_gen[i] =
1192                                         data->registry_data.pcieSpeedOverride;
1193                 else
1194                         pcie_table->pcie_gen[i] =
1195                                         bios_pcie_table->entries[i].gen_speed;
1196
1197                 if (data->registry_data.pcieLaneOverride)
1198                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1199                                         data->registry_data.pcieLaneOverride);
1200                 else
1201                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1202                                                         bios_pcie_table->entries[i].lane_width);
1203                 if (data->registry_data.pcieClockOverride)
1204                         pcie_table->lclk[i] =
1205                                         data->registry_data.pcieClockOverride;
1206                 else
1207                         pcie_table->lclk[i] =
1208                                         bios_pcie_table->entries[i].pcie_sclk;
1209         }
1210
1211         pcie_table->count = NUM_LINK_LEVELS;
1212
1213         return 0;
1214 }
1215
1216 /*
1217  * This function is to initialize all DPM state tables
1218  * for SMU based on the dependency table.
1219  * Dynamic state patching function will then trim these
1220  * state tables to the allowed range based
1221  * on the power policy or external client requests,
1222  * such as UVD request, etc.
1223  */
1224 static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1225 {
1226         struct vega10_hwmgr *data =
1227                         (struct vega10_hwmgr *)(hwmgr->backend);
1228         struct phm_ppt_v2_information *table_info =
1229                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1230         struct vega10_single_dpm_table *dpm_table;
1231         uint32_t i;
1232
1233         struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table =
1234                         table_info->vdd_dep_on_socclk;
1235         struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table =
1236                         table_info->vdd_dep_on_sclk;
1237         struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
1238                         table_info->vdd_dep_on_mclk;
1239         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table =
1240                         table_info->mm_dep_table;
1241         struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table =
1242                         table_info->vdd_dep_on_dcefclk;
1243         struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table =
1244                         table_info->vdd_dep_on_pixclk;
1245         struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table =
1246                         table_info->vdd_dep_on_dispclk;
1247         struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table =
1248                         table_info->vdd_dep_on_phyclk;
1249
1250         PP_ASSERT_WITH_CODE(dep_soc_table,
1251                         "SOCCLK dependency table is missing. This table is mandatory",
1252                         return -EINVAL);
1253         PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1,
1254                         "SOCCLK dependency table is empty. This table is mandatory",
1255                         return -EINVAL);
1256
1257         PP_ASSERT_WITH_CODE(dep_gfx_table,
1258                         "GFXCLK dependency table is missing. This table is mandatory",
1259                         return -EINVAL);
1260         PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1,
1261                         "GFXCLK dependency table is empty. This table is mandatory",
1262                         return -EINVAL);
1263
1264         PP_ASSERT_WITH_CODE(dep_mclk_table,
1265                         "MCLK dependency table is missing. This table is mandatory",
1266                         return -EINVAL);
1267         PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
1268                         "MCLK dependency table has to have is missing. This table is mandatory",
1269                         return -EINVAL);
1270
1271         /* Initialize Sclk DPM table based on allow Sclk values */
1272         data->dpm_table.soc_table.count = 0;
1273         data->dpm_table.gfx_table.count = 0;
1274         data->dpm_table.dcef_table.count = 0;
1275
1276         dpm_table = &(data->dpm_table.soc_table);
1277         vega10_setup_default_single_dpm_table(hwmgr,
1278                         dpm_table,
1279                         dep_soc_table);
1280
1281         vega10_init_dpm_state(&(dpm_table->dpm_state));
1282
1283         dpm_table = &(data->dpm_table.gfx_table);
1284         vega10_setup_default_single_dpm_table(hwmgr,
1285                         dpm_table,
1286                         dep_gfx_table);
1287         vega10_init_dpm_state(&(dpm_table->dpm_state));
1288
1289         /* Initialize Mclk DPM table based on allow Mclk values */
1290         data->dpm_table.mem_table.count = 0;
1291         dpm_table = &(data->dpm_table.mem_table);
1292         vega10_setup_default_single_dpm_table(hwmgr,
1293                         dpm_table,
1294                         dep_mclk_table);
1295         vega10_init_dpm_state(&(dpm_table->dpm_state));
1296
1297         data->dpm_table.eclk_table.count = 0;
1298         dpm_table = &(data->dpm_table.eclk_table);
1299         for (i = 0; i < dep_mm_table->count; i++) {
1300                 if (i == 0 || dpm_table->dpm_levels
1301                                 [dpm_table->count - 1].value <=
1302                                                 dep_mm_table->entries[i].eclk) {
1303                         dpm_table->dpm_levels[dpm_table->count].value =
1304                                         dep_mm_table->entries[i].eclk;
1305                         dpm_table->dpm_levels[dpm_table->count].enabled =
1306                                         (i == 0) ? true : false;
1307                         dpm_table->count++;
1308                 }
1309         }
1310         vega10_init_dpm_state(&(dpm_table->dpm_state));
1311
1312         data->dpm_table.vclk_table.count = 0;
1313         data->dpm_table.dclk_table.count = 0;
1314         dpm_table = &(data->dpm_table.vclk_table);
1315         for (i = 0; i < dep_mm_table->count; i++) {
1316                 if (i == 0 || dpm_table->dpm_levels
1317                                 [dpm_table->count - 1].value <=
1318                                                 dep_mm_table->entries[i].vclk) {
1319                         dpm_table->dpm_levels[dpm_table->count].value =
1320                                         dep_mm_table->entries[i].vclk;
1321                         dpm_table->dpm_levels[dpm_table->count].enabled =
1322                                         (i == 0) ? true : false;
1323                         dpm_table->count++;
1324                 }
1325         }
1326         vega10_init_dpm_state(&(dpm_table->dpm_state));
1327
1328         dpm_table = &(data->dpm_table.dclk_table);
1329         for (i = 0; i < dep_mm_table->count; i++) {
1330                 if (i == 0 || dpm_table->dpm_levels
1331                                 [dpm_table->count - 1].value <=
1332                                                 dep_mm_table->entries[i].dclk) {
1333                         dpm_table->dpm_levels[dpm_table->count].value =
1334                                         dep_mm_table->entries[i].dclk;
1335                         dpm_table->dpm_levels[dpm_table->count].enabled =
1336                                         (i == 0) ? true : false;
1337                         dpm_table->count++;
1338                 }
1339         }
1340         vega10_init_dpm_state(&(dpm_table->dpm_state));
1341
1342         /* Assume there is no headless Vega10 for now */
1343         dpm_table = &(data->dpm_table.dcef_table);
1344         vega10_setup_default_single_dpm_table(hwmgr,
1345                         dpm_table,
1346                         dep_dcef_table);
1347
1348         vega10_init_dpm_state(&(dpm_table->dpm_state));
1349
1350         dpm_table = &(data->dpm_table.pixel_table);
1351         vega10_setup_default_single_dpm_table(hwmgr,
1352                         dpm_table,
1353                         dep_pix_table);
1354
1355         vega10_init_dpm_state(&(dpm_table->dpm_state));
1356
1357         dpm_table = &(data->dpm_table.display_table);
1358         vega10_setup_default_single_dpm_table(hwmgr,
1359                         dpm_table,
1360                         dep_disp_table);
1361
1362         vega10_init_dpm_state(&(dpm_table->dpm_state));
1363
1364         dpm_table = &(data->dpm_table.phy_table);
1365         vega10_setup_default_single_dpm_table(hwmgr,
1366                         dpm_table,
1367                         dep_phy_table);
1368
1369         vega10_init_dpm_state(&(dpm_table->dpm_state));
1370
1371         vega10_setup_default_pcie_table(hwmgr);
1372
1373         /* save a copy of the default DPM table */
1374         memcpy(&(data->golden_dpm_table), &(data->dpm_table),
1375                         sizeof(struct vega10_dpm_table));
1376
1377         if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) ||
1378             PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) {
1379                 data->odn_dpm_table.odn_core_clock_dpm_levels.
1380                 number_of_performance_levels = data->dpm_table.gfx_table.count;
1381                 for (i = 0; i < data->dpm_table.gfx_table.count; i++) {
1382                         data->odn_dpm_table.odn_core_clock_dpm_levels.
1383                         performance_level_entries[i].clock =
1384                                         data->dpm_table.gfx_table.dpm_levels[i].value;
1385                         data->odn_dpm_table.odn_core_clock_dpm_levels.
1386                         performance_level_entries[i].enabled = true;
1387                 }
1388
1389                 data->odn_dpm_table.vdd_dependency_on_sclk.count =
1390                                 dep_gfx_table->count;
1391                 for (i = 0; i < dep_gfx_table->count; i++) {
1392                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].clk =
1393                                         dep_gfx_table->entries[i].clk;
1394                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].vddInd =
1395                                         dep_gfx_table->entries[i].vddInd;
1396                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_enable =
1397                                         dep_gfx_table->entries[i].cks_enable;
1398                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_voffset =
1399                                         dep_gfx_table->entries[i].cks_voffset;
1400                 }
1401
1402                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
1403                 number_of_performance_levels = data->dpm_table.mem_table.count;
1404                 for (i = 0; i < data->dpm_table.mem_table.count; i++) {
1405                         data->odn_dpm_table.odn_memory_clock_dpm_levels.
1406                         performance_level_entries[i].clock =
1407                                         data->dpm_table.mem_table.dpm_levels[i].value;
1408                         data->odn_dpm_table.odn_memory_clock_dpm_levels.
1409                         performance_level_entries[i].enabled = true;
1410                 }
1411
1412                 data->odn_dpm_table.vdd_dependency_on_mclk.count = dep_mclk_table->count;
1413                 for (i = 0; i < dep_mclk_table->count; i++) {
1414                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].clk =
1415                                         dep_mclk_table->entries[i].clk;
1416                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddInd =
1417                                         dep_mclk_table->entries[i].vddInd;
1418                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddci =
1419                                         dep_mclk_table->entries[i].vddci;
1420                 }
1421         }
1422
1423         return 0;
1424 }
1425
1426 /*
1427  * @fn vega10_populate_ulv_state
1428  * @brief Function to provide parameters for Utral Low Voltage state to SMC.
1429  *
1430  * @param    hwmgr - the address of the hardware manager.
1431  * @return   Always 0.
1432  */
1433 static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr)
1434 {
1435         struct vega10_hwmgr *data =
1436                         (struct vega10_hwmgr *)(hwmgr->backend);
1437         struct phm_ppt_v2_information *table_info =
1438                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1439
1440         data->smc_state_table.pp_table.UlvOffsetVid =
1441                         (uint8_t)table_info->us_ulv_voltage_offset;
1442
1443         data->smc_state_table.pp_table.UlvSmnclkDid =
1444                         (uint8_t)(table_info->us_ulv_smnclk_did);
1445         data->smc_state_table.pp_table.UlvMp1clkDid =
1446                         (uint8_t)(table_info->us_ulv_mp1clk_did);
1447         data->smc_state_table.pp_table.UlvGfxclkBypass =
1448                         (uint8_t)(table_info->us_ulv_gfxclk_bypass);
1449         data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 =
1450                         (uint8_t)(data->vddc_voltage_table.psi0_enable);
1451         data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 =
1452                         (uint8_t)(data->vddc_voltage_table.psi1_enable);
1453
1454         return 0;
1455 }
1456
1457 static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr,
1458                 uint32_t lclock, uint8_t *curr_lclk_did)
1459 {
1460         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1461
1462         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1463                         hwmgr,
1464                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1465                         lclock, &dividers),
1466                         "Failed to get LCLK clock settings from VBIOS!",
1467                         return -1);
1468
1469         *curr_lclk_did = dividers.ulDid;
1470
1471         return 0;
1472 }
1473
1474 static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
1475 {
1476         int result = -1;
1477         struct vega10_hwmgr *data =
1478                         (struct vega10_hwmgr *)(hwmgr->backend);
1479         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1480         struct vega10_pcie_table *pcie_table =
1481                         &(data->dpm_table.pcie_table);
1482         uint32_t i, j;
1483
1484         for (i = 0; i < pcie_table->count; i++) {
1485                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i];
1486                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i];
1487
1488                 result = vega10_populate_single_lclk_level(hwmgr,
1489                                 pcie_table->lclk[i], &(pp_table->LclkDid[i]));
1490                 if (result) {
1491                         pr_info("Populate LClock Level %d Failed!\n", i);
1492                         return result;
1493                 }
1494         }
1495
1496         j = i - 1;
1497         while (i < NUM_LINK_LEVELS) {
1498                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j];
1499                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j];
1500
1501                 result = vega10_populate_single_lclk_level(hwmgr,
1502                                 pcie_table->lclk[j], &(pp_table->LclkDid[i]));
1503                 if (result) {
1504                         pr_info("Populate LClock Level %d Failed!\n", i);
1505                         return result;
1506                 }
1507                 i++;
1508         }
1509
1510         return result;
1511 }
1512
1513 /**
1514 * Populates single SMC GFXSCLK structure using the provided engine clock
1515 *
1516 * @param    hwmgr      the address of the hardware manager
1517 * @param    gfx_clock  the GFX clock to use to populate the structure.
1518 * @param    current_gfxclk_level  location in PPTable for the SMC GFXCLK structure.
1519 */
1520
1521 static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr,
1522                 uint32_t gfx_clock, PllSetting_t *current_gfxclk_level,
1523                 uint32_t *acg_freq)
1524 {
1525         struct phm_ppt_v2_information *table_info =
1526                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1527         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk =
1528                         table_info->vdd_dep_on_sclk;
1529         struct vega10_hwmgr *data =
1530                         (struct vega10_hwmgr *)(hwmgr->backend);
1531         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1532         uint32_t gfx_max_clock =
1533                         hwmgr->platform_descriptor.overdriveLimit.engineClock;
1534         uint32_t i = 0;
1535
1536         if (data->apply_overdrive_next_settings_mask &
1537                         DPMTABLE_OD_UPDATE_VDDC)
1538                 dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1539                                                 &(data->odn_dpm_table.vdd_dependency_on_sclk);
1540
1541         PP_ASSERT_WITH_CODE(dep_on_sclk,
1542                         "Invalid SOC_VDD-GFX_CLK Dependency Table!",
1543                         return -EINVAL);
1544
1545         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK)
1546                 gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock;
1547         else {
1548                 for (i = 0; i < dep_on_sclk->count; i++) {
1549                         if (dep_on_sclk->entries[i].clk == gfx_clock)
1550                                 break;
1551                 }
1552                 PP_ASSERT_WITH_CODE(dep_on_sclk->count > i,
1553                                 "Cannot find gfx_clk in SOC_VDD-GFX_CLK!",
1554                                 return -EINVAL);
1555         }
1556
1557         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1558                         COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK,
1559                         gfx_clock, &dividers),
1560                         "Failed to get GFX Clock settings from VBIOS!",
1561                         return -EINVAL);
1562
1563         /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */
1564         current_gfxclk_level->FbMult =
1565                         cpu_to_le32(dividers.ulPll_fb_mult);
1566         /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */
1567         current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
1568         current_gfxclk_level->SsFbMult =
1569                         cpu_to_le32(dividers.ulPll_ss_fbsmult);
1570         current_gfxclk_level->SsSlewFrac =
1571                         cpu_to_le16(dividers.usPll_ss_slew_frac);
1572         current_gfxclk_level->Did = (uint8_t)(dividers.ulDid);
1573
1574         *acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */
1575
1576         return 0;
1577 }
1578
1579 /**
1580  * @brief Populates single SMC SOCCLK structure using the provided clock.
1581  *
1582  * @param    hwmgr - the address of the hardware manager.
1583  * @param    soc_clock - the SOC clock to use to populate the structure.
1584  * @param    current_socclk_level - location in PPTable for the SMC SOCCLK structure.
1585  * @return   0 on success..
1586  */
1587 static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr,
1588                 uint32_t soc_clock, uint8_t *current_soc_did,
1589                 uint8_t *current_vol_index)
1590 {
1591         struct phm_ppt_v2_information *table_info =
1592                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1593         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc =
1594                         table_info->vdd_dep_on_socclk;
1595         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1596         uint32_t i;
1597
1598         PP_ASSERT_WITH_CODE(dep_on_soc,
1599                         "Invalid SOC_VDD-SOC_CLK Dependency Table!",
1600                         return -EINVAL);
1601         for (i = 0; i < dep_on_soc->count; i++) {
1602                 if (dep_on_soc->entries[i].clk == soc_clock)
1603                         break;
1604         }
1605         PP_ASSERT_WITH_CODE(dep_on_soc->count > i,
1606                         "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table",
1607                         return -EINVAL);
1608         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1609                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1610                         soc_clock, &dividers),
1611                         "Failed to get SOC Clock settings from VBIOS!",
1612                         return -EINVAL);
1613
1614         *current_soc_did = (uint8_t)dividers.ulDid;
1615         *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd);
1616
1617         return 0;
1618 }
1619
1620 uint16_t vega10_locate_vddc_given_clock(struct pp_hwmgr *hwmgr,
1621                 uint32_t clk,
1622                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
1623 {
1624         uint16_t i;
1625
1626         for (i = 0; i < dep_table->count; i++) {
1627                 if (dep_table->entries[i].clk == clk)
1628                         return dep_table->entries[i].vddc;
1629         }
1630
1631         pr_info("[LocateVddcGivenClock] Cannot locate SOC Vddc for this clock!");
1632         return 0;
1633 }
1634
1635 /**
1636 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
1637 *
1638 * @param    hwmgr      the address of the hardware manager
1639 */
1640 static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
1641 {
1642         struct vega10_hwmgr *data =
1643                         (struct vega10_hwmgr *)(hwmgr->backend);
1644         struct phm_ppt_v2_information *table_info =
1645                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1646         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
1647                         table_info->vdd_dep_on_socclk;
1648         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1649         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
1650         int result = 0;
1651         uint32_t i, j;
1652
1653         for (i = 0; i < dpm_table->count; i++) {
1654                 result = vega10_populate_single_gfx_level(hwmgr,
1655                                 dpm_table->dpm_levels[i].value,
1656                                 &(pp_table->GfxclkLevel[i]),
1657                                 &(pp_table->AcgFreqTable[i]));
1658                 if (result)
1659                         return result;
1660         }
1661
1662         j = i - 1;
1663         while (i < NUM_GFXCLK_DPM_LEVELS) {
1664                 result = vega10_populate_single_gfx_level(hwmgr,
1665                                 dpm_table->dpm_levels[j].value,
1666                                 &(pp_table->GfxclkLevel[i]),
1667                                 &(pp_table->AcgFreqTable[i]));
1668                 if (result)
1669                         return result;
1670                 i++;
1671         }
1672
1673         pp_table->GfxclkSlewRate =
1674                         cpu_to_le16(table_info->us_gfxclk_slew_rate);
1675
1676         dpm_table = &(data->dpm_table.soc_table);
1677         for (i = 0; i < dpm_table->count; i++) {
1678                 pp_table->SocVid[i] =
1679                                 (uint8_t)convert_to_vid(
1680                                 vega10_locate_vddc_given_clock(hwmgr,
1681                                                 dpm_table->dpm_levels[i].value,
1682                                                 dep_table));
1683                 result = vega10_populate_single_soc_level(hwmgr,
1684                                 dpm_table->dpm_levels[i].value,
1685                                 &(pp_table->SocclkDid[i]),
1686                                 &(pp_table->SocDpmVoltageIndex[i]));
1687                 if (result)
1688                         return result;
1689         }
1690
1691         j = i - 1;
1692         while (i < NUM_SOCCLK_DPM_LEVELS) {
1693                 pp_table->SocVid[i] = pp_table->SocVid[j];
1694                 result = vega10_populate_single_soc_level(hwmgr,
1695                                 dpm_table->dpm_levels[j].value,
1696                                 &(pp_table->SocclkDid[i]),
1697                                 &(pp_table->SocDpmVoltageIndex[i]));
1698                 if (result)
1699                         return result;
1700                 i++;
1701         }
1702
1703         return result;
1704 }
1705
1706 /**
1707  * @brief Populates single SMC GFXCLK structure using the provided clock.
1708  *
1709  * @param    hwmgr - the address of the hardware manager.
1710  * @param    mem_clock - the memory clock to use to populate the structure.
1711  * @return   0 on success..
1712  */
1713 static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
1714                 uint32_t mem_clock, uint8_t *current_mem_vid,
1715                 PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind)
1716 {
1717         struct vega10_hwmgr *data =
1718                         (struct vega10_hwmgr *)(hwmgr->backend);
1719         struct phm_ppt_v2_information *table_info =
1720                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1721         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk =
1722                         table_info->vdd_dep_on_mclk;
1723         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1724         uint32_t mem_max_clock =
1725                         hwmgr->platform_descriptor.overdriveLimit.memoryClock;
1726         uint32_t i = 0;
1727
1728         if (data->apply_overdrive_next_settings_mask &
1729                         DPMTABLE_OD_UPDATE_VDDC)
1730                 dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1731                                         &data->odn_dpm_table.vdd_dependency_on_mclk;
1732
1733         PP_ASSERT_WITH_CODE(dep_on_mclk,
1734                         "Invalid SOC_VDD-UCLK Dependency Table!",
1735                         return -EINVAL);
1736
1737         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK)
1738                 mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock;
1739         else {
1740                 for (i = 0; i < dep_on_mclk->count; i++) {
1741                         if (dep_on_mclk->entries[i].clk == mem_clock)
1742                                 break;
1743                 }
1744                 PP_ASSERT_WITH_CODE(dep_on_mclk->count > i,
1745                                 "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!",
1746                                 return -EINVAL);
1747         }
1748
1749         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1750                         hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, &dividers),
1751                         "Failed to get UCLK settings from VBIOS!",
1752                         return -1);
1753
1754         *current_mem_vid =
1755                         (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd));
1756         *current_mem_soc_vind =
1757                         (uint8_t)(dep_on_mclk->entries[i].vddInd);
1758         current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult);
1759         current_memclk_level->Did = (uint8_t)(dividers.ulDid);
1760
1761         PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1,
1762                         "Invalid Divider ID!",
1763                         return -EINVAL);
1764
1765         return 0;
1766 }
1767
1768 /**
1769  * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states.
1770  *
1771  * @param    pHwMgr - the address of the hardware manager.
1772  * @return   PP_Result_OK on success.
1773  */
1774 static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1775 {
1776         struct vega10_hwmgr *data =
1777                         (struct vega10_hwmgr *)(hwmgr->backend);
1778         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1779         struct vega10_single_dpm_table *dpm_table =
1780                         &(data->dpm_table.mem_table);
1781         int result = 0;
1782         uint32_t i, j, reg, mem_channels;
1783
1784         for (i = 0; i < dpm_table->count; i++) {
1785                 result = vega10_populate_single_memory_level(hwmgr,
1786                                 dpm_table->dpm_levels[i].value,
1787                                 &(pp_table->MemVid[i]),
1788                                 &(pp_table->UclkLevel[i]),
1789                                 &(pp_table->MemSocVoltageIndex[i]));
1790                 if (result)
1791                         return result;
1792         }
1793
1794         j = i - 1;
1795         while (i < NUM_UCLK_DPM_LEVELS) {
1796                 result = vega10_populate_single_memory_level(hwmgr,
1797                                 dpm_table->dpm_levels[j].value,
1798                                 &(pp_table->MemVid[i]),
1799                                 &(pp_table->UclkLevel[i]),
1800                                 &(pp_table->MemSocVoltageIndex[i]));
1801                 if (result)
1802                         return result;
1803                 i++;
1804         }
1805
1806         reg = soc15_get_register_offset(DF_HWID, 0,
1807                         mmDF_CS_AON0_DramBaseAddress0_BASE_IDX,
1808                         mmDF_CS_AON0_DramBaseAddress0);
1809         mem_channels = (cgs_read_register(hwmgr->device, reg) &
1810                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
1811                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
1812         pp_table->NumMemoryChannels = cpu_to_le16(mem_channels);
1813         pp_table->MemoryChannelWidth =
1814                         cpu_to_le16(HBM_MEMORY_CHANNEL_WIDTH *
1815                                         channel_number[mem_channels]);
1816
1817         pp_table->LowestUclkReservedForUlv =
1818                         (uint8_t)(data->lowest_uclk_reserved_for_ulv);
1819
1820         return result;
1821 }
1822
1823 static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr,
1824                 DSPCLK_e disp_clock)
1825 {
1826         struct vega10_hwmgr *data =
1827                         (struct vega10_hwmgr *)(hwmgr->backend);
1828         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1829         struct phm_ppt_v2_information *table_info =
1830                         (struct phm_ppt_v2_information *)
1831                         (hwmgr->pptable);
1832         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
1833         uint32_t i;
1834         uint16_t clk = 0, vddc = 0;
1835         uint8_t vid = 0;
1836
1837         switch (disp_clock) {
1838         case DSPCLK_DCEFCLK:
1839                 dep_table = table_info->vdd_dep_on_dcefclk;
1840                 break;
1841         case DSPCLK_DISPCLK:
1842                 dep_table = table_info->vdd_dep_on_dispclk;
1843                 break;
1844         case DSPCLK_PIXCLK:
1845                 dep_table = table_info->vdd_dep_on_pixclk;
1846                 break;
1847         case DSPCLK_PHYCLK:
1848                 dep_table = table_info->vdd_dep_on_phyclk;
1849                 break;
1850         default:
1851                 return -1;
1852         }
1853
1854         PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS,
1855                         "Number Of Entries Exceeded maximum!",
1856                         return -1);
1857
1858         for (i = 0; i < dep_table->count; i++) {
1859                 clk = (uint16_t)(dep_table->entries[i].clk / 100);
1860                 vddc = table_info->vddc_lookup_table->
1861                                 entries[dep_table->entries[i].vddInd].us_vdd;
1862                 vid = (uint8_t)convert_to_vid(vddc);
1863                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1864                                 cpu_to_le16(clk);
1865                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1866                                 cpu_to_le16(vid);
1867         }
1868
1869         while (i < NUM_DSPCLK_LEVELS) {
1870                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1871                                 cpu_to_le16(clk);
1872                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1873                                 cpu_to_le16(vid);
1874                 i++;
1875         }
1876
1877         return 0;
1878 }
1879
1880 static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr)
1881 {
1882         uint32_t i;
1883
1884         for (i = 0; i < DSPCLK_COUNT; i++) {
1885                 PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i),
1886                                 "Failed to populate Clock in DisplayClockTable!",
1887                                 return -1);
1888         }
1889
1890         return 0;
1891 }
1892
1893 static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr,
1894                 uint32_t eclock, uint8_t *current_eclk_did,
1895                 uint8_t *current_soc_vol)
1896 {
1897         struct phm_ppt_v2_information *table_info =
1898                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1899         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1900                         table_info->mm_dep_table;
1901         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1902         uint32_t i;
1903
1904         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1905                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1906                         eclock, &dividers),
1907                         "Failed to get ECLK clock settings from VBIOS!",
1908                         return -1);
1909
1910         *current_eclk_did = (uint8_t)dividers.ulDid;
1911
1912         for (i = 0; i < dep_table->count; i++) {
1913                 if (dep_table->entries[i].eclk == eclock)
1914                         *current_soc_vol = dep_table->entries[i].vddcInd;
1915         }
1916
1917         return 0;
1918 }
1919
1920 static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr)
1921 {
1922         struct vega10_hwmgr *data =
1923                         (struct vega10_hwmgr *)(hwmgr->backend);
1924         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1925         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table);
1926         int result = -EINVAL;
1927         uint32_t i, j;
1928
1929         for (i = 0; i < dpm_table->count; i++) {
1930                 result = vega10_populate_single_eclock_level(hwmgr,
1931                                 dpm_table->dpm_levels[i].value,
1932                                 &(pp_table->EclkDid[i]),
1933                                 &(pp_table->VceDpmVoltageIndex[i]));
1934                 if (result)
1935                         return result;
1936         }
1937
1938         j = i - 1;
1939         while (i < NUM_VCE_DPM_LEVELS) {
1940                 result = vega10_populate_single_eclock_level(hwmgr,
1941                                 dpm_table->dpm_levels[j].value,
1942                                 &(pp_table->EclkDid[i]),
1943                                 &(pp_table->VceDpmVoltageIndex[i]));
1944                 if (result)
1945                         return result;
1946                 i++;
1947         }
1948
1949         return result;
1950 }
1951
1952 static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr,
1953                 uint32_t vclock, uint8_t *current_vclk_did)
1954 {
1955         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1956
1957         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1958                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1959                         vclock, &dividers),
1960                         "Failed to get VCLK clock settings from VBIOS!",
1961                         return -EINVAL);
1962
1963         *current_vclk_did = (uint8_t)dividers.ulDid;
1964
1965         return 0;
1966 }
1967
1968 static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr,
1969                 uint32_t dclock, uint8_t *current_dclk_did)
1970 {
1971         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1972
1973         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1974                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1975                         dclock, &dividers),
1976                         "Failed to get DCLK clock settings from VBIOS!",
1977                         return -EINVAL);
1978
1979         *current_dclk_did = (uint8_t)dividers.ulDid;
1980
1981         return 0;
1982 }
1983
1984 static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr)
1985 {
1986         struct vega10_hwmgr *data =
1987                         (struct vega10_hwmgr *)(hwmgr->backend);
1988         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1989         struct vega10_single_dpm_table *vclk_dpm_table =
1990                         &(data->dpm_table.vclk_table);
1991         struct vega10_single_dpm_table *dclk_dpm_table =
1992                         &(data->dpm_table.dclk_table);
1993         struct phm_ppt_v2_information *table_info =
1994                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1995         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1996                         table_info->mm_dep_table;
1997         int result = -EINVAL;
1998         uint32_t i, j;
1999
2000         for (i = 0; i < vclk_dpm_table->count; i++) {
2001                 result = vega10_populate_single_vclock_level(hwmgr,
2002                                 vclk_dpm_table->dpm_levels[i].value,
2003                                 &(pp_table->VclkDid[i]));
2004                 if (result)
2005                         return result;
2006         }
2007
2008         j = i - 1;
2009         while (i < NUM_UVD_DPM_LEVELS) {
2010                 result = vega10_populate_single_vclock_level(hwmgr,
2011                                 vclk_dpm_table->dpm_levels[j].value,
2012                                 &(pp_table->VclkDid[i]));
2013                 if (result)
2014                         return result;
2015                 i++;
2016         }
2017
2018         for (i = 0; i < dclk_dpm_table->count; i++) {
2019                 result = vega10_populate_single_dclock_level(hwmgr,
2020                                 dclk_dpm_table->dpm_levels[i].value,
2021                                 &(pp_table->DclkDid[i]));
2022                 if (result)
2023                         return result;
2024         }
2025
2026         j = i - 1;
2027         while (i < NUM_UVD_DPM_LEVELS) {
2028                 result = vega10_populate_single_dclock_level(hwmgr,
2029                                 dclk_dpm_table->dpm_levels[j].value,
2030                                 &(pp_table->DclkDid[i]));
2031                 if (result)
2032                         return result;
2033                 i++;
2034         }
2035
2036         for (i = 0; i < dep_table->count; i++) {
2037                 if (dep_table->entries[i].vclk ==
2038                                 vclk_dpm_table->dpm_levels[i].value &&
2039                         dep_table->entries[i].dclk ==
2040                                 dclk_dpm_table->dpm_levels[i].value)
2041                         pp_table->UvdDpmVoltageIndex[i] =
2042                                         dep_table->entries[i].vddcInd;
2043                 else
2044                         return -1;
2045         }
2046
2047         j = i - 1;
2048         while (i < NUM_UVD_DPM_LEVELS) {
2049                 pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd;
2050                 i++;
2051         }
2052
2053         return 0;
2054 }
2055
2056 static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr)
2057 {
2058         struct vega10_hwmgr *data =
2059                         (struct vega10_hwmgr *)(hwmgr->backend);
2060         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2061         struct phm_ppt_v2_information *table_info =
2062                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2063         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2064                         table_info->vdd_dep_on_sclk;
2065         uint32_t i;
2066
2067         for (i = 0; i < dep_table->count; i++) {
2068                 pp_table->CksEnable[i] = dep_table->entries[i].cks_enable;
2069                 pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset
2070                                 * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
2071         }
2072
2073         return 0;
2074 }
2075
2076 static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
2077 {
2078         struct vega10_hwmgr *data =
2079                         (struct vega10_hwmgr *)(hwmgr->backend);
2080         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2081         struct phm_ppt_v2_information *table_info =
2082                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2083         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2084                         table_info->vdd_dep_on_sclk;
2085         struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
2086         int result = 0;
2087         uint32_t i;
2088
2089         pp_table->MinVoltageVid = (uint8_t)0xff;
2090         pp_table->MaxVoltageVid = (uint8_t)0;
2091
2092         if (data->smu_features[GNLD_AVFS].supported) {
2093                 result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
2094                 if (!result) {
2095                         pp_table->MinVoltageVid = (uint8_t)
2096                                         convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
2097                         pp_table->MaxVoltageVid = (uint8_t)
2098                                         convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
2099
2100                         pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
2101                         pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
2102                         pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
2103                         pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2104                         pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
2105                         pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2106                         pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor);
2107
2108                         pp_table->BtcGbVdroopTableCksOff.a0 =
2109                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0);
2110                         pp_table->BtcGbVdroopTableCksOff.a0_shift = 20;
2111                         pp_table->BtcGbVdroopTableCksOff.a1 =
2112                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1);
2113                         pp_table->BtcGbVdroopTableCksOff.a1_shift = 20;
2114                         pp_table->BtcGbVdroopTableCksOff.a2 =
2115                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2);
2116                         pp_table->BtcGbVdroopTableCksOff.a2_shift = 20;
2117
2118                         pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson;
2119                         pp_table->BtcGbVdroopTableCksOn.a0 =
2120                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
2121                         pp_table->BtcGbVdroopTableCksOn.a0_shift = 20;
2122                         pp_table->BtcGbVdroopTableCksOn.a1 =
2123                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
2124                         pp_table->BtcGbVdroopTableCksOn.a1_shift = 20;
2125                         pp_table->BtcGbVdroopTableCksOn.a2 =
2126                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
2127                         pp_table->BtcGbVdroopTableCksOn.a2_shift = 20;
2128
2129                         pp_table->AvfsGbCksOn.m1 =
2130                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM1);
2131                         pp_table->AvfsGbCksOn.m2 =
2132                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM2);
2133                         pp_table->AvfsGbCksOn.b =
2134                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonB);
2135                         pp_table->AvfsGbCksOn.m1_shift = 24;
2136                         pp_table->AvfsGbCksOn.m2_shift = 12;
2137                         pp_table->AvfsGbCksOn.b_shift = 0;
2138
2139                         pp_table->OverrideAvfsGbCksOn =
2140                                         avfs_params.ucEnableGbFuseTableCkson;
2141                         pp_table->AvfsGbCksOff.m1 =
2142                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1);
2143                         pp_table->AvfsGbCksOff.m2 =
2144                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2);
2145                         pp_table->AvfsGbCksOff.b =
2146                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffB);
2147                         pp_table->AvfsGbCksOff.m1_shift = 24;
2148                         pp_table->AvfsGbCksOff.m2_shift = 12;
2149                         pp_table->AvfsGbCksOff.b_shift = 0;
2150
2151                         for (i = 0; i < dep_table->count; i++)
2152                                 pp_table->StaticVoltageOffsetVid[i] =
2153                                                 convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset));
2154
2155                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2156                                         data->disp_clk_quad_eqn_a) &&
2157                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2158                                         data->disp_clk_quad_eqn_b)) {
2159                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2160                                                 (int32_t)data->disp_clk_quad_eqn_a;
2161                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2162                                                 (int32_t)data->disp_clk_quad_eqn_b;
2163                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2164                                                 (int32_t)data->disp_clk_quad_eqn_c;
2165                         } else {
2166                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2167                                                 (int32_t)avfs_params.ulDispclk2GfxclkM1;
2168                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2169                                                 (int32_t)avfs_params.ulDispclk2GfxclkM2;
2170                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2171                                                 (int32_t)avfs_params.ulDispclk2GfxclkB;
2172                         }
2173
2174                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24;
2175                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12;
2176                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12;
2177
2178                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2179                                         data->dcef_clk_quad_eqn_a) &&
2180                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2181                                         data->dcef_clk_quad_eqn_b)) {
2182                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2183                                                 (int32_t)data->dcef_clk_quad_eqn_a;
2184                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2185                                                 (int32_t)data->dcef_clk_quad_eqn_b;
2186                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2187                                                 (int32_t)data->dcef_clk_quad_eqn_c;
2188                         } else {
2189                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2190                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM1;
2191                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2192                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM2;
2193                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2194                                                 (int32_t)avfs_params.ulDcefclk2GfxclkB;
2195                         }
2196
2197                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24;
2198                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12;
2199                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12;
2200
2201                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2202                                         data->pixel_clk_quad_eqn_a) &&
2203                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2204                                         data->pixel_clk_quad_eqn_b)) {
2205                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2206                                                 (int32_t)data->pixel_clk_quad_eqn_a;
2207                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2208                                                 (int32_t)data->pixel_clk_quad_eqn_b;
2209                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2210                                                 (int32_t)data->pixel_clk_quad_eqn_c;
2211                         } else {
2212                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2213                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM1;
2214                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2215                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM2;
2216                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2217                                                 (int32_t)avfs_params.ulPixelclk2GfxclkB;
2218                         }
2219
2220                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24;
2221                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12;
2222                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12;
2223                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2224                                         data->phy_clk_quad_eqn_a) &&
2225                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2226                                         data->phy_clk_quad_eqn_b)) {
2227                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2228                                                 (int32_t)data->phy_clk_quad_eqn_a;
2229                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2230                                                 (int32_t)data->phy_clk_quad_eqn_b;
2231                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2232                                                 (int32_t)data->phy_clk_quad_eqn_c;
2233                         } else {
2234                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2235                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM1;
2236                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2237                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM2;
2238                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2239                                                 (int32_t)avfs_params.ulPhyclk2GfxclkB;
2240                         }
2241
2242                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24;
2243                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12;
2244                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12;
2245
2246                         pp_table->AcgBtcGbVdroopTable.a0       = avfs_params.ulAcgGbVdroopTableA0;
2247                         pp_table->AcgBtcGbVdroopTable.a0_shift = 20;
2248                         pp_table->AcgBtcGbVdroopTable.a1       = avfs_params.ulAcgGbVdroopTableA1;
2249                         pp_table->AcgBtcGbVdroopTable.a1_shift = 20;
2250                         pp_table->AcgBtcGbVdroopTable.a2       = avfs_params.ulAcgGbVdroopTableA2;
2251                         pp_table->AcgBtcGbVdroopTable.a2_shift = 20;
2252
2253                         pp_table->AcgAvfsGb.m1                   = avfs_params.ulAcgGbFuseTableM1;
2254                         pp_table->AcgAvfsGb.m2                   = avfs_params.ulAcgGbFuseTableM2;
2255                         pp_table->AcgAvfsGb.b                    = avfs_params.ulAcgGbFuseTableB;
2256                         pp_table->AcgAvfsGb.m1_shift             = 0;
2257                         pp_table->AcgAvfsGb.m2_shift             = 0;
2258                         pp_table->AcgAvfsGb.b_shift              = 0;
2259
2260                 } else {
2261                         data->smu_features[GNLD_AVFS].supported = false;
2262                 }
2263         }
2264
2265         return 0;
2266 }
2267
2268 static int vega10_acg_enable(struct pp_hwmgr *hwmgr)
2269 {
2270         struct vega10_hwmgr *data =
2271                         (struct vega10_hwmgr *)(hwmgr->backend);
2272         uint32_t agc_btc_response;
2273
2274         if (data->smu_features[GNLD_ACG].supported) {
2275                 if (0 == vega10_enable_smc_features(hwmgr->smumgr, true,
2276                                         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap))
2277                         data->smu_features[GNLD_DPM_PREFETCHER].enabled = true;
2278
2279                 smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_InitializeAcg);
2280
2281                 smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgBtc);
2282                 vega10_read_arg_from_smc(hwmgr->smumgr, &agc_btc_response);
2283
2284                 if (1 == agc_btc_response) {
2285                         if (1 == data->acg_loop_state)
2286                                 smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgInClosedLoop);
2287                         else if (2 == data->acg_loop_state)
2288                                 smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_RunAcgInOpenLoop);
2289                         if (0 == vega10_enable_smc_features(hwmgr->smumgr, true,
2290                                 data->smu_features[GNLD_ACG].smu_feature_bitmap))
2291                                         data->smu_features[GNLD_ACG].enabled = true;
2292                 } else {
2293                         pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n");
2294                         data->smu_features[GNLD_ACG].enabled = false;
2295                 }
2296         }
2297
2298         return 0;
2299 }
2300
2301 static int vega10_acg_disable(struct pp_hwmgr *hwmgr)
2302 {
2303         struct vega10_hwmgr *data =
2304                         (struct vega10_hwmgr *)(hwmgr->backend);
2305
2306         if (data->smu_features[GNLD_ACG].supported && 
2307             data->smu_features[GNLD_ACG].enabled)
2308                 if (!vega10_enable_smc_features(hwmgr->smumgr, false,
2309                         data->smu_features[GNLD_ACG].smu_feature_bitmap))
2310                         data->smu_features[GNLD_ACG].enabled = false;
2311
2312         return 0;
2313 }
2314
2315 static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr)
2316 {
2317         struct vega10_hwmgr *data =
2318                         (struct vega10_hwmgr *)(hwmgr->backend);
2319         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2320         struct pp_atomfwctrl_gpio_parameters gpio_params = {0};
2321         int result;
2322
2323         result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params);
2324         if (!result) {
2325                 if (PP_CAP(PHM_PlatformCaps_RegulatorHot) &&
2326                     data->registry_data.regulator_hot_gpio_support) {
2327                         pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio;
2328                         pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity;
2329                         pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio;
2330                         pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity;
2331                 } else {
2332                         pp_table->VR0HotGpio = 0;
2333                         pp_table->VR0HotPolarity = 0;
2334                         pp_table->VR1HotGpio = 0;
2335                         pp_table->VR1HotPolarity = 0;
2336                 }
2337
2338                 if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) &&
2339                     data->registry_data.ac_dc_switch_gpio_support) {
2340                         pp_table->AcDcGpio = gpio_params.ucAcDcGpio;
2341                         pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity;
2342                 } else {
2343                         pp_table->AcDcGpio = 0;
2344                         pp_table->AcDcPolarity = 0;
2345                 }
2346         }
2347
2348         return result;
2349 }
2350
2351 static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable)
2352 {
2353         struct vega10_hwmgr *data =
2354                         (struct vega10_hwmgr *)(hwmgr->backend);
2355
2356         if (data->smu_features[GNLD_AVFS].supported) {
2357                 if (enable) {
2358                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2359                                         true,
2360                                         data->smu_features[GNLD_AVFS].smu_feature_bitmap),
2361                                         "[avfs_control] Attempt to Enable AVFS feature Failed!",
2362                                         return -1);
2363                         data->smu_features[GNLD_AVFS].enabled = true;
2364                 } else {
2365                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2366                                         false,
2367                                         data->smu_features[GNLD_AVFS].smu_feature_id),
2368                                         "[avfs_control] Attempt to Disable AVFS feature Failed!",
2369                                         return -1);
2370                         data->smu_features[GNLD_AVFS].enabled = false;
2371                 }
2372         }
2373
2374         return 0;
2375 }
2376
2377 static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
2378 {
2379         int result = 0;
2380
2381         uint64_t serial_number = 0;
2382         uint32_t top32, bottom32;
2383         struct phm_fuses_default fuse;
2384
2385         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2386         AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table);
2387
2388         smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ReadSerialNumTop32);
2389         vega10_read_arg_from_smc(hwmgr->smumgr, &top32);
2390
2391         smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ReadSerialNumBottom32);
2392         vega10_read_arg_from_smc(hwmgr->smumgr, &bottom32);
2393
2394         serial_number = ((uint64_t)bottom32 << 32) | top32;
2395
2396         if (pp_override_get_default_fuse_value(serial_number, vega10_fuses_default, &fuse) == 0) {
2397                 avfs_fuse_table->VFT0_b  = fuse.VFT0_b;
2398                 avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1;
2399                 avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2;
2400                 avfs_fuse_table->VFT1_b  = fuse.VFT1_b;
2401                 avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1;
2402                 avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2;
2403                 avfs_fuse_table->VFT2_b  = fuse.VFT2_b;
2404                 avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1;
2405                 avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2;
2406                 result = vega10_copy_table_to_smc(hwmgr->smumgr,
2407                         (uint8_t *)avfs_fuse_table, AVFSFUSETABLE);
2408                 PP_ASSERT_WITH_CODE(!result,
2409                         "Failed to upload FuseOVerride!",
2410                         );
2411         }
2412
2413         return result;
2414 }
2415
2416 static int vega10_save_default_power_profile(struct pp_hwmgr *hwmgr)
2417 {
2418         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2419         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2420         uint32_t min_level;
2421
2422         hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
2423         hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
2424
2425         /* Optimize compute power profile: Use only highest
2426          * 2 power levels (if more than 2 are available)
2427          */
2428         if (dpm_table->count > 2)
2429                 min_level = dpm_table->count - 2;
2430         else if (dpm_table->count == 2)
2431                 min_level = 1;
2432         else
2433                 min_level = 0;
2434
2435         hwmgr->default_compute_power_profile.min_sclk =
2436                         dpm_table->dpm_levels[min_level].value;
2437
2438         hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
2439         hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
2440
2441         return 0;
2442 }
2443
2444 /**
2445 * Initializes the SMC table and uploads it
2446 *
2447 * @param    hwmgr  the address of the powerplay hardware manager.
2448 * @param    pInput  the pointer to input data (PowerState)
2449 * @return   always 0
2450 */
2451 static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
2452 {
2453         int result;
2454         struct vega10_hwmgr *data =
2455                         (struct vega10_hwmgr *)(hwmgr->backend);
2456         struct phm_ppt_v2_information *table_info =
2457                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2458         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2459         struct pp_atomfwctrl_voltage_table voltage_table;
2460         struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
2461
2462         result = vega10_setup_default_dpm_tables(hwmgr);
2463         PP_ASSERT_WITH_CODE(!result,
2464                         "Failed to setup default DPM tables!",
2465                         return result);
2466
2467         pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC,
2468                         VOLTAGE_OBJ_SVID2,  &voltage_table);
2469         pp_table->MaxVidStep = voltage_table.max_vid_step;
2470
2471         pp_table->GfxDpmVoltageMode =
2472                         (uint8_t)(table_info->uc_gfx_dpm_voltage_mode);
2473         pp_table->SocDpmVoltageMode =
2474                         (uint8_t)(table_info->uc_soc_dpm_voltage_mode);
2475         pp_table->UclkDpmVoltageMode =
2476                         (uint8_t)(table_info->uc_uclk_dpm_voltage_mode);
2477         pp_table->UvdDpmVoltageMode =
2478                         (uint8_t)(table_info->uc_uvd_dpm_voltage_mode);
2479         pp_table->VceDpmVoltageMode =
2480                         (uint8_t)(table_info->uc_vce_dpm_voltage_mode);
2481         pp_table->Mp0DpmVoltageMode =
2482                         (uint8_t)(table_info->uc_mp0_dpm_voltage_mode);
2483
2484         pp_table->DisplayDpmVoltageMode =
2485                         (uint8_t)(table_info->uc_dcef_dpm_voltage_mode);
2486
2487         data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable;
2488         data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable;
2489
2490         if (data->registry_data.ulv_support &&
2491                         table_info->us_ulv_voltage_offset) {
2492                 result = vega10_populate_ulv_state(hwmgr);
2493                 PP_ASSERT_WITH_CODE(!result,
2494                                 "Failed to initialize ULV state!",
2495                                 return result);
2496         }
2497
2498         result = vega10_populate_smc_link_levels(hwmgr);
2499         PP_ASSERT_WITH_CODE(!result,
2500                         "Failed to initialize Link Level!",
2501                         return result);
2502
2503         result = vega10_populate_all_graphic_levels(hwmgr);
2504         PP_ASSERT_WITH_CODE(!result,
2505                         "Failed to initialize Graphics Level!",
2506                         return result);
2507
2508         result = vega10_populate_all_memory_levels(hwmgr);
2509         PP_ASSERT_WITH_CODE(!result,
2510                         "Failed to initialize Memory Level!",
2511                         return result);
2512
2513         result = vega10_populate_all_display_clock_levels(hwmgr);
2514         PP_ASSERT_WITH_CODE(!result,
2515                         "Failed to initialize Display Level!",
2516                         return result);
2517
2518         result = vega10_populate_smc_vce_levels(hwmgr);
2519         PP_ASSERT_WITH_CODE(!result,
2520                         "Failed to initialize VCE Level!",
2521                         return result);
2522
2523         result = vega10_populate_smc_uvd_levels(hwmgr);
2524         PP_ASSERT_WITH_CODE(!result,
2525                         "Failed to initialize UVD Level!",
2526                         return result);
2527
2528         if (data->registry_data.clock_stretcher_support) {
2529                 result = vega10_populate_clock_stretcher_table(hwmgr);
2530                 PP_ASSERT_WITH_CODE(!result,
2531                                 "Failed to populate Clock Stretcher Table!",
2532                                 return result);
2533         }
2534
2535         result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
2536         if (!result) {
2537                 data->vbios_boot_state.vddc     = boot_up_values.usVddc;
2538                 data->vbios_boot_state.vddci    = boot_up_values.usVddci;
2539                 data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
2540                 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
2541                 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
2542                 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
2543                 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
2544                 if (0 != boot_up_values.usVddc) {
2545                         smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2546                                                 PPSMC_MSG_SetFloorSocVoltage,
2547                                                 (boot_up_values.usVddc * 4));
2548                         data->vbios_boot_state.bsoc_vddc_lock = true;
2549                 } else {
2550                         data->vbios_boot_state.bsoc_vddc_lock = false;
2551                 }
2552                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2553                                 PPSMC_MSG_SetMinDeepSleepDcefclk,
2554                         (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
2555         }
2556
2557         result = vega10_populate_avfs_parameters(hwmgr);
2558         PP_ASSERT_WITH_CODE(!result,
2559                         "Failed to initialize AVFS Parameters!",
2560                         return result);
2561
2562         result = vega10_populate_gpio_parameters(hwmgr);
2563         PP_ASSERT_WITH_CODE(!result,
2564                         "Failed to initialize GPIO Parameters!",
2565                         return result);
2566
2567         pp_table->GfxclkAverageAlpha = (uint8_t)
2568                         (data->gfxclk_average_alpha);
2569         pp_table->SocclkAverageAlpha = (uint8_t)
2570                         (data->socclk_average_alpha);
2571         pp_table->UclkAverageAlpha = (uint8_t)
2572                         (data->uclk_average_alpha);
2573         pp_table->GfxActivityAverageAlpha = (uint8_t)
2574                         (data->gfx_activity_average_alpha);
2575
2576         vega10_populate_and_upload_avfs_fuse_override(hwmgr);
2577
2578         result = vega10_copy_table_to_smc(hwmgr->smumgr,
2579                         (uint8_t *)pp_table, PPTABLE);
2580         PP_ASSERT_WITH_CODE(!result,
2581                         "Failed to upload PPtable!", return result);
2582
2583         result = vega10_avfs_enable(hwmgr, true);
2584         PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
2585                                         return result);
2586         vega10_acg_enable(hwmgr);
2587         vega10_save_default_power_profile(hwmgr);
2588
2589         return 0;
2590 }
2591
2592 static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
2593 {
2594         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2595
2596         if (data->smu_features[GNLD_THERMAL].supported) {
2597                 if (data->smu_features[GNLD_THERMAL].enabled)
2598                         pr_info("THERMAL Feature Already enabled!");
2599
2600                 PP_ASSERT_WITH_CODE(
2601                                 !vega10_enable_smc_features(hwmgr->smumgr,
2602                                 true,
2603                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2604                                 "Enable THERMAL Feature Failed!",
2605                                 return -1);
2606                 data->smu_features[GNLD_THERMAL].enabled = true;
2607         }
2608
2609         return 0;
2610 }
2611
2612 static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr)
2613 {
2614         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2615
2616         if (data->smu_features[GNLD_THERMAL].supported) {
2617                 if (!data->smu_features[GNLD_THERMAL].enabled)
2618                         pr_info("THERMAL Feature Already disabled!");
2619
2620                 PP_ASSERT_WITH_CODE(
2621                                 !vega10_enable_smc_features(hwmgr->smumgr,
2622                                 false,
2623                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2624                                 "disable THERMAL Feature Failed!",
2625                                 return -1);
2626                 data->smu_features[GNLD_THERMAL].enabled = false;
2627         }
2628
2629         return 0;
2630 }
2631
2632 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
2633 {
2634         struct vega10_hwmgr *data =
2635                         (struct vega10_hwmgr *)(hwmgr->backend);
2636
2637         if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) {
2638                 if (data->smu_features[GNLD_VR0HOT].supported) {
2639                         PP_ASSERT_WITH_CODE(
2640                                         !vega10_enable_smc_features(hwmgr->smumgr,
2641                                         true,
2642                                         data->smu_features[GNLD_VR0HOT].smu_feature_bitmap),
2643                                         "Attempt to Enable VR0 Hot feature Failed!",
2644                                         return -1);
2645                         data->smu_features[GNLD_VR0HOT].enabled = true;
2646                 } else {
2647                         if (data->smu_features[GNLD_VR1HOT].supported) {
2648                                 PP_ASSERT_WITH_CODE(
2649                                                 !vega10_enable_smc_features(hwmgr->smumgr,
2650                                                 true,
2651                                                 data->smu_features[GNLD_VR1HOT].smu_feature_bitmap),
2652                                                 "Attempt to Enable VR0 Hot feature Failed!",
2653                                                 return -1);
2654                                 data->smu_features[GNLD_VR1HOT].enabled = true;
2655                         }
2656                 }
2657         }
2658         return 0;
2659 }
2660
2661 static int vega10_enable_ulv(struct pp_hwmgr *hwmgr)
2662 {
2663         struct vega10_hwmgr *data =
2664                         (struct vega10_hwmgr *)(hwmgr->backend);
2665
2666         if (data->registry_data.ulv_support) {
2667                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2668                                 true, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2669                                 "Enable ULV Feature Failed!",
2670                                 return -1);
2671                 data->smu_features[GNLD_ULV].enabled = true;
2672         }
2673
2674         return 0;
2675 }
2676
2677 static int vega10_disable_ulv(struct pp_hwmgr *hwmgr)
2678 {
2679         struct vega10_hwmgr *data =
2680                         (struct vega10_hwmgr *)(hwmgr->backend);
2681
2682         if (data->registry_data.ulv_support) {
2683                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2684                                 false, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2685                                 "disable ULV Feature Failed!",
2686                                 return -EINVAL);
2687                 data->smu_features[GNLD_ULV].enabled = false;
2688         }
2689
2690         return 0;
2691 }
2692
2693 static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2694 {
2695         struct vega10_hwmgr *data =
2696                         (struct vega10_hwmgr *)(hwmgr->backend);
2697
2698         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2699                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2700                                 true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2701                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2702                                 return -EINVAL);
2703                 data->smu_features[GNLD_DS_GFXCLK].enabled = true;
2704         }
2705
2706         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2707                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2708                                 true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2709                                 "Attempt to Enable DS_SOCCLK Feature Failed!",
2710                                 return -EINVAL);
2711                 data->smu_features[GNLD_DS_SOCCLK].enabled = true;
2712         }
2713
2714         if (data->smu_features[GNLD_DS_LCLK].supported) {
2715                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2716                                 true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2717                                 "Attempt to Enable DS_LCLK Feature Failed!",
2718                                 return -EINVAL);
2719                 data->smu_features[GNLD_DS_LCLK].enabled = true;
2720         }
2721
2722         if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
2723                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2724                                 true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap),
2725                                 "Attempt to Enable DS_DCEFCLK Feature Failed!",
2726                                 return -EINVAL);
2727                 data->smu_features[GNLD_DS_DCEFCLK].enabled = true;
2728         }
2729
2730         return 0;
2731 }
2732
2733 static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2734 {
2735         struct vega10_hwmgr *data =
2736                         (struct vega10_hwmgr *)(hwmgr->backend);
2737
2738         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2739                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2740                                 false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2741                                 "Attempt to disable DS_GFXCLK Feature Failed!",
2742                                 return -EINVAL);
2743                 data->smu_features[GNLD_DS_GFXCLK].enabled = false;
2744         }
2745
2746         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2747                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2748                                 false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2749                                 "Attempt to disable DS_ Feature Failed!",
2750                                 return -EINVAL);
2751                 data->smu_features[GNLD_DS_SOCCLK].enabled = false;
2752         }
2753
2754         if (data->smu_features[GNLD_DS_LCLK].supported) {
2755                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2756                                 false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2757                                 "Attempt to disable DS_LCLK Feature Failed!",
2758                                 return -EINVAL);
2759                 data->smu_features[GNLD_DS_LCLK].enabled = false;
2760         }
2761
2762         if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
2763                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2764                                 false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap),
2765                                 "Attempt to disable DS_DCEFCLK Feature Failed!",
2766                                 return -EINVAL);
2767                 data->smu_features[GNLD_DS_DCEFCLK].enabled = false;
2768         }
2769
2770         return 0;
2771 }
2772
2773 static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2774 {
2775         struct vega10_hwmgr *data =
2776                         (struct vega10_hwmgr *)(hwmgr->backend);
2777         uint32_t i, feature_mask = 0;
2778
2779
2780         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2781                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2782                                 false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2783                 "Attempt to disable LED DPM feature failed!", return -EINVAL);
2784                 data->smu_features[GNLD_LED_DISPLAY].enabled = false;
2785         }
2786
2787         for (i = 0; i < GNLD_DPM_MAX; i++) {
2788                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2789                         if (data->smu_features[i].supported) {
2790                                 if (data->smu_features[i].enabled) {
2791                                         feature_mask |= data->smu_features[i].
2792                                                         smu_feature_bitmap;
2793                                         data->smu_features[i].enabled = false;
2794                                 }
2795                         }
2796                 }
2797         }
2798
2799         vega10_enable_smc_features(hwmgr->smumgr, false, feature_mask);
2800
2801         return 0;
2802 }
2803
2804 /**
2805  * @brief Tell SMC to enabled the supported DPMs.
2806  *
2807  * @param    hwmgr - the address of the powerplay hardware manager.
2808  * @Param    bitmap - bitmap for the features to enabled.
2809  * @return   0 on at least one DPM is successfully enabled.
2810  */
2811 static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2812 {
2813         struct vega10_hwmgr *data =
2814                         (struct vega10_hwmgr *)(hwmgr->backend);
2815         uint32_t i, feature_mask = 0;
2816
2817         for (i = 0; i < GNLD_DPM_MAX; i++) {
2818                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2819                         if (data->smu_features[i].supported) {
2820                                 if (!data->smu_features[i].enabled) {
2821                                         feature_mask |= data->smu_features[i].
2822                                                         smu_feature_bitmap;
2823                                         data->smu_features[i].enabled = true;
2824                                 }
2825                         }
2826                 }
2827         }
2828
2829         if (vega10_enable_smc_features(hwmgr->smumgr,
2830                         true, feature_mask)) {
2831                 for (i = 0; i < GNLD_DPM_MAX; i++) {
2832                         if (data->smu_features[i].smu_feature_bitmap &
2833                                         feature_mask)
2834                                 data->smu_features[i].enabled = false;
2835                 }
2836         }
2837
2838         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2839                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2840                                 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2841                 "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
2842                 data->smu_features[GNLD_LED_DISPLAY].enabled = true;
2843         }
2844
2845         if (data->vbios_boot_state.bsoc_vddc_lock) {
2846                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2847                                                 PPSMC_MSG_SetFloorSocVoltage, 0);
2848                 data->vbios_boot_state.bsoc_vddc_lock = false;
2849         }
2850
2851         if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) {
2852                 if (data->smu_features[GNLD_ACDC].supported) {
2853                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2854                                         true, data->smu_features[GNLD_ACDC].smu_feature_bitmap),
2855                                         "Attempt to Enable DS_GFXCLK Feature Failed!",
2856                                         return -1);
2857                         data->smu_features[GNLD_ACDC].enabled = true;
2858                 }
2859         }
2860
2861         return 0;
2862 }
2863
2864 static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
2865 {
2866         struct vega10_hwmgr *data =
2867                         (struct vega10_hwmgr *)(hwmgr->backend);
2868         int tmp_result, result = 0;
2869
2870         tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2871                         PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
2872         PP_ASSERT_WITH_CODE(!tmp_result,
2873                         "Failed to configure telemetry!",
2874                         return tmp_result);
2875
2876         smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2877                         PPSMC_MSG_NumOfDisplays, 0);
2878
2879         tmp_result = (!vega10_is_dpm_running(hwmgr)) ? 0 : -1;
2880         PP_ASSERT_WITH_CODE(!tmp_result,
2881                         "DPM is already running right , skipping re-enablement!",
2882                         return 0);
2883
2884         tmp_result = vega10_construct_voltage_tables(hwmgr);
2885         PP_ASSERT_WITH_CODE(!tmp_result,
2886                         "Failed to contruct voltage tables!",
2887                         result = tmp_result);
2888
2889         tmp_result = vega10_init_smc_table(hwmgr);
2890         PP_ASSERT_WITH_CODE(!tmp_result,
2891                         "Failed to initialize SMC table!",
2892                         result = tmp_result);
2893
2894         if (PP_CAP(PHM_PlatformCaps_ThermalController)) {
2895                 tmp_result = vega10_enable_thermal_protection(hwmgr);
2896                 PP_ASSERT_WITH_CODE(!tmp_result,
2897                                 "Failed to enable thermal protection!",
2898                                 result = tmp_result);
2899         }
2900