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