Merge tag 'docs-4.15-2' of git://git.lwn.net/linux
[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 static const 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 static 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, PPSMC_MSG_GetSmuVersion);
429         vega10_read_arg_from_smc(hwmgr, &(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, &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         dpm_table->count = 0;
1165
1166         for (i = 0; i < dep_table->count; i++) {
1167                 if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <=
1168                                 dep_table->entries[i].clk) {
1169                         dpm_table->dpm_levels[dpm_table->count].value =
1170                                         dep_table->entries[i].clk;
1171                         dpm_table->dpm_levels[dpm_table->count].enabled = true;
1172                         dpm_table->count++;
1173                 }
1174         }
1175 }
1176 static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
1177 {
1178         struct vega10_hwmgr *data =
1179                         (struct vega10_hwmgr *)(hwmgr->backend);
1180         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
1181         struct phm_ppt_v2_information *table_info =
1182                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1183         struct phm_ppt_v1_pcie_table *bios_pcie_table =
1184                         table_info->pcie_table;
1185         uint32_t i;
1186
1187         PP_ASSERT_WITH_CODE(bios_pcie_table->count,
1188                         "Incorrect number of PCIE States from VBIOS!",
1189                         return -1);
1190
1191         for (i = 0; i < NUM_LINK_LEVELS; i++) {
1192                 if (data->registry_data.pcieSpeedOverride)
1193                         pcie_table->pcie_gen[i] =
1194                                         data->registry_data.pcieSpeedOverride;
1195                 else
1196                         pcie_table->pcie_gen[i] =
1197                                         bios_pcie_table->entries[i].gen_speed;
1198
1199                 if (data->registry_data.pcieLaneOverride)
1200                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1201                                         data->registry_data.pcieLaneOverride);
1202                 else
1203                         pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width(
1204                                                         bios_pcie_table->entries[i].lane_width);
1205                 if (data->registry_data.pcieClockOverride)
1206                         pcie_table->lclk[i] =
1207                                         data->registry_data.pcieClockOverride;
1208                 else
1209                         pcie_table->lclk[i] =
1210                                         bios_pcie_table->entries[i].pcie_sclk;
1211         }
1212
1213         pcie_table->count = NUM_LINK_LEVELS;
1214
1215         return 0;
1216 }
1217
1218 /*
1219  * This function is to initialize all DPM state tables
1220  * for SMU based on the dependency table.
1221  * Dynamic state patching function will then trim these
1222  * state tables to the allowed range based
1223  * on the power policy or external client requests,
1224  * such as UVD request, etc.
1225  */
1226 static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
1227 {
1228         struct vega10_hwmgr *data =
1229                         (struct vega10_hwmgr *)(hwmgr->backend);
1230         struct phm_ppt_v2_information *table_info =
1231                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1232         struct vega10_single_dpm_table *dpm_table;
1233         uint32_t i;
1234
1235         struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table =
1236                         table_info->vdd_dep_on_socclk;
1237         struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table =
1238                         table_info->vdd_dep_on_sclk;
1239         struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
1240                         table_info->vdd_dep_on_mclk;
1241         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table =
1242                         table_info->mm_dep_table;
1243         struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table =
1244                         table_info->vdd_dep_on_dcefclk;
1245         struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table =
1246                         table_info->vdd_dep_on_pixclk;
1247         struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table =
1248                         table_info->vdd_dep_on_dispclk;
1249         struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table =
1250                         table_info->vdd_dep_on_phyclk;
1251
1252         PP_ASSERT_WITH_CODE(dep_soc_table,
1253                         "SOCCLK dependency table is missing. This table is mandatory",
1254                         return -EINVAL);
1255         PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1,
1256                         "SOCCLK dependency table is empty. This table is mandatory",
1257                         return -EINVAL);
1258
1259         PP_ASSERT_WITH_CODE(dep_gfx_table,
1260                         "GFXCLK dependency table is missing. This table is mandatory",
1261                         return -EINVAL);
1262         PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1,
1263                         "GFXCLK dependency table is empty. This table is mandatory",
1264                         return -EINVAL);
1265
1266         PP_ASSERT_WITH_CODE(dep_mclk_table,
1267                         "MCLK dependency table is missing. This table is mandatory",
1268                         return -EINVAL);
1269         PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
1270                         "MCLK dependency table has to have is missing. This table is mandatory",
1271                         return -EINVAL);
1272
1273         /* Initialize Sclk DPM table based on allow Sclk values */
1274         dpm_table = &(data->dpm_table.soc_table);
1275         vega10_setup_default_single_dpm_table(hwmgr,
1276                         dpm_table,
1277                         dep_soc_table);
1278
1279         vega10_init_dpm_state(&(dpm_table->dpm_state));
1280
1281         dpm_table = &(data->dpm_table.gfx_table);
1282         vega10_setup_default_single_dpm_table(hwmgr,
1283                         dpm_table,
1284                         dep_gfx_table);
1285         vega10_init_dpm_state(&(dpm_table->dpm_state));
1286
1287         /* Initialize Mclk DPM table based on allow Mclk values */
1288         data->dpm_table.mem_table.count = 0;
1289         dpm_table = &(data->dpm_table.mem_table);
1290         vega10_setup_default_single_dpm_table(hwmgr,
1291                         dpm_table,
1292                         dep_mclk_table);
1293         vega10_init_dpm_state(&(dpm_table->dpm_state));
1294
1295         data->dpm_table.eclk_table.count = 0;
1296         dpm_table = &(data->dpm_table.eclk_table);
1297         for (i = 0; i < dep_mm_table->count; i++) {
1298                 if (i == 0 || dpm_table->dpm_levels
1299                                 [dpm_table->count - 1].value <=
1300                                                 dep_mm_table->entries[i].eclk) {
1301                         dpm_table->dpm_levels[dpm_table->count].value =
1302                                         dep_mm_table->entries[i].eclk;
1303                         dpm_table->dpm_levels[dpm_table->count].enabled =
1304                                         (i == 0) ? true : false;
1305                         dpm_table->count++;
1306                 }
1307         }
1308         vega10_init_dpm_state(&(dpm_table->dpm_state));
1309
1310         data->dpm_table.vclk_table.count = 0;
1311         data->dpm_table.dclk_table.count = 0;
1312         dpm_table = &(data->dpm_table.vclk_table);
1313         for (i = 0; i < dep_mm_table->count; i++) {
1314                 if (i == 0 || dpm_table->dpm_levels
1315                                 [dpm_table->count - 1].value <=
1316                                                 dep_mm_table->entries[i].vclk) {
1317                         dpm_table->dpm_levels[dpm_table->count].value =
1318                                         dep_mm_table->entries[i].vclk;
1319                         dpm_table->dpm_levels[dpm_table->count].enabled =
1320                                         (i == 0) ? true : false;
1321                         dpm_table->count++;
1322                 }
1323         }
1324         vega10_init_dpm_state(&(dpm_table->dpm_state));
1325
1326         dpm_table = &(data->dpm_table.dclk_table);
1327         for (i = 0; i < dep_mm_table->count; i++) {
1328                 if (i == 0 || dpm_table->dpm_levels
1329                                 [dpm_table->count - 1].value <=
1330                                                 dep_mm_table->entries[i].dclk) {
1331                         dpm_table->dpm_levels[dpm_table->count].value =
1332                                         dep_mm_table->entries[i].dclk;
1333                         dpm_table->dpm_levels[dpm_table->count].enabled =
1334                                         (i == 0) ? true : false;
1335                         dpm_table->count++;
1336                 }
1337         }
1338         vega10_init_dpm_state(&(dpm_table->dpm_state));
1339
1340         /* Assume there is no headless Vega10 for now */
1341         dpm_table = &(data->dpm_table.dcef_table);
1342         vega10_setup_default_single_dpm_table(hwmgr,
1343                         dpm_table,
1344                         dep_dcef_table);
1345
1346         vega10_init_dpm_state(&(dpm_table->dpm_state));
1347
1348         dpm_table = &(data->dpm_table.pixel_table);
1349         vega10_setup_default_single_dpm_table(hwmgr,
1350                         dpm_table,
1351                         dep_pix_table);
1352
1353         vega10_init_dpm_state(&(dpm_table->dpm_state));
1354
1355         dpm_table = &(data->dpm_table.display_table);
1356         vega10_setup_default_single_dpm_table(hwmgr,
1357                         dpm_table,
1358                         dep_disp_table);
1359
1360         vega10_init_dpm_state(&(dpm_table->dpm_state));
1361
1362         dpm_table = &(data->dpm_table.phy_table);
1363         vega10_setup_default_single_dpm_table(hwmgr,
1364                         dpm_table,
1365                         dep_phy_table);
1366
1367         vega10_init_dpm_state(&(dpm_table->dpm_state));
1368
1369         vega10_setup_default_pcie_table(hwmgr);
1370
1371         /* save a copy of the default DPM table */
1372         memcpy(&(data->golden_dpm_table), &(data->dpm_table),
1373                         sizeof(struct vega10_dpm_table));
1374
1375         if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) ||
1376             PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) {
1377                 data->odn_dpm_table.odn_core_clock_dpm_levels.
1378                 number_of_performance_levels = data->dpm_table.gfx_table.count;
1379                 for (i = 0; i < data->dpm_table.gfx_table.count; i++) {
1380                         data->odn_dpm_table.odn_core_clock_dpm_levels.
1381                         performance_level_entries[i].clock =
1382                                         data->dpm_table.gfx_table.dpm_levels[i].value;
1383                         data->odn_dpm_table.odn_core_clock_dpm_levels.
1384                         performance_level_entries[i].enabled = true;
1385                 }
1386
1387                 data->odn_dpm_table.vdd_dependency_on_sclk.count =
1388                                 dep_gfx_table->count;
1389                 for (i = 0; i < dep_gfx_table->count; i++) {
1390                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].clk =
1391                                         dep_gfx_table->entries[i].clk;
1392                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].vddInd =
1393                                         dep_gfx_table->entries[i].vddInd;
1394                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_enable =
1395                                         dep_gfx_table->entries[i].cks_enable;
1396                         data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_voffset =
1397                                         dep_gfx_table->entries[i].cks_voffset;
1398                 }
1399
1400                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
1401                 number_of_performance_levels = data->dpm_table.mem_table.count;
1402                 for (i = 0; i < data->dpm_table.mem_table.count; i++) {
1403                         data->odn_dpm_table.odn_memory_clock_dpm_levels.
1404                         performance_level_entries[i].clock =
1405                                         data->dpm_table.mem_table.dpm_levels[i].value;
1406                         data->odn_dpm_table.odn_memory_clock_dpm_levels.
1407                         performance_level_entries[i].enabled = true;
1408                 }
1409
1410                 data->odn_dpm_table.vdd_dependency_on_mclk.count = dep_mclk_table->count;
1411                 for (i = 0; i < dep_mclk_table->count; i++) {
1412                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].clk =
1413                                         dep_mclk_table->entries[i].clk;
1414                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddInd =
1415                                         dep_mclk_table->entries[i].vddInd;
1416                         data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddci =
1417                                         dep_mclk_table->entries[i].vddci;
1418                 }
1419         }
1420
1421         return 0;
1422 }
1423
1424 /*
1425  * @fn vega10_populate_ulv_state
1426  * @brief Function to provide parameters for Utral Low Voltage state to SMC.
1427  *
1428  * @param    hwmgr - the address of the hardware manager.
1429  * @return   Always 0.
1430  */
1431 static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr)
1432 {
1433         struct vega10_hwmgr *data =
1434                         (struct vega10_hwmgr *)(hwmgr->backend);
1435         struct phm_ppt_v2_information *table_info =
1436                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1437
1438         data->smc_state_table.pp_table.UlvOffsetVid =
1439                         (uint8_t)table_info->us_ulv_voltage_offset;
1440
1441         data->smc_state_table.pp_table.UlvSmnclkDid =
1442                         (uint8_t)(table_info->us_ulv_smnclk_did);
1443         data->smc_state_table.pp_table.UlvMp1clkDid =
1444                         (uint8_t)(table_info->us_ulv_mp1clk_did);
1445         data->smc_state_table.pp_table.UlvGfxclkBypass =
1446                         (uint8_t)(table_info->us_ulv_gfxclk_bypass);
1447         data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 =
1448                         (uint8_t)(data->vddc_voltage_table.psi0_enable);
1449         data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 =
1450                         (uint8_t)(data->vddc_voltage_table.psi1_enable);
1451
1452         return 0;
1453 }
1454
1455 static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr,
1456                 uint32_t lclock, uint8_t *curr_lclk_did)
1457 {
1458         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1459
1460         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1461                         hwmgr,
1462                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1463                         lclock, &dividers),
1464                         "Failed to get LCLK clock settings from VBIOS!",
1465                         return -1);
1466
1467         *curr_lclk_did = dividers.ulDid;
1468
1469         return 0;
1470 }
1471
1472 static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr)
1473 {
1474         int result = -1;
1475         struct vega10_hwmgr *data =
1476                         (struct vega10_hwmgr *)(hwmgr->backend);
1477         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1478         struct vega10_pcie_table *pcie_table =
1479                         &(data->dpm_table.pcie_table);
1480         uint32_t i, j;
1481
1482         for (i = 0; i < pcie_table->count; i++) {
1483                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i];
1484                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i];
1485
1486                 result = vega10_populate_single_lclk_level(hwmgr,
1487                                 pcie_table->lclk[i], &(pp_table->LclkDid[i]));
1488                 if (result) {
1489                         pr_info("Populate LClock Level %d Failed!\n", i);
1490                         return result;
1491                 }
1492         }
1493
1494         j = i - 1;
1495         while (i < NUM_LINK_LEVELS) {
1496                 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j];
1497                 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j];
1498
1499                 result = vega10_populate_single_lclk_level(hwmgr,
1500                                 pcie_table->lclk[j], &(pp_table->LclkDid[i]));
1501                 if (result) {
1502                         pr_info("Populate LClock Level %d Failed!\n", i);
1503                         return result;
1504                 }
1505                 i++;
1506         }
1507
1508         return result;
1509 }
1510
1511 /**
1512 * Populates single SMC GFXSCLK structure using the provided engine clock
1513 *
1514 * @param    hwmgr      the address of the hardware manager
1515 * @param    gfx_clock  the GFX clock to use to populate the structure.
1516 * @param    current_gfxclk_level  location in PPTable for the SMC GFXCLK structure.
1517 */
1518
1519 static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr,
1520                 uint32_t gfx_clock, PllSetting_t *current_gfxclk_level,
1521                 uint32_t *acg_freq)
1522 {
1523         struct phm_ppt_v2_information *table_info =
1524                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1525         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk =
1526                         table_info->vdd_dep_on_sclk;
1527         struct vega10_hwmgr *data =
1528                         (struct vega10_hwmgr *)(hwmgr->backend);
1529         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1530         uint32_t gfx_max_clock =
1531                         hwmgr->platform_descriptor.overdriveLimit.engineClock;
1532         uint32_t i = 0;
1533
1534         if (data->apply_overdrive_next_settings_mask &
1535                         DPMTABLE_OD_UPDATE_VDDC)
1536                 dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1537                                                 &(data->odn_dpm_table.vdd_dependency_on_sclk);
1538
1539         PP_ASSERT_WITH_CODE(dep_on_sclk,
1540                         "Invalid SOC_VDD-GFX_CLK Dependency Table!",
1541                         return -EINVAL);
1542
1543         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK)
1544                 gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock;
1545         else {
1546                 for (i = 0; i < dep_on_sclk->count; i++) {
1547                         if (dep_on_sclk->entries[i].clk == gfx_clock)
1548                                 break;
1549                 }
1550                 PP_ASSERT_WITH_CODE(dep_on_sclk->count > i,
1551                                 "Cannot find gfx_clk in SOC_VDD-GFX_CLK!",
1552                                 return -EINVAL);
1553         }
1554
1555         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1556                         COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK,
1557                         gfx_clock, &dividers),
1558                         "Failed to get GFX Clock settings from VBIOS!",
1559                         return -EINVAL);
1560
1561         /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */
1562         current_gfxclk_level->FbMult =
1563                         cpu_to_le32(dividers.ulPll_fb_mult);
1564         /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */
1565         current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
1566         current_gfxclk_level->SsFbMult =
1567                         cpu_to_le32(dividers.ulPll_ss_fbsmult);
1568         current_gfxclk_level->SsSlewFrac =
1569                         cpu_to_le16(dividers.usPll_ss_slew_frac);
1570         current_gfxclk_level->Did = (uint8_t)(dividers.ulDid);
1571
1572         *acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */
1573
1574         return 0;
1575 }
1576
1577 /**
1578  * @brief Populates single SMC SOCCLK structure using the provided clock.
1579  *
1580  * @param    hwmgr - the address of the hardware manager.
1581  * @param    soc_clock - the SOC clock to use to populate the structure.
1582  * @param    current_socclk_level - location in PPTable for the SMC SOCCLK structure.
1583  * @return   0 on success..
1584  */
1585 static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr,
1586                 uint32_t soc_clock, uint8_t *current_soc_did,
1587                 uint8_t *current_vol_index)
1588 {
1589         struct phm_ppt_v2_information *table_info =
1590                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1591         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc =
1592                         table_info->vdd_dep_on_socclk;
1593         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1594         uint32_t i;
1595
1596         PP_ASSERT_WITH_CODE(dep_on_soc,
1597                         "Invalid SOC_VDD-SOC_CLK Dependency Table!",
1598                         return -EINVAL);
1599         for (i = 0; i < dep_on_soc->count; i++) {
1600                 if (dep_on_soc->entries[i].clk == soc_clock)
1601                         break;
1602         }
1603         PP_ASSERT_WITH_CODE(dep_on_soc->count > i,
1604                         "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table",
1605                         return -EINVAL);
1606         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1607                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1608                         soc_clock, &dividers),
1609                         "Failed to get SOC Clock settings from VBIOS!",
1610                         return -EINVAL);
1611
1612         *current_soc_did = (uint8_t)dividers.ulDid;
1613         *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd);
1614
1615         return 0;
1616 }
1617
1618 uint16_t vega10_locate_vddc_given_clock(struct pp_hwmgr *hwmgr,
1619                 uint32_t clk,
1620                 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
1621 {
1622         uint16_t i;
1623
1624         for (i = 0; i < dep_table->count; i++) {
1625                 if (dep_table->entries[i].clk == clk)
1626                         return dep_table->entries[i].vddc;
1627         }
1628
1629         pr_info("[LocateVddcGivenClock] Cannot locate SOC Vddc for this clock!");
1630         return 0;
1631 }
1632
1633 /**
1634 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
1635 *
1636 * @param    hwmgr      the address of the hardware manager
1637 */
1638 static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
1639 {
1640         struct vega10_hwmgr *data =
1641                         (struct vega10_hwmgr *)(hwmgr->backend);
1642         struct phm_ppt_v2_information *table_info =
1643                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1644         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
1645                         table_info->vdd_dep_on_socclk;
1646         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1647         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
1648         int result = 0;
1649         uint32_t i, j;
1650
1651         for (i = 0; i < dpm_table->count; i++) {
1652                 result = vega10_populate_single_gfx_level(hwmgr,
1653                                 dpm_table->dpm_levels[i].value,
1654                                 &(pp_table->GfxclkLevel[i]),
1655                                 &(pp_table->AcgFreqTable[i]));
1656                 if (result)
1657                         return result;
1658         }
1659
1660         j = i - 1;
1661         while (i < NUM_GFXCLK_DPM_LEVELS) {
1662                 result = vega10_populate_single_gfx_level(hwmgr,
1663                                 dpm_table->dpm_levels[j].value,
1664                                 &(pp_table->GfxclkLevel[i]),
1665                                 &(pp_table->AcgFreqTable[i]));
1666                 if (result)
1667                         return result;
1668                 i++;
1669         }
1670
1671         pp_table->GfxclkSlewRate =
1672                         cpu_to_le16(table_info->us_gfxclk_slew_rate);
1673
1674         dpm_table = &(data->dpm_table.soc_table);
1675         for (i = 0; i < dpm_table->count; i++) {
1676                 pp_table->SocVid[i] =
1677                                 (uint8_t)convert_to_vid(
1678                                 vega10_locate_vddc_given_clock(hwmgr,
1679                                                 dpm_table->dpm_levels[i].value,
1680                                                 dep_table));
1681                 result = vega10_populate_single_soc_level(hwmgr,
1682                                 dpm_table->dpm_levels[i].value,
1683                                 &(pp_table->SocclkDid[i]),
1684                                 &(pp_table->SocDpmVoltageIndex[i]));
1685                 if (result)
1686                         return result;
1687         }
1688
1689         j = i - 1;
1690         while (i < NUM_SOCCLK_DPM_LEVELS) {
1691                 pp_table->SocVid[i] = pp_table->SocVid[j];
1692                 result = vega10_populate_single_soc_level(hwmgr,
1693                                 dpm_table->dpm_levels[j].value,
1694                                 &(pp_table->SocclkDid[i]),
1695                                 &(pp_table->SocDpmVoltageIndex[i]));
1696                 if (result)
1697                         return result;
1698                 i++;
1699         }
1700
1701         return result;
1702 }
1703
1704 /**
1705  * @brief Populates single SMC GFXCLK structure using the provided clock.
1706  *
1707  * @param    hwmgr - the address of the hardware manager.
1708  * @param    mem_clock - the memory clock to use to populate the structure.
1709  * @return   0 on success..
1710  */
1711 static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
1712                 uint32_t mem_clock, uint8_t *current_mem_vid,
1713                 PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind)
1714 {
1715         struct vega10_hwmgr *data =
1716                         (struct vega10_hwmgr *)(hwmgr->backend);
1717         struct phm_ppt_v2_information *table_info =
1718                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1719         struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk =
1720                         table_info->vdd_dep_on_mclk;
1721         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1722         uint32_t mem_max_clock =
1723                         hwmgr->platform_descriptor.overdriveLimit.memoryClock;
1724         uint32_t i = 0;
1725
1726         if (data->apply_overdrive_next_settings_mask &
1727                         DPMTABLE_OD_UPDATE_VDDC)
1728                 dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
1729                                         &data->odn_dpm_table.vdd_dependency_on_mclk;
1730
1731         PP_ASSERT_WITH_CODE(dep_on_mclk,
1732                         "Invalid SOC_VDD-UCLK Dependency Table!",
1733                         return -EINVAL);
1734
1735         if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK)
1736                 mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock;
1737         else {
1738                 for (i = 0; i < dep_on_mclk->count; i++) {
1739                         if (dep_on_mclk->entries[i].clk == mem_clock)
1740                                 break;
1741                 }
1742                 PP_ASSERT_WITH_CODE(dep_on_mclk->count > i,
1743                                 "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!",
1744                                 return -EINVAL);
1745         }
1746
1747         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(
1748                         hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, &dividers),
1749                         "Failed to get UCLK settings from VBIOS!",
1750                         return -1);
1751
1752         *current_mem_vid =
1753                         (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd));
1754         *current_mem_soc_vind =
1755                         (uint8_t)(dep_on_mclk->entries[i].vddInd);
1756         current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult);
1757         current_memclk_level->Did = (uint8_t)(dividers.ulDid);
1758
1759         PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1,
1760                         "Invalid Divider ID!",
1761                         return -EINVAL);
1762
1763         return 0;
1764 }
1765
1766 /**
1767  * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states.
1768  *
1769  * @param    pHwMgr - the address of the hardware manager.
1770  * @return   PP_Result_OK on success.
1771  */
1772 static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
1773 {
1774         struct vega10_hwmgr *data =
1775                         (struct vega10_hwmgr *)(hwmgr->backend);
1776         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1777         struct vega10_single_dpm_table *dpm_table =
1778                         &(data->dpm_table.mem_table);
1779         int result = 0;
1780         uint32_t i, j, reg, mem_channels;
1781
1782         for (i = 0; i < dpm_table->count; i++) {
1783                 result = vega10_populate_single_memory_level(hwmgr,
1784                                 dpm_table->dpm_levels[i].value,
1785                                 &(pp_table->MemVid[i]),
1786                                 &(pp_table->UclkLevel[i]),
1787                                 &(pp_table->MemSocVoltageIndex[i]));
1788                 if (result)
1789                         return result;
1790         }
1791
1792         j = i - 1;
1793         while (i < NUM_UCLK_DPM_LEVELS) {
1794                 result = vega10_populate_single_memory_level(hwmgr,
1795                                 dpm_table->dpm_levels[j].value,
1796                                 &(pp_table->MemVid[i]),
1797                                 &(pp_table->UclkLevel[i]),
1798                                 &(pp_table->MemSocVoltageIndex[i]));
1799                 if (result)
1800                         return result;
1801                 i++;
1802         }
1803
1804         reg = soc15_get_register_offset(DF_HWID, 0,
1805                         mmDF_CS_AON0_DramBaseAddress0_BASE_IDX,
1806                         mmDF_CS_AON0_DramBaseAddress0);
1807         mem_channels = (cgs_read_register(hwmgr->device, reg) &
1808                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >>
1809                         DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT;
1810         PP_ASSERT_WITH_CODE(mem_channels < ARRAY_SIZE(channel_number),
1811                         "Mem Channel Index Exceeded maximum!",
1812                         return -1);
1813
1814         pp_table->NumMemoryChannels = cpu_to_le16(mem_channels);
1815         pp_table->MemoryChannelWidth =
1816                         cpu_to_le16(HBM_MEMORY_CHANNEL_WIDTH *
1817                                         channel_number[mem_channels]);
1818
1819         pp_table->LowestUclkReservedForUlv =
1820                         (uint8_t)(data->lowest_uclk_reserved_for_ulv);
1821
1822         return result;
1823 }
1824
1825 static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr,
1826                 DSPCLK_e disp_clock)
1827 {
1828         struct vega10_hwmgr *data =
1829                         (struct vega10_hwmgr *)(hwmgr->backend);
1830         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1831         struct phm_ppt_v2_information *table_info =
1832                         (struct phm_ppt_v2_information *)
1833                         (hwmgr->pptable);
1834         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
1835         uint32_t i;
1836         uint16_t clk = 0, vddc = 0;
1837         uint8_t vid = 0;
1838
1839         switch (disp_clock) {
1840         case DSPCLK_DCEFCLK:
1841                 dep_table = table_info->vdd_dep_on_dcefclk;
1842                 break;
1843         case DSPCLK_DISPCLK:
1844                 dep_table = table_info->vdd_dep_on_dispclk;
1845                 break;
1846         case DSPCLK_PIXCLK:
1847                 dep_table = table_info->vdd_dep_on_pixclk;
1848                 break;
1849         case DSPCLK_PHYCLK:
1850                 dep_table = table_info->vdd_dep_on_phyclk;
1851                 break;
1852         default:
1853                 return -1;
1854         }
1855
1856         PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS,
1857                         "Number Of Entries Exceeded maximum!",
1858                         return -1);
1859
1860         for (i = 0; i < dep_table->count; i++) {
1861                 clk = (uint16_t)(dep_table->entries[i].clk / 100);
1862                 vddc = table_info->vddc_lookup_table->
1863                                 entries[dep_table->entries[i].vddInd].us_vdd;
1864                 vid = (uint8_t)convert_to_vid(vddc);
1865                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1866                                 cpu_to_le16(clk);
1867                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1868                                 cpu_to_le16(vid);
1869         }
1870
1871         while (i < NUM_DSPCLK_LEVELS) {
1872                 pp_table->DisplayClockTable[disp_clock][i].Freq =
1873                                 cpu_to_le16(clk);
1874                 pp_table->DisplayClockTable[disp_clock][i].Vid =
1875                                 cpu_to_le16(vid);
1876                 i++;
1877         }
1878
1879         return 0;
1880 }
1881
1882 static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr)
1883 {
1884         uint32_t i;
1885
1886         for (i = 0; i < DSPCLK_COUNT; i++) {
1887                 PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i),
1888                                 "Failed to populate Clock in DisplayClockTable!",
1889                                 return -1);
1890         }
1891
1892         return 0;
1893 }
1894
1895 static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr,
1896                 uint32_t eclock, uint8_t *current_eclk_did,
1897                 uint8_t *current_soc_vol)
1898 {
1899         struct phm_ppt_v2_information *table_info =
1900                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1901         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1902                         table_info->mm_dep_table;
1903         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1904         uint32_t i;
1905
1906         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1907                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1908                         eclock, &dividers),
1909                         "Failed to get ECLK clock settings from VBIOS!",
1910                         return -1);
1911
1912         *current_eclk_did = (uint8_t)dividers.ulDid;
1913
1914         for (i = 0; i < dep_table->count; i++) {
1915                 if (dep_table->entries[i].eclk == eclock)
1916                         *current_soc_vol = dep_table->entries[i].vddcInd;
1917         }
1918
1919         return 0;
1920 }
1921
1922 static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr)
1923 {
1924         struct vega10_hwmgr *data =
1925                         (struct vega10_hwmgr *)(hwmgr->backend);
1926         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1927         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table);
1928         int result = -EINVAL;
1929         uint32_t i, j;
1930
1931         for (i = 0; i < dpm_table->count; i++) {
1932                 result = vega10_populate_single_eclock_level(hwmgr,
1933                                 dpm_table->dpm_levels[i].value,
1934                                 &(pp_table->EclkDid[i]),
1935                                 &(pp_table->VceDpmVoltageIndex[i]));
1936                 if (result)
1937                         return result;
1938         }
1939
1940         j = i - 1;
1941         while (i < NUM_VCE_DPM_LEVELS) {
1942                 result = vega10_populate_single_eclock_level(hwmgr,
1943                                 dpm_table->dpm_levels[j].value,
1944                                 &(pp_table->EclkDid[i]),
1945                                 &(pp_table->VceDpmVoltageIndex[i]));
1946                 if (result)
1947                         return result;
1948                 i++;
1949         }
1950
1951         return result;
1952 }
1953
1954 static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr,
1955                 uint32_t vclock, uint8_t *current_vclk_did)
1956 {
1957         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1958
1959         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1960                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1961                         vclock, &dividers),
1962                         "Failed to get VCLK clock settings from VBIOS!",
1963                         return -EINVAL);
1964
1965         *current_vclk_did = (uint8_t)dividers.ulDid;
1966
1967         return 0;
1968 }
1969
1970 static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr,
1971                 uint32_t dclock, uint8_t *current_dclk_did)
1972 {
1973         struct pp_atomfwctrl_clock_dividers_soc15 dividers;
1974
1975         PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
1976                         COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
1977                         dclock, &dividers),
1978                         "Failed to get DCLK clock settings from VBIOS!",
1979                         return -EINVAL);
1980
1981         *current_dclk_did = (uint8_t)dividers.ulDid;
1982
1983         return 0;
1984 }
1985
1986 static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr)
1987 {
1988         struct vega10_hwmgr *data =
1989                         (struct vega10_hwmgr *)(hwmgr->backend);
1990         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
1991         struct vega10_single_dpm_table *vclk_dpm_table =
1992                         &(data->dpm_table.vclk_table);
1993         struct vega10_single_dpm_table *dclk_dpm_table =
1994                         &(data->dpm_table.dclk_table);
1995         struct phm_ppt_v2_information *table_info =
1996                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
1997         struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table =
1998                         table_info->mm_dep_table;
1999         int result = -EINVAL;
2000         uint32_t i, j;
2001
2002         for (i = 0; i < vclk_dpm_table->count; i++) {
2003                 result = vega10_populate_single_vclock_level(hwmgr,
2004                                 vclk_dpm_table->dpm_levels[i].value,
2005                                 &(pp_table->VclkDid[i]));
2006                 if (result)
2007                         return result;
2008         }
2009
2010         j = i - 1;
2011         while (i < NUM_UVD_DPM_LEVELS) {
2012                 result = vega10_populate_single_vclock_level(hwmgr,
2013                                 vclk_dpm_table->dpm_levels[j].value,
2014                                 &(pp_table->VclkDid[i]));
2015                 if (result)
2016                         return result;
2017                 i++;
2018         }
2019
2020         for (i = 0; i < dclk_dpm_table->count; i++) {
2021                 result = vega10_populate_single_dclock_level(hwmgr,
2022                                 dclk_dpm_table->dpm_levels[i].value,
2023                                 &(pp_table->DclkDid[i]));
2024                 if (result)
2025                         return result;
2026         }
2027
2028         j = i - 1;
2029         while (i < NUM_UVD_DPM_LEVELS) {
2030                 result = vega10_populate_single_dclock_level(hwmgr,
2031                                 dclk_dpm_table->dpm_levels[j].value,
2032                                 &(pp_table->DclkDid[i]));
2033                 if (result)
2034                         return result;
2035                 i++;
2036         }
2037
2038         for (i = 0; i < dep_table->count; i++) {
2039                 if (dep_table->entries[i].vclk ==
2040                                 vclk_dpm_table->dpm_levels[i].value &&
2041                         dep_table->entries[i].dclk ==
2042                                 dclk_dpm_table->dpm_levels[i].value)
2043                         pp_table->UvdDpmVoltageIndex[i] =
2044                                         dep_table->entries[i].vddcInd;
2045                 else
2046                         return -1;
2047         }
2048
2049         j = i - 1;
2050         while (i < NUM_UVD_DPM_LEVELS) {
2051                 pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd;
2052                 i++;
2053         }
2054
2055         return 0;
2056 }
2057
2058 static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr)
2059 {
2060         struct vega10_hwmgr *data =
2061                         (struct vega10_hwmgr *)(hwmgr->backend);
2062         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2063         struct phm_ppt_v2_information *table_info =
2064                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2065         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2066                         table_info->vdd_dep_on_sclk;
2067         uint32_t i;
2068
2069         for (i = 0; i < dep_table->count; i++) {
2070                 pp_table->CksEnable[i] = dep_table->entries[i].cks_enable;
2071                 pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset
2072                                 * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
2073         }
2074
2075         return 0;
2076 }
2077
2078 static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
2079 {
2080         struct vega10_hwmgr *data =
2081                         (struct vega10_hwmgr *)(hwmgr->backend);
2082         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2083         struct phm_ppt_v2_information *table_info =
2084                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2085         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
2086                         table_info->vdd_dep_on_sclk;
2087         struct pp_atomfwctrl_avfs_parameters avfs_params = {0};
2088         int result = 0;
2089         uint32_t i;
2090
2091         pp_table->MinVoltageVid = (uint8_t)0xff;
2092         pp_table->MaxVoltageVid = (uint8_t)0;
2093
2094         if (data->smu_features[GNLD_AVFS].supported) {
2095                 result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
2096                 if (!result) {
2097                         pp_table->MinVoltageVid = (uint8_t)
2098                                         convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
2099                         pp_table->MaxVoltageVid = (uint8_t)
2100                                         convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
2101
2102                         pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
2103                         pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
2104                         pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
2105                         pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2106                         pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
2107                         pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
2108                         pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor);
2109
2110                         pp_table->BtcGbVdroopTableCksOff.a0 =
2111                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0);
2112                         pp_table->BtcGbVdroopTableCksOff.a0_shift = 20;
2113                         pp_table->BtcGbVdroopTableCksOff.a1 =
2114                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1);
2115                         pp_table->BtcGbVdroopTableCksOff.a1_shift = 20;
2116                         pp_table->BtcGbVdroopTableCksOff.a2 =
2117                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2);
2118                         pp_table->BtcGbVdroopTableCksOff.a2_shift = 20;
2119
2120                         pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson;
2121                         pp_table->BtcGbVdroopTableCksOn.a0 =
2122                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
2123                         pp_table->BtcGbVdroopTableCksOn.a0_shift = 20;
2124                         pp_table->BtcGbVdroopTableCksOn.a1 =
2125                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
2126                         pp_table->BtcGbVdroopTableCksOn.a1_shift = 20;
2127                         pp_table->BtcGbVdroopTableCksOn.a2 =
2128                                         cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
2129                         pp_table->BtcGbVdroopTableCksOn.a2_shift = 20;
2130
2131                         pp_table->AvfsGbCksOn.m1 =
2132                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM1);
2133                         pp_table->AvfsGbCksOn.m2 =
2134                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonM2);
2135                         pp_table->AvfsGbCksOn.b =
2136                                         cpu_to_le32(avfs_params.ulGbFuseTableCksonB);
2137                         pp_table->AvfsGbCksOn.m1_shift = 24;
2138                         pp_table->AvfsGbCksOn.m2_shift = 12;
2139                         pp_table->AvfsGbCksOn.b_shift = 0;
2140
2141                         pp_table->OverrideAvfsGbCksOn =
2142                                         avfs_params.ucEnableGbFuseTableCkson;
2143                         pp_table->AvfsGbCksOff.m1 =
2144                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1);
2145                         pp_table->AvfsGbCksOff.m2 =
2146                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2);
2147                         pp_table->AvfsGbCksOff.b =
2148                                         cpu_to_le32(avfs_params.ulGbFuseTableCksoffB);
2149                         pp_table->AvfsGbCksOff.m1_shift = 24;
2150                         pp_table->AvfsGbCksOff.m2_shift = 12;
2151                         pp_table->AvfsGbCksOff.b_shift = 0;
2152
2153                         for (i = 0; i < dep_table->count; i++)
2154                                 pp_table->StaticVoltageOffsetVid[i] =
2155                                                 convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset));
2156
2157                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2158                                         data->disp_clk_quad_eqn_a) &&
2159                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2160                                         data->disp_clk_quad_eqn_b)) {
2161                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2162                                                 (int32_t)data->disp_clk_quad_eqn_a;
2163                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2164                                                 (int32_t)data->disp_clk_quad_eqn_b;
2165                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2166                                                 (int32_t)data->disp_clk_quad_eqn_c;
2167                         } else {
2168                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
2169                                                 (int32_t)avfs_params.ulDispclk2GfxclkM1;
2170                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
2171                                                 (int32_t)avfs_params.ulDispclk2GfxclkM2;
2172                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
2173                                                 (int32_t)avfs_params.ulDispclk2GfxclkB;
2174                         }
2175
2176                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24;
2177                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12;
2178                         pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12;
2179
2180                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2181                                         data->dcef_clk_quad_eqn_a) &&
2182                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2183                                         data->dcef_clk_quad_eqn_b)) {
2184                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2185                                                 (int32_t)data->dcef_clk_quad_eqn_a;
2186                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2187                                                 (int32_t)data->dcef_clk_quad_eqn_b;
2188                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2189                                                 (int32_t)data->dcef_clk_quad_eqn_c;
2190                         } else {
2191                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
2192                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM1;
2193                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
2194                                                 (int32_t)avfs_params.ulDcefclk2GfxclkM2;
2195                                 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
2196                                                 (int32_t)avfs_params.ulDcefclk2GfxclkB;
2197                         }
2198
2199                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24;
2200                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12;
2201                         pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12;
2202
2203                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2204                                         data->pixel_clk_quad_eqn_a) &&
2205                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2206                                         data->pixel_clk_quad_eqn_b)) {
2207                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2208                                                 (int32_t)data->pixel_clk_quad_eqn_a;
2209                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2210                                                 (int32_t)data->pixel_clk_quad_eqn_b;
2211                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2212                                                 (int32_t)data->pixel_clk_quad_eqn_c;
2213                         } else {
2214                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
2215                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM1;
2216                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
2217                                                 (int32_t)avfs_params.ulPixelclk2GfxclkM2;
2218                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
2219                                                 (int32_t)avfs_params.ulPixelclk2GfxclkB;
2220                         }
2221
2222                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24;
2223                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12;
2224                         pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12;
2225                         if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2226                                         data->phy_clk_quad_eqn_a) &&
2227                                 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
2228                                         data->phy_clk_quad_eqn_b)) {
2229                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2230                                                 (int32_t)data->phy_clk_quad_eqn_a;
2231                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2232                                                 (int32_t)data->phy_clk_quad_eqn_b;
2233                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2234                                                 (int32_t)data->phy_clk_quad_eqn_c;
2235                         } else {
2236                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
2237                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM1;
2238                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
2239                                                 (int32_t)avfs_params.ulPhyclk2GfxclkM2;
2240                                 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
2241                                                 (int32_t)avfs_params.ulPhyclk2GfxclkB;
2242                         }
2243
2244                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24;
2245                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12;
2246                         pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12;
2247
2248                         pp_table->AcgBtcGbVdroopTable.a0       = avfs_params.ulAcgGbVdroopTableA0;
2249                         pp_table->AcgBtcGbVdroopTable.a0_shift = 20;
2250                         pp_table->AcgBtcGbVdroopTable.a1       = avfs_params.ulAcgGbVdroopTableA1;
2251                         pp_table->AcgBtcGbVdroopTable.a1_shift = 20;
2252                         pp_table->AcgBtcGbVdroopTable.a2       = avfs_params.ulAcgGbVdroopTableA2;
2253                         pp_table->AcgBtcGbVdroopTable.a2_shift = 20;
2254
2255                         pp_table->AcgAvfsGb.m1                   = avfs_params.ulAcgGbFuseTableM1;
2256                         pp_table->AcgAvfsGb.m2                   = avfs_params.ulAcgGbFuseTableM2;
2257                         pp_table->AcgAvfsGb.b                    = avfs_params.ulAcgGbFuseTableB;
2258                         pp_table->AcgAvfsGb.m1_shift             = 0;
2259                         pp_table->AcgAvfsGb.m2_shift             = 0;
2260                         pp_table->AcgAvfsGb.b_shift              = 0;
2261
2262                 } else {
2263                         data->smu_features[GNLD_AVFS].supported = false;
2264                 }
2265         }
2266
2267         return 0;
2268 }
2269
2270 static int vega10_acg_enable(struct pp_hwmgr *hwmgr)
2271 {
2272         struct vega10_hwmgr *data =
2273                         (struct vega10_hwmgr *)(hwmgr->backend);
2274         uint32_t agc_btc_response;
2275
2276         if (data->smu_features[GNLD_ACG].supported) {
2277                 if (0 == vega10_enable_smc_features(hwmgr, true,
2278                                         data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap))
2279                         data->smu_features[GNLD_DPM_PREFETCHER].enabled = true;
2280
2281                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg);
2282
2283                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc);
2284                 vega10_read_arg_from_smc(hwmgr, &agc_btc_response);
2285
2286                 if (1 == agc_btc_response) {
2287                         if (1 == data->acg_loop_state)
2288                                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop);
2289                         else if (2 == data->acg_loop_state)
2290                                 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop);
2291                         if (0 == vega10_enable_smc_features(hwmgr, true,
2292                                 data->smu_features[GNLD_ACG].smu_feature_bitmap))
2293                                         data->smu_features[GNLD_ACG].enabled = true;
2294                 } else {
2295                         pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n");
2296                         data->smu_features[GNLD_ACG].enabled = false;
2297                 }
2298         }
2299
2300         return 0;
2301 }
2302
2303 static int vega10_acg_disable(struct pp_hwmgr *hwmgr)
2304 {
2305         struct vega10_hwmgr *data =
2306                         (struct vega10_hwmgr *)(hwmgr->backend);
2307
2308         if (data->smu_features[GNLD_ACG].supported && 
2309             data->smu_features[GNLD_ACG].enabled)
2310                 if (!vega10_enable_smc_features(hwmgr, false,
2311                         data->smu_features[GNLD_ACG].smu_feature_bitmap))
2312                         data->smu_features[GNLD_ACG].enabled = false;
2313
2314         return 0;
2315 }
2316
2317 static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr)
2318 {
2319         struct vega10_hwmgr *data =
2320                         (struct vega10_hwmgr *)(hwmgr->backend);
2321         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2322         struct pp_atomfwctrl_gpio_parameters gpio_params = {0};
2323         int result;
2324
2325         result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params);
2326         if (!result) {
2327                 if (PP_CAP(PHM_PlatformCaps_RegulatorHot) &&
2328                     data->registry_data.regulator_hot_gpio_support) {
2329                         pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio;
2330                         pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity;
2331                         pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio;
2332                         pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity;
2333                 } else {
2334                         pp_table->VR0HotGpio = 0;
2335                         pp_table->VR0HotPolarity = 0;
2336                         pp_table->VR1HotGpio = 0;
2337                         pp_table->VR1HotPolarity = 0;
2338                 }
2339
2340                 if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) &&
2341                     data->registry_data.ac_dc_switch_gpio_support) {
2342                         pp_table->AcDcGpio = gpio_params.ucAcDcGpio;
2343                         pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity;
2344                 } else {
2345                         pp_table->AcDcGpio = 0;
2346                         pp_table->AcDcPolarity = 0;
2347                 }
2348         }
2349
2350         return result;
2351 }
2352
2353 static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable)
2354 {
2355         struct vega10_hwmgr *data =
2356                         (struct vega10_hwmgr *)(hwmgr->backend);
2357
2358         if (data->smu_features[GNLD_AVFS].supported) {
2359                 if (enable) {
2360                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2361                                         true,
2362                                         data->smu_features[GNLD_AVFS].smu_feature_bitmap),
2363                                         "[avfs_control] Attempt to Enable AVFS feature Failed!",
2364                                         return -1);
2365                         data->smu_features[GNLD_AVFS].enabled = true;
2366                 } else {
2367                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2368                                         false,
2369                                         data->smu_features[GNLD_AVFS].smu_feature_bitmap),
2370                                         "[avfs_control] Attempt to Disable AVFS feature Failed!",
2371                                         return -1);
2372                         data->smu_features[GNLD_AVFS].enabled = false;
2373                 }
2374         }
2375
2376         return 0;
2377 }
2378
2379 static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
2380 {
2381         int result = 0;
2382
2383         uint64_t serial_number = 0;
2384         uint32_t top32, bottom32;
2385         struct phm_fuses_default fuse;
2386
2387         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2388         AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table);
2389
2390         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32);
2391         vega10_read_arg_from_smc(hwmgr, &top32);
2392
2393         smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32);
2394         vega10_read_arg_from_smc(hwmgr, &bottom32);
2395
2396         serial_number = ((uint64_t)bottom32 << 32) | top32;
2397
2398         if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) {
2399                 avfs_fuse_table->VFT0_b  = fuse.VFT0_b;
2400                 avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1;
2401                 avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2;
2402                 avfs_fuse_table->VFT1_b  = fuse.VFT1_b;
2403                 avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1;
2404                 avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2;
2405                 avfs_fuse_table->VFT2_b  = fuse.VFT2_b;
2406                 avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1;
2407                 avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2;
2408                 result = vega10_copy_table_to_smc(hwmgr,
2409                         (uint8_t *)avfs_fuse_table, AVFSFUSETABLE);
2410                 PP_ASSERT_WITH_CODE(!result,
2411                         "Failed to upload FuseOVerride!",
2412                         );
2413         }
2414
2415         return result;
2416 }
2417
2418 static int vega10_save_default_power_profile(struct pp_hwmgr *hwmgr)
2419 {
2420         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2421         struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2422         uint32_t min_level;
2423
2424         hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
2425         hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
2426
2427         /* Optimize compute power profile: Use only highest
2428          * 2 power levels (if more than 2 are available)
2429          */
2430         if (dpm_table->count > 2)
2431                 min_level = dpm_table->count - 2;
2432         else if (dpm_table->count == 2)
2433                 min_level = 1;
2434         else
2435                 min_level = 0;
2436
2437         hwmgr->default_compute_power_profile.min_sclk =
2438                         dpm_table->dpm_levels[min_level].value;
2439
2440         hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
2441         hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
2442
2443         return 0;
2444 }
2445
2446 /**
2447 * Initializes the SMC table and uploads it
2448 *
2449 * @param    hwmgr  the address of the powerplay hardware manager.
2450 * @param    pInput  the pointer to input data (PowerState)
2451 * @return   always 0
2452 */
2453 static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
2454 {
2455         int result;
2456         struct vega10_hwmgr *data =
2457                         (struct vega10_hwmgr *)(hwmgr->backend);
2458         struct phm_ppt_v2_information *table_info =
2459                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2460         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
2461         struct pp_atomfwctrl_voltage_table voltage_table;
2462         struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
2463
2464         result = vega10_setup_default_dpm_tables(hwmgr);
2465         PP_ASSERT_WITH_CODE(!result,
2466                         "Failed to setup default DPM tables!",
2467                         return result);
2468
2469         pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC,
2470                         VOLTAGE_OBJ_SVID2,  &voltage_table);
2471         pp_table->MaxVidStep = voltage_table.max_vid_step;
2472
2473         pp_table->GfxDpmVoltageMode =
2474                         (uint8_t)(table_info->uc_gfx_dpm_voltage_mode);
2475         pp_table->SocDpmVoltageMode =
2476                         (uint8_t)(table_info->uc_soc_dpm_voltage_mode);
2477         pp_table->UclkDpmVoltageMode =
2478                         (uint8_t)(table_info->uc_uclk_dpm_voltage_mode);
2479         pp_table->UvdDpmVoltageMode =
2480                         (uint8_t)(table_info->uc_uvd_dpm_voltage_mode);
2481         pp_table->VceDpmVoltageMode =
2482                         (uint8_t)(table_info->uc_vce_dpm_voltage_mode);
2483         pp_table->Mp0DpmVoltageMode =
2484                         (uint8_t)(table_info->uc_mp0_dpm_voltage_mode);
2485
2486         pp_table->DisplayDpmVoltageMode =
2487                         (uint8_t)(table_info->uc_dcef_dpm_voltage_mode);
2488
2489         data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable;
2490         data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable;
2491
2492         if (data->registry_data.ulv_support &&
2493                         table_info->us_ulv_voltage_offset) {
2494                 result = vega10_populate_ulv_state(hwmgr);
2495                 PP_ASSERT_WITH_CODE(!result,
2496                                 "Failed to initialize ULV state!",
2497                                 return result);
2498         }
2499
2500         result = vega10_populate_smc_link_levels(hwmgr);
2501         PP_ASSERT_WITH_CODE(!result,
2502                         "Failed to initialize Link Level!",
2503                         return result);
2504
2505         result = vega10_populate_all_graphic_levels(hwmgr);
2506         PP_ASSERT_WITH_CODE(!result,
2507                         "Failed to initialize Graphics Level!",
2508                         return result);
2509
2510         result = vega10_populate_all_memory_levels(hwmgr);
2511         PP_ASSERT_WITH_CODE(!result,
2512                         "Failed to initialize Memory Level!",
2513                         return result);
2514
2515         result = vega10_populate_all_display_clock_levels(hwmgr);
2516         PP_ASSERT_WITH_CODE(!result,
2517                         "Failed to initialize Display Level!",
2518                         return result);
2519
2520         result = vega10_populate_smc_vce_levels(hwmgr);
2521         PP_ASSERT_WITH_CODE(!result,
2522                         "Failed to initialize VCE Level!",
2523                         return result);
2524
2525         result = vega10_populate_smc_uvd_levels(hwmgr);
2526         PP_ASSERT_WITH_CODE(!result,
2527                         "Failed to initialize UVD Level!",
2528                         return result);
2529
2530         if (data->registry_data.clock_stretcher_support) {
2531                 result = vega10_populate_clock_stretcher_table(hwmgr);
2532                 PP_ASSERT_WITH_CODE(!result,
2533                                 "Failed to populate Clock Stretcher Table!",
2534                                 return result);
2535         }
2536
2537         result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
2538         if (!result) {
2539                 data->vbios_boot_state.vddc     = boot_up_values.usVddc;
2540                 data->vbios_boot_state.vddci    = boot_up_values.usVddci;
2541                 data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
2542                 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
2543                 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
2544                 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
2545                 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
2546                 if (0 != boot_up_values.usVddc) {
2547                         smum_send_msg_to_smc_with_parameter(hwmgr,
2548                                                 PPSMC_MSG_SetFloorSocVoltage,
2549                                                 (boot_up_values.usVddc * 4));
2550                         data->vbios_boot_state.bsoc_vddc_lock = true;
2551                 } else {
2552                         data->vbios_boot_state.bsoc_vddc_lock = false;
2553                 }
2554                 smum_send_msg_to_smc_with_parameter(hwmgr,
2555                                 PPSMC_MSG_SetMinDeepSleepDcefclk,
2556                         (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
2557         }
2558
2559         result = vega10_populate_avfs_parameters(hwmgr);
2560         PP_ASSERT_WITH_CODE(!result,
2561                         "Failed to initialize AVFS Parameters!",
2562                         return result);
2563
2564         result = vega10_populate_gpio_parameters(hwmgr);
2565         PP_ASSERT_WITH_CODE(!result,
2566                         "Failed to initialize GPIO Parameters!",
2567                         return result);
2568
2569         pp_table->GfxclkAverageAlpha = (uint8_t)
2570                         (data->gfxclk_average_alpha);
2571         pp_table->SocclkAverageAlpha = (uint8_t)
2572                         (data->socclk_average_alpha);
2573         pp_table->UclkAverageAlpha = (uint8_t)
2574                         (data->uclk_average_alpha);
2575         pp_table->GfxActivityAverageAlpha = (uint8_t)
2576                         (data->gfx_activity_average_alpha);
2577
2578         vega10_populate_and_upload_avfs_fuse_override(hwmgr);
2579
2580         result = vega10_copy_table_to_smc(hwmgr,
2581                         (uint8_t *)pp_table, PPTABLE);
2582         PP_ASSERT_WITH_CODE(!result,
2583                         "Failed to upload PPtable!", return result);
2584
2585         result = vega10_avfs_enable(hwmgr, true);
2586         PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
2587                                         return result);
2588         vega10_acg_enable(hwmgr);
2589         vega10_save_default_power_profile(hwmgr);
2590
2591         return 0;
2592 }
2593
2594 static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
2595 {
2596         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2597
2598         if (data->smu_features[GNLD_THERMAL].supported) {
2599                 if (data->smu_features[GNLD_THERMAL].enabled)
2600                         pr_info("THERMAL Feature Already enabled!");
2601
2602                 PP_ASSERT_WITH_CODE(
2603                                 !vega10_enable_smc_features(hwmgr,
2604                                 true,
2605                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2606                                 "Enable THERMAL Feature Failed!",
2607                                 return -1);
2608                 data->smu_features[GNLD_THERMAL].enabled = true;
2609         }
2610
2611         return 0;
2612 }
2613
2614 static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr)
2615 {
2616         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2617
2618         if (data->smu_features[GNLD_THERMAL].supported) {
2619                 if (!data->smu_features[GNLD_THERMAL].enabled)
2620                         pr_info("THERMAL Feature Already disabled!");
2621
2622                 PP_ASSERT_WITH_CODE(
2623                                 !vega10_enable_smc_features(hwmgr,
2624                                 false,
2625                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2626                                 "disable THERMAL Feature Failed!",
2627                                 return -1);
2628                 data->smu_features[GNLD_THERMAL].enabled = false;
2629         }
2630
2631         return 0;
2632 }
2633
2634 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
2635 {
2636         struct vega10_hwmgr *data =
2637                         (struct vega10_hwmgr *)(hwmgr->backend);
2638
2639         if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) {
2640                 if (data->smu_features[GNLD_VR0HOT].supported) {
2641                         PP_ASSERT_WITH_CODE(
2642                                         !vega10_enable_smc_features(hwmgr,
2643                                         true,
2644                                         data->smu_features[GNLD_VR0HOT].smu_feature_bitmap),
2645                                         "Attempt to Enable VR0 Hot feature Failed!",
2646                                         return -1);
2647                         data->smu_features[GNLD_VR0HOT].enabled = true;
2648                 } else {
2649                         if (data->smu_features[GNLD_VR1HOT].supported) {
2650                                 PP_ASSERT_WITH_CODE(
2651                                                 !vega10_enable_smc_features(hwmgr,
2652                                                 true,
2653                                                 data->smu_features[GNLD_VR1HOT].smu_feature_bitmap),
2654                                                 "Attempt to Enable VR0 Hot feature Failed!",
2655                                                 return -1);
2656                                 data->smu_features[GNLD_VR1HOT].enabled = true;
2657                         }
2658                 }
2659         }
2660         return 0;
2661 }
2662
2663 static int vega10_enable_ulv(struct pp_hwmgr *hwmgr)
2664 {
2665         struct vega10_hwmgr *data =
2666                         (struct vega10_hwmgr *)(hwmgr->backend);
2667
2668         if (data->registry_data.ulv_support) {
2669                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2670                                 true, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2671                                 "Enable ULV Feature Failed!",
2672                                 return -1);
2673                 data->smu_features[GNLD_ULV].enabled = true;
2674         }
2675
2676         return 0;
2677 }
2678
2679 static int vega10_disable_ulv(struct pp_hwmgr *hwmgr)
2680 {
2681         struct vega10_hwmgr *data =
2682                         (struct vega10_hwmgr *)(hwmgr->backend);
2683
2684         if (data->registry_data.ulv_support) {
2685                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2686                                 false, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2687                                 "disable ULV Feature Failed!",
2688                                 return -EINVAL);
2689                 data->smu_features[GNLD_ULV].enabled = false;
2690         }
2691
2692         return 0;
2693 }
2694
2695 static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2696 {
2697         struct vega10_hwmgr *data =
2698                         (struct vega10_hwmgr *)(hwmgr->backend);
2699
2700         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2701                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2702                                 true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2703                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2704                                 return -EINVAL);
2705                 data->smu_features[GNLD_DS_GFXCLK].enabled = true;
2706         }
2707
2708         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2709                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2710                                 true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2711                                 "Attempt to Enable DS_SOCCLK Feature Failed!",
2712                                 return -EINVAL);
2713                 data->smu_features[GNLD_DS_SOCCLK].enabled = true;
2714         }
2715
2716         if (data->smu_features[GNLD_DS_LCLK].supported) {
2717                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2718                                 true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2719                                 "Attempt to Enable DS_LCLK Feature Failed!",
2720                                 return -EINVAL);
2721                 data->smu_features[GNLD_DS_LCLK].enabled = true;
2722         }
2723
2724         if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
2725                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2726                                 true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap),
2727                                 "Attempt to Enable DS_DCEFCLK Feature Failed!",
2728                                 return -EINVAL);
2729                 data->smu_features[GNLD_DS_DCEFCLK].enabled = true;
2730         }
2731
2732         return 0;
2733 }
2734
2735 static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2736 {
2737         struct vega10_hwmgr *data =
2738                         (struct vega10_hwmgr *)(hwmgr->backend);
2739
2740         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2741                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2742                                 false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2743                                 "Attempt to disable DS_GFXCLK Feature Failed!",
2744                                 return -EINVAL);
2745                 data->smu_features[GNLD_DS_GFXCLK].enabled = false;
2746         }
2747
2748         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2749                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2750                                 false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2751                                 "Attempt to disable DS_ Feature Failed!",
2752                                 return -EINVAL);
2753                 data->smu_features[GNLD_DS_SOCCLK].enabled = false;
2754         }
2755
2756         if (data->smu_features[GNLD_DS_LCLK].supported) {
2757                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2758                                 false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2759                                 "Attempt to disable DS_LCLK Feature Failed!",
2760                                 return -EINVAL);
2761                 data->smu_features[GNLD_DS_LCLK].enabled = false;
2762         }
2763
2764         if (data->smu_features[GNLD_DS_DCEFCLK].supported) {
2765                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2766                                 false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap),
2767                                 "Attempt to disable DS_DCEFCLK Feature Failed!",
2768                                 return -EINVAL);
2769                 data->smu_features[GNLD_DS_DCEFCLK].enabled = false;
2770         }
2771
2772         return 0;
2773 }
2774
2775 static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2776 {
2777         struct vega10_hwmgr *data =
2778                         (struct vega10_hwmgr *)(hwmgr->backend);
2779         uint32_t i, feature_mask = 0;
2780
2781
2782         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2783                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2784                                 false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2785                 "Attempt to disable LED DPM feature failed!", return -EINVAL);
2786                 data->smu_features[GNLD_LED_DISPLAY].enabled = false;
2787         }
2788
2789         for (i = 0; i < GNLD_DPM_MAX; i++) {
2790                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2791                         if (data->smu_features[i].supported) {
2792                                 if (data->smu_features[i].enabled) {
2793                                         feature_mask |= data->smu_features[i].
2794                                                         smu_feature_bitmap;
2795                                         data->smu_features[i].enabled = false;
2796                                 }
2797                         }
2798                 }
2799         }
2800
2801         vega10_enable_smc_features(hwmgr, false, feature_mask);
2802
2803         return 0;
2804 }
2805
2806 /**
2807  * @brief Tell SMC to enabled the supported DPMs.
2808  *
2809  * @param    hwmgr - the address of the powerplay hardware manager.
2810  * @Param    bitmap - bitmap for the features to enabled.
2811  * @return   0 on at least one DPM is successfully enabled.
2812  */
2813 static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2814 {
2815         struct vega10_hwmgr *data =
2816                         (struct vega10_hwmgr *)(hwmgr->backend);
2817         uint32_t i, feature_mask = 0;
2818
2819         for (i = 0; i < GNLD_DPM_MAX; i++) {
2820                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2821                         if (data->smu_features[i].supported) {
2822                                 if (!data->smu_features[i].enabled) {
2823                                         feature_mask |= data->smu_features[i].
2824                                                         smu_feature_bitmap;
2825                                         data->smu_features[i].enabled = true;
2826                                 }
2827                         }
2828                 }
2829         }
2830
2831         if (vega10_enable_smc_features(hwmgr,
2832                         true, feature_mask)) {
2833                 for (i = 0; i < GNLD_DPM_MAX; i++) {
2834                         if (data->smu_features[i].smu_feature_bitmap &
2835                                         feature_mask)
2836                                 data->smu_features[i].enabled = false;
2837                 }
2838         }
2839
2840         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2841                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2842                                 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2843                 "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
2844                 data->smu_features[GNLD_LED_DISPLAY].enabled = true;
2845         }
2846
2847         if (data->vbios_boot_state.bsoc_vddc_lock) {
2848                 smum_send_msg_to_smc_with_parameter(hwmgr,
2849                                                 PPSMC_MSG_SetFloorSocVoltage, 0);
2850                 data->vbios_boot_state.bsoc_vddc_lock = false;
2851         }
2852
2853         if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) {
2854                 if (data->smu_features[GNLD_ACDC].supported) {
2855                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
2856                                         true, data->smu_features[GNLD_ACDC].smu_feature_bitmap),
2857                                         "Attempt to Enable DS_GFXCLK Feature Failed!",
2858                                         return -1);
2859                         data->smu_features[GNLD_ACDC].enabled = true;
2860                 }
2861         }
2862
2863         return 0;
2864 }
2865
2866 static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
2867 {
2868         struct vega10_hwmgr *data =
2869                         (struct vega10_hwmgr *)(hwmgr->backend);
2870         int tmp_result, result = 0;
2871
2872         tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr,
2873                         PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
2874         PP_ASSERT_WITH_CODE(!tmp_result,
2875                         "Failed to configure telemetry!",
2876                         return tmp_result);
2877
2878         smum_send_msg_to_smc_with_parameter(hwmgr,
2879                         PPSMC_MSG_NumOfDisplays, 0);
2880
2881         tmp_result = (!vega10_is_dpm_running(hwmgr)) ? 0 : -1;
2882         PP_ASSERT_WITH_CODE(!tmp_result,
2883                         "DPM is already running right , skipping re-enablement!",
2884                         return 0);
2885
2886         if ((data->smu_version == 0x001c2c00) ||
2887                         (data->smu_version == 0x001c2d00)) {
2888                 tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr,
2889                                 PPSMC_MSG_UpdatePkgPwrPidAlpha, 1);
2890                 PP_ASSERT_WITH_CODE(!tmp_result,
2891                                 "Failed to set package power PID!",
2892                                 return tmp_result);
2893         }
2894
2895         tmp_result = vega10_construct_voltage_tables(hwmgr);
2896         PP_ASSERT_WITH_CODE(!tmp_result,
2897                         "Failed to contruct voltage tables!",
2898                         result = tmp_result);
2899
2900         tmp_result = vega10_init_smc_table(hwmgr);
2901