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