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