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