]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drm/amd/powerplay: enable AGM logging while dpm disabled.
[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         result = vega10_avfs_enable(hwmgr, true);
2415         PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
2416                                         return result);
2417
2418         return 0;
2419 }
2420
2421 static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
2422 {
2423         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2424
2425         if (data->smu_features[GNLD_THERMAL].supported) {
2426                 if (data->smu_features[GNLD_THERMAL].enabled)
2427                         pr_info("THERMAL Feature Already enabled!");
2428
2429                 PP_ASSERT_WITH_CODE(
2430                                 !vega10_enable_smc_features(hwmgr->smumgr,
2431                                 true,
2432                                 data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
2433                                 "Enable THERMAL Feature Failed!",
2434                                 return -1);
2435                 data->smu_features[GNLD_THERMAL].enabled = true;
2436         }
2437
2438         return 0;
2439 }
2440
2441 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
2442 {
2443         struct vega10_hwmgr *data =
2444                         (struct vega10_hwmgr *)(hwmgr->backend);
2445
2446         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2447                         PHM_PlatformCaps_RegulatorHot)) {
2448                 if (data->smu_features[GNLD_VR0HOT].supported) {
2449                         PP_ASSERT_WITH_CODE(
2450                                         !vega10_enable_smc_features(hwmgr->smumgr,
2451                                         true,
2452                                         data->smu_features[GNLD_VR0HOT].smu_feature_bitmap),
2453                                         "Attempt to Enable VR0 Hot feature Failed!",
2454                                         return -1);
2455                         data->smu_features[GNLD_VR0HOT].enabled = true;
2456                 } else {
2457                         if (data->smu_features[GNLD_VR1HOT].supported) {
2458                                 PP_ASSERT_WITH_CODE(
2459                                                 !vega10_enable_smc_features(hwmgr->smumgr,
2460                                                 true,
2461                                                 data->smu_features[GNLD_VR1HOT].smu_feature_bitmap),
2462                                                 "Attempt to Enable VR0 Hot feature Failed!",
2463                                                 return -1);
2464                                 data->smu_features[GNLD_VR1HOT].enabled = true;
2465                         }
2466                 }
2467         }
2468         return 0;
2469 }
2470
2471 static int vega10_enable_ulv(struct pp_hwmgr *hwmgr)
2472 {
2473         struct vega10_hwmgr *data =
2474                         (struct vega10_hwmgr *)(hwmgr->backend);
2475
2476         if (data->registry_data.ulv_support) {
2477                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2478                                 true, data->smu_features[GNLD_ULV].smu_feature_bitmap),
2479                                 "Enable ULV Feature Failed!",
2480                                 return -1);
2481                 data->smu_features[GNLD_ULV].enabled = true;
2482         }
2483
2484         return 0;
2485 }
2486
2487 static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
2488 {
2489         struct vega10_hwmgr *data =
2490                         (struct vega10_hwmgr *)(hwmgr->backend);
2491
2492         if (data->smu_features[GNLD_DS_GFXCLK].supported) {
2493                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2494                                 true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap),
2495                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2496                                 return -1);
2497                 data->smu_features[GNLD_DS_GFXCLK].enabled = true;
2498         }
2499
2500         if (data->smu_features[GNLD_DS_SOCCLK].supported) {
2501                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2502                                 true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap),
2503                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2504                                 return -1);
2505                 data->smu_features[GNLD_DS_SOCCLK].enabled = true;
2506         }
2507
2508         if (data->smu_features[GNLD_DS_LCLK].supported) {
2509                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2510                                 true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap),
2511                                 "Attempt to Enable DS_GFXCLK Feature Failed!",
2512                                 return -1);
2513                 data->smu_features[GNLD_DS_LCLK].enabled = true;
2514         }
2515
2516         return 0;
2517 }
2518
2519 /**
2520  * @brief Tell SMC to enabled the supported DPMs.
2521  *
2522  * @param    hwmgr - the address of the powerplay hardware manager.
2523  * @Param    bitmap - bitmap for the features to enabled.
2524  * @return   0 on at least one DPM is successfully enabled.
2525  */
2526 static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
2527 {
2528         struct vega10_hwmgr *data =
2529                         (struct vega10_hwmgr *)(hwmgr->backend);
2530         uint32_t i, feature_mask = 0;
2531
2532         for (i = 0; i < GNLD_DPM_MAX; i++) {
2533                 if (data->smu_features[i].smu_feature_bitmap & bitmap) {
2534                         if (data->smu_features[i].supported) {
2535                                 if (!data->smu_features[i].enabled) {
2536                                         feature_mask |= data->smu_features[i].
2537                                                         smu_feature_bitmap;
2538                                         data->smu_features[i].enabled = true;
2539                                 }
2540                         }
2541                 }
2542         }
2543
2544         if (vega10_enable_smc_features(hwmgr->smumgr,
2545                         true, feature_mask)) {
2546                 for (i = 0; i < GNLD_DPM_MAX; i++) {
2547                         if (data->smu_features[i].smu_feature_bitmap &
2548                                         feature_mask)
2549                                 data->smu_features[i].enabled = false;
2550                 }
2551         }
2552
2553         if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
2554                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2555                                 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
2556                 "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
2557                 data->smu_features[GNLD_LED_DISPLAY].enabled = true;
2558         }
2559
2560         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2561                         PHM_PlatformCaps_Falcon_QuickTransition)) {
2562                 if (data->smu_features[GNLD_ACDC].supported) {
2563                         PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
2564                                         true, data->smu_features[GNLD_ACDC].smu_feature_bitmap),
2565                                         "Attempt to Enable DS_GFXCLK Feature Failed!",
2566                                         return -1);
2567                         data->smu_features[GNLD_ACDC].enabled = true;
2568                 }
2569         }
2570
2571         return 0;
2572 }
2573
2574 static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
2575 {
2576         struct vega10_hwmgr *data =
2577                         (struct vega10_hwmgr *)(hwmgr->backend);
2578         int tmp_result, result = 0;
2579
2580         tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2581                         PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
2582         PP_ASSERT_WITH_CODE(!tmp_result,
2583                         "Failed to configure telemetry!",
2584                         return tmp_result);
2585
2586         smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
2587                         PPSMC_MSG_NumOfDisplays, 0);
2588
2589         tmp_result = (!vega10_is_dpm_running(hwmgr)) ? 0 : -1;
2590         PP_ASSERT_WITH_CODE(!tmp_result,
2591                         "DPM is already running right , skipping re-enablement!",
2592                         return 0);
2593
2594         tmp_result = vega10_construct_voltage_tables(hwmgr);
2595         PP_ASSERT_WITH_CODE(!tmp_result,
2596                         "Failed to contruct voltage tables!",
2597                         result = tmp_result);
2598
2599         tmp_result = vega10_init_smc_table(hwmgr);
2600         PP_ASSERT_WITH_CODE(!tmp_result,
2601                         "Failed to initialize SMC table!",
2602                         result = tmp_result);
2603
2604         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2605                         PHM_PlatformCaps_ThermalController)) {
2606                 tmp_result = vega10_enable_thermal_protection(hwmgr);
2607                 PP_ASSERT_WITH_CODE(!tmp_result,
2608                                 "Failed to enable thermal protection!",
2609                                 result = tmp_result);
2610         }
2611
2612         tmp_result = vega10_enable_vrhot_feature(hwmgr);
2613         PP_ASSERT_WITH_CODE(!tmp_result,
2614                         "Failed to enable VR hot feature!",
2615                         result = tmp_result);
2616
2617         tmp_result = vega10_enable_ulv(hwmgr);
2618         PP_ASSERT_WITH_CODE(!tmp_result,
2619                         "Failed to enable ULV!",
2620                         result = tmp_result);
2621
2622         tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr);
2623         PP_ASSERT_WITH_CODE(!tmp_result,
2624                         "Failed to enable deep sleep master switch!",
2625                         result = tmp_result);
2626
2627         tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES);
2628         PP_ASSERT_WITH_CODE(!tmp_result,
2629                         "Failed to start DPM!", result = tmp_result);
2630
2631         tmp_result = vega10_enable_power_containment(hwmgr);
2632         PP_ASSERT_WITH_CODE(!tmp_result,
2633                         "Failed to enable power containment!",
2634                         result = tmp_result);
2635
2636         tmp_result = vega10_power_control_set_level(hwmgr);
2637         PP_ASSERT_WITH_CODE(!tmp_result,
2638                         "Failed to power control set level!",
2639                         result = tmp_result);
2640
2641         return result;
2642 }
2643
2644 static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr)
2645 {
2646         return sizeof(struct vega10_power_state);
2647 }
2648
2649 static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
2650                 void *state, struct pp_power_state *power_state,
2651                 void *pp_table, uint32_t classification_flag)
2652 {
2653         struct vega10_power_state *vega10_power_state =
2654                         cast_phw_vega10_power_state(&(power_state->hardware));
2655         struct vega10_performance_level *performance_level;
2656         ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state;
2657         ATOM_Vega10_POWERPLAYTABLE *powerplay_table =
2658                         (ATOM_Vega10_POWERPLAYTABLE *)pp_table;
2659         ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table =
2660                         (ATOM_Vega10_SOCCLK_Dependency_Table *)
2661                         (((unsigned long)powerplay_table) +
2662                         le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset));
2663         ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
2664                         (ATOM_Vega10_GFXCLK_Dependency_Table *)
2665                         (((unsigned long)powerplay_table) +
2666                         le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
2667         ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table =
2668                         (ATOM_Vega10_MCLK_Dependency_Table *)
2669                         (((unsigned long)powerplay_table) +
2670                         le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
2671
2672
2673         /* The following fields are not initialized here:
2674          * id orderedList allStatesList
2675          */
2676         power_state->classification.ui_label =
2677                         (le16_to_cpu(state_entry->usClassification) &
2678                         ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
2679                         ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
2680         power_state->classification.flags = classification_flag;
2681         /* NOTE: There is a classification2 flag in BIOS
2682          * that is not being used right now
2683          */
2684         power_state->classification.temporary_state = false;
2685         power_state->classification.to_be_deleted = false;
2686
2687         power_state->validation.disallowOnDC =
2688                         ((le32_to_cpu(state_entry->ulCapsAndSettings) &
2689                                         ATOM_Vega10_DISALLOW_ON_DC) != 0);
2690
2691         power_state->display.disableFrameModulation = false;
2692         power_state->display.limitRefreshrate = false;
2693         power_state->display.enableVariBright =
2694                         ((le32_to_cpu(state_entry->ulCapsAndSettings) &
2695                                         ATOM_Vega10_ENABLE_VARIBRIGHT) != 0);
2696
2697         power_state->validation.supportedPowerLevels = 0;
2698         power_state->uvd_clocks.VCLK = 0;
2699         power_state->uvd_clocks.DCLK = 0;
2700         power_state->temperatures.min = 0;
2701         power_state->temperatures.max = 0;
2702
2703         performance_level = &(vega10_power_state->performance_levels
2704                         [vega10_power_state->performance_level_count++]);
2705
2706         PP_ASSERT_WITH_CODE(
2707                         (vega10_power_state->performance_level_count <
2708                                         NUM_GFXCLK_DPM_LEVELS),
2709                         "Performance levels exceeds SMC limit!",
2710                         return -1);
2711
2712         PP_ASSERT_WITH_CODE(
2713                         (vega10_power_state->performance_level_count <=
2714                                         hwmgr->platform_descriptor.
2715                                         hardwareActivityPerformanceLevels),
2716                         "Performance levels exceeds Driver limit!",
2717                         return -1);
2718
2719         /* Performance levels are arranged from low to high. */
2720         performance_level->soc_clock = socclk_dep_table->entries
2721                         [state_entry->ucSocClockIndexLow].ulClk;
2722         performance_level->gfx_clock = gfxclk_dep_table->entries
2723                         [state_entry->ucGfxClockIndexLow].ulClk;
2724         performance_level->mem_clock = mclk_dep_table->entries
2725                         [state_entry->ucMemClockIndexLow].ulMemClk;
2726
2727         performance_level = &(vega10_power_state->performance_levels
2728                                 [vega10_power_state->performance_level_count++]);
2729
2730         performance_level->soc_clock = socclk_dep_table->entries
2731                         [state_entry->ucSocClockIndexHigh].ulClk;
2732         performance_level->gfx_clock = gfxclk_dep_table->entries
2733                         [state_entry->ucGfxClockIndexHigh].ulClk;
2734         performance_level->mem_clock = mclk_dep_table->entries
2735                         [state_entry->ucMemClockIndexHigh].ulMemClk;
2736         return 0;
2737 }
2738
2739 static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr,
2740                 unsigned long entry_index, struct pp_power_state *state)
2741 {
2742         int result;
2743         struct vega10_power_state *ps;
2744
2745         state->hardware.magic = PhwVega10_Magic;
2746
2747         ps = cast_phw_vega10_power_state(&state->hardware);
2748
2749         result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state,
2750                         vega10_get_pp_table_entry_callback_func);
2751
2752         /*
2753          * This is the earliest time we have all the dependency table
2754          * and the VBIOS boot state
2755          */
2756         /* set DC compatible flag if this state supports DC */
2757         if (!state->validation.disallowOnDC)
2758                 ps->dc_compatible = true;
2759
2760         ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
2761         ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
2762
2763         return 0;
2764 }
2765
2766 static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr,
2767              struct pp_hw_power_state *hw_ps)
2768 {
2769         return 0;
2770 }
2771
2772 static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
2773                                 struct pp_power_state  *request_ps,
2774                         const struct pp_power_state *current_ps)
2775 {
2776         struct vega10_power_state *vega10_ps =
2777                                 cast_phw_vega10_power_state(&request_ps->hardware);
2778         uint32_t sclk;
2779         uint32_t mclk;
2780         struct PP_Clocks minimum_clocks = {0};
2781         bool disable_mclk_switching;
2782         bool disable_mclk_switching_for_frame_lock;
2783         bool disable_mclk_switching_for_vr;
2784         bool force_mclk_high;
2785         struct cgs_display_info info = {0};
2786         const struct phm_clock_and_voltage_limits *max_limits;
2787         uint32_t i;
2788         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
2789         struct phm_ppt_v2_information *table_info =
2790                         (struct phm_ppt_v2_information *)(hwmgr->pptable);
2791         int32_t count;
2792         uint32_t stable_pstate_sclk_dpm_percentage;
2793         uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
2794         uint32_t latency;
2795
2796         data->battery_state = (PP_StateUILabel_Battery ==
2797                         request_ps->classification.ui_label);
2798
2799         if (vega10_ps->performance_level_count != 2)
2800                 pr_info("VI should always have 2 performance levels");
2801
2802         max_limits = (PP_PowerSource_AC == hwmgr->power_source) ?
2803                         &(hwmgr->dyn_state.max_clock_voltage_on_ac) :
2804                         &(hwmgr->dyn_state.max_clock_voltage_on_dc);
2805
2806         /* Cap clock DPM tables at DC MAX if it is in DC. */
2807         if (PP_PowerSource_DC == hwmgr->power_source) {
2808                 for (i = 0; i < vega10_ps->performance_level_count; i++) {
2809                         if (vega10_ps->performance_levels[i].mem_clock >
2810                                 max_limits->mclk)
2811                                 vega10_ps->performance_levels[i].mem_clock =
2812                                                 max_limits->mclk;
2813                         if (vega10_ps->performance_levels[i].gfx_clock >
2814                                 max_limits->sclk)
2815                                 vega10_ps->performance_levels[i].gfx_clock =
2816                                                 max_limits->sclk;
2817                 }
2818         }
2819
2820         vega10_ps->vce_clks.evclk = hwmgr->vce_arbiter.evclk;
2821         vega10_ps->vce_clks.ecclk = hwmgr->vce_arbiter.ecclk;
2822
2823         cgs_get_active_displays_info(hwmgr->device, &info);
2824
2825         /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
2826         minimum_clocks.engineClock = hwmgr->display_config.min_core_set_clock;
2827         /* minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock; */
2828
2829         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2830                         PHM_PlatformCaps_StablePState)) {
2831                 PP_ASSERT_WITH_CODE(
2832                         data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 &&
2833                         data->registry_data.stable_pstate_sclk_dpm_percentage <= 100,
2834                         "percent sclk value must range from 1% to 100%, setting default value",
2835                         stable_pstate_sclk_dpm_percentage = 75);
2836
2837                 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
2838                 stable_pstate_sclk = (max_limits->sclk *
2839                                 stable_pstate_sclk_dpm_percentage) / 100;
2840
2841                 for (count = table_info->vdd_dep_on_sclk->count - 1;
2842                                 count >= 0; count--) {
2843                         if (stable_pstate_sclk >=
2844                                         table_info->vdd_dep_on_sclk->entries[count].clk) {
2845                                 stable_pstate_sclk =
2846                                                 table_info->vdd_dep_on_sclk->entries[count].clk;
2847                                 break;
2848                         }
2849                 }
2850
2851                 if (count < 0)
2852                         stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
2853
2854                 stable_pstate_mclk = max_limits->mclk;
2855
2856                 minimum_clocks.engineClock = stable_pstate_sclk;
2857                 minimum_clocks.memoryClock = stable_pstate_mclk;
2858         }
2859
2860         if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk)
2861                 minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk;
2862
2863         if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
2864                 minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
2865
2866         vega10_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold;
2867
2868         if (hwmgr->gfx_arbiter.sclk_over_drive) {
2869                 PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <=
2870                                 hwmgr->platform_descriptor.overdriveLimit.engineClock),
2871                                 "Overdrive sclk exceeds limit",
2872                                 hwmgr->gfx_arbiter.sclk_over_drive =
2873                                                 hwmgr->platform_descriptor.overdriveLimit.engineClock);
2874
2875                 if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk)
2876                         vega10_ps->performance_levels[1].gfx_clock =
2877                                         hwmgr->gfx_arbiter.sclk_over_drive;
2878         }
2879
2880         if (hwmgr->gfx_arbiter.mclk_over_drive) {
2881                 PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <=
2882                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock),
2883                                 "Overdrive mclk exceeds limit",
2884                                 hwmgr->gfx_arbiter.mclk_over_drive =
2885                                                 hwmgr->platform_descriptor.overdriveLimit.memoryClock);
2886
2887                 if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk)
2888                         vega10_ps->performance_levels[1].mem_clock =
2889                                         hwmgr->gfx_arbiter.mclk_over_drive;
2890         }
2891
2892         disable_mclk_switching_for_frame_lock = phm_cap_enabled(
2893                                     hwmgr->platform_descriptor.platformCaps,
2894                                     PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
2895         disable_mclk_switching_for_vr = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2896                         PHM_PlatformCaps_DisableMclkSwitchForVR);
2897         force_mclk_high = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2898                         PHM_PlatformCaps_ForceMclkHigh);
2899
2900         disable_mclk_switching = (info.display_count > 1) ||
2901                                     disable_mclk_switching_for_frame_lock ||
2902                                     disable_mclk_switching_for_vr ||
2903                                     force_mclk_high;
2904
2905         sclk = vega10_ps->performance_levels[0].gfx_clock;
2906         mclk = vega10_ps->performance_levels[0].mem_clock;
2907
2908         if (sclk < minimum_clocks.engineClock)
2909                 sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
2910                                 max_limits->sclk : minimum_clocks.engineClock;
2911
2912         if (mclk < minimum_clocks.memoryClock)
2913                 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
2914                                 max_limits->mclk : minimum_clocks.memoryClock;
2915
2916         vega10_ps->performance_levels[0].gfx_clock = sclk;
2917         vega10_ps->performance_levels[0].mem_clock = mclk;
2918
2919         vega10_ps->performance_levels[1].gfx_clock =
2920                 (vega10_ps->performance_levels[1].gfx_clock >=
2921                                 vega10_ps->performance_levels[0].gfx_clock) ?
2922                                                 vega10_ps->performance_levels[1].gfx_clock :
2923                                                 vega10_ps->performance_levels[0].gfx_clock;
2924
2925         if (disable_mclk_switching) {
2926                 /* Set Mclk the max of level 0 and level 1 */
2927                 if (mclk < vega10_ps->performance_levels[1].mem_clock)
2928                         mclk = vega10_ps->performance_levels[1].mem_clock;
2929
2930                 /* Find the lowest MCLK frequency that is within
2931                  * the tolerable latency defined in DAL
2932                  */
2933                 latency = 0;
2934                 for (i = 0; i < data->mclk_latency_table.count; i++) {
2935                         if ((data->mclk_latency_table.entries[i].latency <= latency) &&
2936                                 (data->mclk_latency_table.entries[i].frequency >=
2937                                                 vega10_ps->performance_levels[0].mem_clock) &&
2938                                 (data->mclk_latency_table.entries[i].frequency <=
2939                                                 vega10_ps->performance_levels[1].mem_clock))
2940                                 mclk = data->mclk_latency_table.entries[i].frequency;
2941                 }
2942                 vega10_ps->performance_levels[0].mem_clock = mclk;
2943         } else {
2944                 if (vega10_ps->performance_levels[1].mem_clock <
2945                                 vega10_ps->performance_levels[0].mem_clock)
2946                         vega10_ps->performance_levels[1].mem_clock =
2947                                         vega10_ps->performance_levels[0].mem_clock;
2948         }
2949
2950         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2951                         PHM_PlatformCaps_StablePState)) {
2952                 for (i = 0; i < vega10_ps->performance_level_count; i++) {
2953                         vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk;
2954                         vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk;
2955                 }
2956         }
2957
2958         return 0;
2959 }
2960
2961 static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
2962 {
2963         const struct phm_set_power_state_input *states =
2964                         (const struct phm_set_power_state_input *)input;
2965         const struct vega10_power_state *vega10_ps =
2966                         cast_const_phw_vega10_power_state(states->pnew_state);
2967         struct vega10_hwmgr *data =
2968                         (struct vega10_hwmgr *)(hwmgr->backend);
2969         struct vega10_single_dpm_table *sclk_table =
2970                         &(data->dpm_table.gfx_table);
2971         uint32_t sclk = vega10_ps->performance_levels
2972                         [vega10_ps->performance_level_count - 1].gfx_clock;
2973         struct vega10_single_dpm_table *mclk_table =
2974                         &(data->dpm_table.mem_table);
2975         uint32_t mclk = vega10_ps->performance_levels
2976                         [vega10_ps->performance_level_count - 1].mem_clock;
2977         struct PP_Clocks min_clocks = {0};
2978         uint32_t i;
2979         struct cgs_display_info info = {0};
2980
2981         data->need_update_dpm_table = 0;
2982
2983         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2984                         PHM_PlatformCaps_ODNinACSupport) ||
2985                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
2986                                 PHM_PlatformCaps_ODNinDCSupport)) {
2987                 for (i = 0; i < sclk_table->count; i++) {
2988                         if (sclk == sclk_table->dpm_levels[i].value)
2989                                 break;
2990                 }
2991
2992                 if (!(data->apply_overdrive_next_settings_mask &
2993                                 DPMTABLE_OD_UPDATE_SCLK) && i >= sclk_table->count) {
2994                         /* Check SCLK in DAL's minimum clocks
2995                          * in case DeepSleep divider update is required.
2996                          */
2997                         if (data->display_timing.min_clock_in_sr !=
2998                                         min_clocks.engineClockInSR &&
2999                                 (min_clocks.engineClockInSR >=
3000                                                 VEGA10_MINIMUM_ENGINE_CLOCK ||
3001                                         data->display_timing.min_clock_in_sr >=
3002                                                 VEGA10_MINIMUM_ENGINE_CLOCK))
3003                                 data->need_update_dpm_table |= DPMTABLE_UPDATE_SCLK;
3004                 }
3005
3006                 cgs_get_active_displays_info(hwmgr->device, &info);
3007
3008                 if (data->display_timing.num_existing_displays !=
3009                                 info.display_count)
3010                         data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
3011         } else {
3012                 for (i = 0; i < sclk_table->count; i++) {
3013                         if (sclk == sclk_table->dpm_levels[i].value)
3014                                 break;
3015                 }
3016
3017                 if (i >= sclk_table->count)
3018                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
3019                 else {
3020                         /* Check SCLK in DAL's minimum clocks
3021                          * in case DeepSleep divider update is required.
3022                          */
3023                         if (data->display_timing.min_clock_in_sr !=
3024                                         min_clocks.engineClockInSR &&
3025                                 (min_clocks.engineClockInSR >=
3026                                                 VEGA10_MINIMUM_ENGINE_CLOCK ||
3027                                         data->display_timing.min_clock_in_sr >=
3028                                                 VEGA10_MINIMUM_ENGINE_CLOCK))
3029                                 data->need_update_dpm_table |= DPMTABLE_UPDATE_SCLK;
3030                 }
3031
3032                 for (i = 0; i < mclk_table->count; i++) {
3033                         if (mclk == mclk_table->dpm_levels[i].value)
3034                                 break;
3035                 }
3036
3037                 cgs_get_active_displays_info(hwmgr->device, &info);
3038
3039                 if (i >= mclk_table->count)
3040                         data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
3041
3042                 if (data->display_timing.num_existing_displays !=
3043                                 info.display_count ||
3044                                 i >= mclk_table->count)
3045                         data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
3046         }
3047         return 0;
3048 }
3049
3050 static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
3051                 struct pp_hwmgr *hwmgr, const void *input)
3052 {
3053         int result = 0;
3054         const struct phm_set_power_state_input *states =
3055                         (const struct phm_set_power_state_input *)input;
3056         const struct vega10_power_state *vega10_ps =
3057                         cast_const_phw_vega10_power_state(states->pnew_state);
3058         struct vega10_hwmgr *data =
3059                         (struct vega10_hwmgr *)(hwmgr->backend);
3060         uint32_t sclk = vega10_ps->performance_levels
3061                         [vega10_ps->performance_level_count - 1].gfx_clock;
3062         uint32_t mclk = vega10_ps->performance_levels
3063                         [vega10_ps->performance_level_count - 1].mem_clock;
3064         struct vega10_dpm_table *dpm_table = &data->dpm_table;
3065         struct vega10_dpm_table *golden_dpm_table =
3066                         &data->golden_dpm_table;
3067         uint32_t dpm_count, clock_percent;
3068         uint32_t i;
3069
3070         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3071                         PHM_PlatformCaps_ODNinACSupport) ||
3072                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3073                         PHM_PlatformCaps_ODNinDCSupport)) {
3074
3075                 if (!data->need_update_dpm_table &&
3076                         !data->apply_optimized_settings &&
3077                         !data->apply_overdrive_next_settings_mask)
3078                         return 0;
3079
3080                 if (data->apply_overdrive_next_settings_mask &
3081                                 DPMTABLE_OD_UPDATE_SCLK) {
3082                         for (dpm_count = 0;
3083                                         dpm_count < dpm_table->gfx_table.count;
3084                                         dpm_count++) {
3085                                 dpm_table->gfx_table.dpm_levels[dpm_count].enabled =
3086                                                 data->odn_dpm_table.odn_core_clock_dpm_levels.
3087                                                 performance_level_entries[dpm_count].enabled;
3088                                 dpm_table->gfx_table.dpm_levels[dpm_count].value =
3089                                                 data->odn_dpm_table.odn_core_clock_dpm_levels.
3090                                                 performance_level_entries[dpm_count].clock;
3091                         }
3092                 }
3093
3094                 if (data->apply_overdrive_next_settings_mask &
3095                                 DPMTABLE_OD_UPDATE_MCLK) {
3096                         for (dpm_count = 0;
3097                                         dpm_count < dpm_table->mem_table.count;
3098                                         dpm_count++) {
3099                                 dpm_table->mem_table.dpm_levels[dpm_count].enabled =
3100                                                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
3101                                                 performance_level_entries[dpm_count].enabled;
3102                                 dpm_table->mem_table.dpm_levels[dpm_count].value =
3103                                                 data->odn_dpm_table.odn_memory_clock_dpm_levels.
3104                                                 performance_level_entries[dpm_count].clock;
3105                         }
3106                 }
3107
3108                 if ((data->need_update_dpm_table & DPMTABLE_UPDATE_SCLK) ||
3109                         data->apply_optimized_settings ||
3110                         (data->apply_overdrive_next_settings_mask &
3111                                         DPMTABLE_OD_UPDATE_SCLK)) {
3112                         result = vega10_populate_all_graphic_levels(hwmgr);
3113                         PP_ASSERT_WITH_CODE(!result,
3114                                         "Failed to populate SCLK during \
3115                                         PopulateNewDPMClocksStates Function!",
3116                                         return result);
3117                 }
3118
3119                 if ((data->need_update_dpm_table & DPMTABLE_UPDATE_MCLK) ||
3120                         (data->apply_overdrive_next_settings_mask &
3121                                         DPMTABLE_OD_UPDATE_MCLK)){
3122                         result = vega10_populate_all_memory_levels(hwmgr);
3123                         PP_ASSERT_WITH_CODE(!result,
3124                                         "Failed to populate MCLK during \
3125                                         PopulateNewDPMClocksStates Function!",
3126                                         return result);
3127                 }
3128         } else {
3129                 if (!data->need_update_dpm_table &&
3130                                 !data->apply_optimized_settings)
3131                         return 0;
3132
3133                 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK &&
3134                                 data->smu_features[GNLD_DPM_GFXCLK].supported) {
3135                                 dpm_table->
3136                                 gfx_table.dpm_levels[dpm_table->gfx_table.count - 1].
3137                                 value = sclk;
3138
3139                                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3140                                                 PHM_PlatformCaps_OD6PlusinACSupport) ||
3141                                         phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3142                                                         PHM_PlatformCaps_OD6PlusinDCSupport)) {
3143                                         /* Need to do calculation based on the golden DPM table
3144                                          * as the Heatmap GPU Clock axis is also based on
3145                                          * the default values
3146                                          */
3147                                         PP_ASSERT_WITH_CODE(
3148                                                         golden_dpm_table->gfx_table.dpm_levels
3149                                                         [golden_dpm_table->gfx_table.count - 1].value,
3150                                                         "Divide by 0!",
3151                                                         return -1);
3152
3153                                         dpm_count = dpm_table->gfx_table.count < 2 ?
3154                                                         0 : dpm_table->gfx_table.count - 2;
3155                                         for (i = dpm_count; i > 1; i--) {
3156                                                 if (sclk > golden_dpm_table->gfx_table.dpm_levels
3157                                                         [golden_dpm_table->gfx_table.count - 1].value) {
3158                                                         clock_percent =
3159                                                                 ((sclk - golden_dpm_table->gfx_table.dpm_levels
3160                                                                 [golden_dpm_table->gfx_table.count - 1].value) *
3161                                                                 100) /
3162                                                                 golden_dpm_table->gfx_table.dpm_levels
3163                                                                 [golden_dpm_table->gfx_table.count - 1].value;
3164
3165                                                         dpm_table->gfx_table.dpm_levels[i].value =
3166                                                                 golden_dpm_table->gfx_table.dpm_levels[i].value +
3167                                                                 (golden_dpm_table->gfx_table.dpm_levels[i].value *
3168                                                                 clock_percent) / 100;
3169                                                 } else if (golden_dpm_table->
3170                                                                 gfx_table.dpm_levels[dpm_table->gfx_table.count-1].value >
3171                                                                 sclk) {
3172                                                         clock_percent =
3173                                                                 ((golden_dpm_table->gfx_table.dpm_levels
3174                                                                 [golden_dpm_table->gfx_table.count - 1].value -
3175                                                                 sclk) * 100) /
3176                                                                 golden_dpm_table->gfx_table.dpm_levels
3177                                                                 [golden_dpm_table->gfx_table.count-1].value;
3178
3179                                                         dpm_table->gfx_table.dpm_levels[i].value =
3180                                                                 golden_dpm_table->gfx_table.dpm_levels[i].value -
3181                                                                 (golden_dpm_table->gfx_table.dpm_levels[i].value *
3182                                                                 clock_percent) / 100;
3183                                                 } else
3184                                                         dpm_table->gfx_table.dpm_levels[i].value =
3185                                                                 golden_dpm_table->gfx_table.dpm_levels[i].value;
3186                                         }
3187                                 }
3188                         }
3189
3190                 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK &&
3191                                 data->smu_features[GNLD_DPM_UCLK].supported) {
3192                         dpm_table->
3193                         mem_table.dpm_levels[dpm_table->mem_table.count - 1].
3194                         value = mclk;
3195
3196                         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3197                                         PHM_PlatformCaps_OD6PlusinACSupport) ||
3198                                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3199                                                 PHM_PlatformCaps_OD6PlusinDCSupport)) {
3200
3201                                 PP_ASSERT_WITH_CODE(
3202                                         golden_dpm_table->mem_table.dpm_levels
3203                                         [golden_dpm_table->mem_table.count - 1].value,
3204                                         "Divide by 0!",
3205                                         return -1);
3206
3207                                 dpm_count = dpm_table->mem_table.count < 2 ?
3208                                                 0 : dpm_table->mem_table.count - 2;
3209                                 for (i = dpm_count; i > 1; i--) {
3210                                         if (mclk > golden_dpm_table->mem_table.dpm_levels
3211                                                 [golden_dpm_table->mem_table.count-1].value) {
3212                                                 clock_percent = ((mclk -
3213                                                         golden_dpm_table->mem_table.dpm_levels
3214                                                         [golden_dpm_table->mem_table.count-1].value) *
3215                                                         100) /
3216                                                         golden_dpm_table->mem_table.dpm_levels
3217                                                         [golden_dpm_table->mem_table.count-1].value;
3218
3219                                                 dpm_table->mem_table.dpm_levels[i].value =
3220                                                         golden_dpm_table->mem_table.dpm_levels[i].value +
3221                                                         (golden_dpm_table->mem_table.dpm_levels[i].value *
3222                                                         clock_percent) / 100;
3223                                         } else if (golden_dpm_table->mem_table.dpm_levels
3224                                                         [dpm_table->mem_table.count-1].value > mclk) {
3225                                                 clock_percent = ((golden_dpm_table->mem_table.dpm_levels
3226                                                         [golden_dpm_table->mem_table.count-1].value - mclk) *
3227                                                         100) /
3228                                                         golden_dpm_table->mem_table.dpm_levels
3229                                                         [golden_dpm_table->mem_table.count-1].value;
3230
3231                                                 dpm_table->mem_table.dpm_levels[i].value =
3232                                                         golden_dpm_table->mem_table.dpm_levels[i].value -
3233                                                         (golden_dpm_table->mem_table.dpm_levels[i].value *
3234                                                         clock_percent) / 100;
3235                                         } else
3236                                                 dpm_table->mem_table.dpm_levels[i].value =
3237                                                         golden_dpm_table->mem_table.dpm_levels[i].value;
3238                                 }
3239                         }
3240                 }
3241
3242                 if ((data->need_update_dpm_table &
3243                         (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) ||
3244                         data->apply_optimized_settings) {
3245                         result = vega10_populate_all_graphic_levels(hwmgr);
3246                         PP_ASSERT_WITH_CODE(!result,
3247                                         "Failed to populate SCLK during \
3248                                         PopulateNewDPMClocksStates Function!",
3249                                         return result);
3250                 }
3251
3252                 if (data->need_update_dpm_table &
3253                                 (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
3254                         result = vega10_populate_all_memory_levels(hwmgr);
3255                         PP_ASSERT_WITH_CODE(!result,
3256                                         "Failed to populate MCLK during \
3257                                         PopulateNewDPMClocksStates Function!",
3258                                         return result);
3259                 }
3260         }
3261
3262         return result;
3263 }
3264
3265 static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
3266                 struct vega10_single_dpm_table *dpm_table,
3267                 uint32_t low_limit, uint32_t high_limit)
3268 {
3269         uint32_t i;
3270
3271         for (i = 0; i < dpm_table->count; i++) {
3272                 if ((dpm_table->dpm_levels[i].value < low_limit) ||
3273                     (dpm_table->dpm_levels[i].value > high_limit))
3274                         dpm_table->dpm_levels[i].enabled = false;
3275                 else
3276                         dpm_table->dpm_levels[i].enabled = true;
3277         }
3278         return 0;
3279 }
3280
3281 static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr,
3282                 struct vega10_single_dpm_table *dpm_table,
3283                 uint32_t low_limit, uint32_t high_limit,
3284                 uint32_t disable_dpm_mask)
3285 {
3286         uint32_t i;
3287
3288         for (i = 0; i < dpm_table->count; i++) {
3289                 if ((dpm_table->dpm_levels[i].value < low_limit) ||
3290                     (dpm_table->dpm_levels[i].value > high_limit))
3291                         dpm_table->dpm_levels[i].enabled = false;
3292                 else if (!((1 << i) & disable_dpm_mask))
3293                         dpm_table->dpm_levels[i].enabled = false;
3294                 else
3295                         dpm_table->dpm_levels[i].enabled = true;
3296         }
3297         return 0;
3298 }
3299
3300 static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr,
3301                 const struct vega10_power_state *vega10_ps)
3302 {
3303         struct vega10_hwmgr *data =
3304                         (struct vega10_hwmgr *)(hwmgr->backend);
3305         uint32_t high_limit_count;
3306
3307         PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1),
3308                         "power state did not have any performance level",
3309                         return -1);
3310
3311         high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1;
3312
3313         vega10_trim_single_dpm_states(hwmgr,
3314                         &(data->dpm_table.soc_table),
3315                         vega10_ps->performance_levels[0].soc_clock,
3316                         vega10_ps->performance_levels[high_limit_count].soc_clock);
3317
3318         vega10_trim_single_dpm_states_with_mask(hwmgr,
3319                         &(data->dpm_table.gfx_table),
3320                         vega10_ps->performance_levels[0].gfx_clock,
3321                         vega10_ps->performance_levels[high_limit_count].gfx_clock,
3322                         data->disable_dpm_mask);
3323
3324         vega10_trim_single_dpm_states(hwmgr,
3325                         &(data->dpm_table.mem_table),
3326                         vega10_ps->performance_levels[0].mem_clock,
3327                         vega10_ps->performance_levels[high_limit_count].mem_clock);
3328
3329         return 0;
3330 }
3331
3332 static uint32_t vega10_find_lowest_dpm_level(
3333                 struct vega10_single_dpm_table *table)
3334 {
3335         uint32_t i;
3336
3337         for (i = 0; i < table->count; i++) {
3338                 if (table->dpm_levels[i].enabled)
3339                         break;
3340         }
3341
3342         return i;
3343 }
3344
3345 static uint32_t vega10_find_highest_dpm_level(
3346                 struct vega10_single_dpm_table *table)
3347 {
3348         uint32_t i = 0;
3349
3350         if (table->count <= MAX_REGULAR_DPM_NUMBER) {
3351                 for (i = table->count; i > 0; i--) {
3352                         if (table->dpm_levels[i - 1].enabled)
3353                                 return i - 1;
3354                 }
3355         } else {
3356                 pr_info("DPM Table Has Too Many Entries!");
3357                 return MAX_REGULAR_DPM_NUMBER - 1;
3358         }
3359
3360         return i;
3361 }
3362
3363 static void vega10_apply_dal_minimum_voltage_request(
3364                 struct pp_hwmgr *hwmgr)
3365 {
3366         return;
3367 }
3368
3369 static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
3370 {
3371         struct vega10_hwmgr *data =
3372                         (struct vega10_hwmgr *)(hwmgr->backend);
3373
3374         vega10_apply_dal_minimum_voltage_request(hwmgr);
3375
3376         if (!data->registry_data.sclk_dpm_key_disabled) {
3377                 if (data->smc_state_table.gfx_boot_level !=
3378                                 data->dpm_table.gfx_table.dpm_state.soft_min_level) {
3379                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3380                                 hwmgr->smumgr,
3381                                 PPSMC_MSG_SetSoftMinGfxclkByIndex,
3382                                 data->smc_state_table.gfx_boot_level),
3383                                 "Failed to set soft min sclk index!",
3384                                 return -EINVAL);
3385                         data->dpm_table.gfx_table.dpm_state.soft_min_level =
3386                                         data->smc_state_table.gfx_boot_level;
3387                 }
3388         }
3389
3390         if (!data->registry_data.mclk_dpm_key_disabled) {
3391                 if (data->smc_state_table.mem_boot_level !=
3392                                 data->dpm_table.mem_table.dpm_state.soft_min_level) {
3393                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3394                                 hwmgr->smumgr,
3395                                  PPSMC_MSG_SetSoftMinUclkByIndex,
3396                                 data->smc_state_table.mem_boot_level),
3397                                 "Failed to set soft min mclk index!",
3398                                 return -EINVAL);
3399
3400                         data->dpm_table.mem_table.dpm_state.soft_min_level =
3401                                         data->smc_state_table.mem_boot_level;
3402                 }
3403         }
3404
3405         return 0;
3406 }
3407
3408 static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
3409 {
3410         struct vega10_hwmgr *data =
3411                         (struct vega10_hwmgr *)(hwmgr->backend);
3412
3413         vega10_apply_dal_minimum_voltage_request(hwmgr);
3414
3415         if (!data->registry_data.sclk_dpm_key_disabled) {
3416                 if (data->smc_state_table.gfx_max_level !=
3417                                 data->dpm_table.gfx_table.dpm_state.soft_max_level) {
3418                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3419                                 hwmgr->smumgr,
3420                                 PPSMC_MSG_SetSoftMaxGfxclkByIndex,
3421                                 data->smc_state_table.gfx_max_level),
3422                                 "Failed to set soft max sclk index!",
3423                                 return -EINVAL);
3424                         data->dpm_table.gfx_table.dpm_state.soft_max_level =
3425                                         data->smc_state_table.gfx_max_level;
3426                 }
3427         }
3428
3429         if (!data->registry_data.mclk_dpm_key_disabled) {
3430                 if (data->smc_state_table.mem_max_level !=
3431                                 data->dpm_table.mem_table.dpm_state.soft_max_level) {
3432                                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3433                                 hwmgr->smumgr,
3434                                 PPSMC_MSG_SetSoftMaxUclkByIndex,
3435                                 data->smc_state_table.mem_max_level),
3436                                 "Failed to set soft max mclk index!",
3437                                 return -EINVAL);
3438                         data->dpm_table.mem_table.dpm_state.soft_max_level =
3439                                         data->smc_state_table.mem_max_level;
3440                 }
3441         }
3442
3443         return 0;
3444 }
3445
3446 static int vega10_generate_dpm_level_enable_mask(
3447                 struct pp_hwmgr *hwmgr, const void *input)
3448 {
3449         struct vega10_hwmgr *data =
3450                         (struct vega10_hwmgr *)(hwmgr->backend);
3451         const struct phm_set_power_state_input *states =
3452                         (const struct phm_set_power_state_input *)input;
3453         const struct vega10_power_state *vega10_ps =
3454                         cast_const_phw_vega10_power_state(states->pnew_state);
3455         int i;
3456
3457         PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps),
3458                         "Attempt to Trim DPM States Failed!",
3459                         return -1);
3460
3461         data->smc_state_table.gfx_boot_level =
3462                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3463         data->smc_state_table.gfx_max_level =
3464                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3465         data->smc_state_table.mem_boot_level =
3466                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3467         data->smc_state_table.mem_max_level =
3468                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3469
3470         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3471                         "Attempt to upload DPM Bootup Levels Failed!",
3472                         return -1);
3473         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3474                         "Attempt to upload DPM Max Levels Failed!",
3475                         return -1);
3476         for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++)
3477                 data->dpm_table.gfx_table.dpm_levels[i].enabled = true;
3478
3479
3480         for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++)
3481                 data->dpm_table.mem_table.dpm_levels[i].enabled = true;
3482
3483         return 0;
3484 }
3485
3486 int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
3487 {
3488         struct vega10_hwmgr *data =
3489                         (struct vega10_hwmgr *)(hwmgr->backend);
3490
3491         if (data->smu_features[GNLD_DPM_VCE].supported) {
3492                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
3493                                 enable,
3494                                 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap),
3495                                 "Attempt to Enable/Disable DPM VCE Failed!",
3496                                 return -1);
3497                 data->smu_features[GNLD_DPM_VCE].enabled = enable;
3498         }
3499
3500         return 0;
3501 }
3502
3503 static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
3504 {
3505         struct vega10_hwmgr *data =
3506                         (struct vega10_hwmgr *)(hwmgr->backend);
3507         int result = 0;
3508         uint32_t low_sclk_interrupt_threshold = 0;
3509
3510         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3511                         PHM_PlatformCaps_SclkThrottleLowNotification)
3512                 && (hwmgr->gfx_arbiter.sclk_threshold !=
3513                                 data->low_sclk_interrupt_threshold)) {
3514                 data->low_sclk_interrupt_threshold =
3515                                 hwmgr->gfx_arbiter.sclk_threshold;
3516                 low_sclk_interrupt_threshold =
3517                                 data->low_sclk_interrupt_threshold;
3518
3519                 data->smc_state_table.pp_table.LowGfxclkInterruptThreshold =
3520                                 cpu_to_le32(low_sclk_interrupt_threshold);
3521
3522                 /* This message will also enable SmcToHost Interrupt */
3523                 result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
3524                                 PPSMC_MSG_SetLowGfxclkInterruptThreshold,
3525                                 (uint32_t)low_sclk_interrupt_threshold);
3526         }
3527
3528         return result;
3529 }
3530
3531 static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
3532                 const void *input)
3533 {
3534         int tmp_result, result = 0;
3535         struct vega10_hwmgr *data =
3536                         (struct vega10_hwmgr *)(hwmgr->backend);
3537         PPTable_t *pp_table = &(data->smc_state_table.pp_table);
3538
3539         tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
3540         PP_ASSERT_WITH_CODE(!tmp_result,
3541                         "Failed to find DPM states clocks in DPM table!",
3542                         result = tmp_result);
3543
3544         tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
3545         PP_ASSERT_WITH_CODE(!tmp_result,
3546                         "Failed to populate and upload SCLK MCLK DPM levels!",
3547                         result = tmp_result);
3548
3549         tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input);
3550         PP_ASSERT_WITH_CODE(!tmp_result,
3551                         "Failed to generate DPM level enabled mask!",
3552                         result = tmp_result);
3553
3554         tmp_result = vega10_update_sclk_threshold(hwmgr);
3555         PP_ASSERT_WITH_CODE(!tmp_result,
3556                         "Failed to update SCLK threshold!",
3557                         result = tmp_result);
3558
3559         result = vega10_copy_table_to_smc(hwmgr->smumgr,
3560                         (uint8_t *)pp_table, PPTABLE);
3561         PP_ASSERT_WITH_CODE(!result,
3562                         "Failed to upload PPtable!", return result);
3563
3564         data->apply_optimized_settings = false;
3565         data->apply_overdrive_next_settings_mask = 0;
3566
3567         return 0;
3568 }
3569
3570 static int vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
3571 {
3572         struct pp_power_state *ps;
3573         struct vega10_power_state *vega10_ps;
3574
3575         if (hwmgr == NULL)
3576                 return -EINVAL;
3577
3578         ps = hwmgr->request_ps;
3579
3580         if (ps == NULL)
3581                 return -EINVAL;
3582
3583         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
3584
3585         if (low)
3586                 return vega10_ps->performance_levels[0].gfx_clock;
3587         else
3588                 return vega10_ps->performance_levels
3589                                 [vega10_ps->performance_level_count - 1].gfx_clock;
3590 }
3591
3592 static int vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
3593 {
3594         struct pp_power_state *ps;
3595         struct vega10_power_state *vega10_ps;
3596
3597         if (hwmgr == NULL)
3598                 return -EINVAL;
3599
3600         ps = hwmgr->request_ps;
3601
3602         if (ps == NULL)
3603                 return -EINVAL;
3604
3605         vega10_ps = cast_phw_vega10_power_state(&ps->hardware);
3606
3607         if (low)
3608                 return vega10_ps->performance_levels[0].mem_clock;
3609         else
3610                 return vega10_ps->performance_levels
3611                                 [vega10_ps->performance_level_count-1].mem_clock;
3612 }
3613
3614 static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
3615                               void *value, int *size)
3616 {
3617         uint32_t sclk_idx, mclk_idx, activity_percent = 0;
3618         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
3619         struct vega10_dpm_table *dpm_table = &data->dpm_table;
3620         int ret = 0;
3621
3622         switch (idx) {
3623         case AMDGPU_PP_SENSOR_GFX_SCLK:
3624                 ret = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetCurrentGfxclkIndex);
3625                 if (!ret) {
3626                         vega10_read_arg_from_smc(hwmgr->smumgr, &sclk_idx);
3627                         *((uint32_t *)value) = dpm_table->gfx_table.dpm_levels[sclk_idx].value;
3628                         *size = 4;
3629                 }
3630                 break;
3631         case AMDGPU_PP_SENSOR_GFX_MCLK:
3632                 ret = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetCurrentUclkIndex);
3633                 if (!ret) {
3634                         vega10_read_arg_from_smc(hwmgr->smumgr, &mclk_idx);
3635                         *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value;
3636                         *size = 4;
3637                 }
3638                 break;
3639         case AMDGPU_PP_SENSOR_GPU_LOAD:
3640                 ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_GetAverageGfxActivity, 0);
3641                 if (!ret) {
3642                         vega10_read_arg_from_smc(hwmgr->smumgr, &activity_percent);
3643                         *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
3644                         *size = 4;
3645                 }
3646                 break;
3647         case AMDGPU_PP_SENSOR_GPU_TEMP:
3648                 *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr);
3649                 *size = 4;
3650                 break;
3651         case AMDGPU_PP_SENSOR_UVD_POWER:
3652                 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
3653                 *size = 4;
3654                 break;
3655         case AMDGPU_PP_SENSOR_VCE_POWER:
3656                 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
3657                 *size = 4;
3658                 break;
3659         default:
3660                 ret = -EINVAL;
3661                 break;
3662         }
3663         return ret;
3664 }
3665
3666 static int vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr,
3667                 bool has_disp)
3668 {
3669         return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
3670                         PPSMC_MSG_SetUclkFastSwitch,
3671                         has_disp ? 0 : 1);
3672 }
3673
3674 int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
3675                 struct pp_display_clock_request *clock_req)
3676 {
3677         int result = 0;
3678         enum amd_pp_clock_type clk_type = clock_req->clock_type;
3679         uint32_t clk_freq = clock_req->clock_freq_in_khz / 100;
3680         DSPCLK_e clk_select = 0;
3681         uint32_t clk_request = 0;
3682
3683         switch (clk_type) {
3684         case amd_pp_dcef_clock:
3685                 clk_select = DSPCLK_DCEFCLK;
3686                 break;
3687         case amd_pp_disp_clock:
3688                 clk_select = DSPCLK_DISPCLK;
3689                 break;
3690         case amd_pp_pixel_clock:
3691                 clk_select = DSPCLK_PIXCLK;
3692                 break;
3693         case amd_pp_phy_clock:
3694                 clk_select = DSPCLK_PHYCLK;
3695                 break;
3696         default:
3697                 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
3698                 result = -1;
3699                 break;
3700         }
3701
3702         if (!result) {
3703                 clk_request = (clk_freq << 16) | clk_select;
3704                 result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
3705                                 PPSMC_MSG_RequestDisplayClockByFreq,
3706                                 clk_request);
3707         }
3708
3709         return result;
3710 }
3711
3712 static int vega10_notify_smc_display_config_after_ps_adjustment(
3713                 struct pp_hwmgr *hwmgr)
3714 {
3715         struct vega10_hwmgr *data =
3716                         (struct vega10_hwmgr *)(hwmgr->backend);
3717         struct vega10_single_dpm_table *dpm_table =
3718                         &data->dpm_table.dcef_table;
3719         uint32_t num_active_disps = 0;
3720         struct cgs_display_info info = {0};
3721         struct PP_Clocks min_clocks = {0};
3722         uint32_t i;
3723         struct pp_display_clock_request clock_req;
3724
3725         info.mode_info = NULL;
3726
3727         cgs_get_active_displays_info(hwmgr->device, &info);
3728
3729         num_active_disps = info.display_count;
3730
3731         if (num_active_disps > 1)
3732                 vega10_notify_smc_display_change(hwmgr, false);
3733         else
3734                 vega10_notify_smc_display_change(hwmgr, true);
3735
3736         min_clocks.dcefClock = hwmgr->display_config.min_dcef_set_clk;
3737         min_clocks.dcefClockInSR = hwmgr->display_config.min_dcef_deep_sleep_set_clk;
3738
3739         for (i = 0; i < dpm_table->count; i++) {
3740                 if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock)
3741                         break;
3742         }
3743
3744         if (i < dpm_table->count) {
3745                 clock_req.clock_type = amd_pp_dcef_clock;
3746                 clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value;
3747                 if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) {
3748                         PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
3749                                         hwmgr->smumgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
3750                                         min_clocks.dcefClockInSR),
3751                                         "Attempt to set divider for DCEFCLK Failed!",);
3752                 } else
3753                         pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
3754         } else
3755                 pr_info("Cannot find requested DCEFCLK!");
3756
3757         return 0;
3758 }
3759
3760 static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr)
3761 {
3762         struct vega10_hwmgr *data =
3763                         (struct vega10_hwmgr *)(hwmgr->backend);
3764
3765         data->smc_state_table.gfx_boot_level =
3766         data->smc_state_table.gfx_max_level =
3767                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3768         data->smc_state_table.mem_boot_level =
3769         data->smc_state_table.mem_max_level =
3770                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3771
3772         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3773                         "Failed to upload boot level to highest!",
3774                         return -1);
3775
3776         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3777                         "Failed to upload dpm max level to highest!",
3778                         return -1);
3779
3780         return 0;
3781 }
3782
3783 static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr)
3784 {
3785         struct vega10_hwmgr *data =
3786                         (struct vega10_hwmgr *)(hwmgr->backend);
3787
3788         data->smc_state_table.gfx_boot_level =
3789         data->smc_state_table.gfx_max_level =
3790                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3791         data->smc_state_table.mem_boot_level =
3792         data->smc_state_table.mem_max_level =
3793                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3794
3795         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3796                         "Failed to upload boot level to highest!",
3797                         return -1);
3798
3799         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3800                         "Failed to upload dpm max level to highest!",
3801                         return -1);
3802
3803         return 0;
3804
3805 }
3806
3807 static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
3808 {
3809         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
3810
3811         data->smc_state_table.gfx_boot_level =
3812                         vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
3813         data->smc_state_table.gfx_max_level =
3814                         vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table));
3815         data->smc_state_table.mem_boot_level =
3816                         vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table));
3817         data->smc_state_table.mem_max_level =
3818                         vega10_find_highest_dpm_level(&(data->dpm_table.mem_table));
3819
3820         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
3821                         "Failed to upload DPM Bootup Levels!",
3822                         return -1);
3823
3824         PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
3825                         "Failed to upload DPM Max Levels!",
3826                         return -1);
3827         return 0;
3828 }
3829
3830 static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
3831                                 enum amd_dpm_forced_level level)
3832 {
3833         int ret = 0;
3834
3835         switch (level) {
3836         case AMD_DPM_FORCED_LEVEL_HIGH:
3837                 ret = vega10_force_dpm_highest(hwmgr);
3838                 if (ret)
3839                         return ret;
3840                 break;
3841         case AMD_DPM_FORCED_LEVEL_LOW:
3842                 ret = vega10_force_dpm_lowest(hwmgr);
3843                 if (ret)
3844                         return ret;
3845                 break;
3846         case AMD_DPM_FORCED_LEVEL_AUTO:
3847                 ret = vega10_unforce_dpm_levels(hwmgr);
3848                 if (ret)
3849                         return ret;
3850                 break;
3851         default:
3852                 break;
3853         }
3854
3855         hwmgr->dpm_level = level;
3856
3857         return ret;
3858 }
3859
3860 static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
3861 {
3862         if (mode) {
3863                 /* stop auto-manage */
3864                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
3865                                 PHM_PlatformCaps_MicrocodeFanControl))
3866                         vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
3867                 vega10_fan_ctrl_set_static_mode(hwmgr, mode);
3868         } else
3869                 /* restart auto-manage */
3870                 vega10_fan_ctrl_reset_fan_speed_to_default(hwmgr);
3871
3872         return 0;
3873 }
3874
3875 static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr)
3876 {
3877         uint32_t reg;
3878
3879         if (hwmgr->fan_ctrl_is_in_default_mode) {
3880                 return hwmgr->fan_ctrl_default_mode;
3881         } else {
3882                 reg = soc15_get_register_offset(THM_HWID, 0,
3883                         mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
3884                 return (cgs_read_register(hwmgr->device, reg) &
3885                                 CG_FDO_CTRL2__FDO_PWM_MODE_MASK) >>
3886                                 CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;
3887         }
3888 }
3889
3890 static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr,
3891                 struct amd_pp_simple_clock_info *info)
3892 {
3893         struct phm_ppt_v2_information *table_info =
3894                         (struct phm_ppt_v2_information *)hwmgr->pptable;
3895         struct phm_clock_and_voltage_limits *max_limits =
3896                         &table_info->max_clock_voltage_on_ac;
3897
3898         info->engine_max_clock = max_limits->sclk;
3899         info->memory_max_clock = max_limits->mclk;
3900
3901         return 0;
3902 }
3903
3904 static void vega10_get_sclks(struct pp_hwmgr *hwmgr,
3905                 struct pp_clock_levels_with_latency *clocks)
3906 {
3907         struct phm_ppt_v2_information *table_info =
3908                         (struct phm_ppt_v2_information *)hwmgr->pptable;
3909         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
3910                         table_info->vdd_dep_on_sclk;
3911         uint32_t i;
3912
3913         for (i = 0; i < dep_table->count; i++) {
3914                 if (dep_table->entries[i].clk) {
3915                         clocks->data[clocks->num_levels].clocks_in_khz =
3916                                         dep_table->entries[i].clk;
3917                         clocks->num_levels++;
3918                 }
3919         }
3920
3921 }
3922
3923 static uint32_t vega10_get_mem_latency(struct pp_hwmgr *hwmgr,
3924                 uint32_t clock)
3925 {
3926         if (clock >= MEM_FREQ_LOW_LATENCY &&
3927                         clock < MEM_FREQ_HIGH_LATENCY)
3928                 return MEM_LATENCY_HIGH;
3929         else if (clock >= MEM_FREQ_HIGH_LATENCY)
3930                 return MEM_LATENCY_LOW;
3931         else
3932                 return MEM_LATENCY_ERR;
3933 }
3934
3935 static void vega10_get_memclocks(struct pp_hwmgr *hwmgr,
3936                 struct pp_clock_levels_with_latency *clocks)
3937 {
3938         struct phm_ppt_v2_information *table_info =
3939                         (struct phm_ppt_v2_information *)hwmgr->pptable;
3940         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
3941                         table_info->vdd_dep_on_mclk;
3942         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
3943         uint32_t i;
3944
3945         clocks->num_levels = 0;
3946         data->mclk_latency_table.count = 0;
3947
3948         for (i = 0; i < dep_table->count; i++) {
3949                 if (dep_table->entries[i].clk) {
3950                         clocks->data[clocks->num_levels].clocks_in_khz =
3951                         data->mclk_latency_table.entries
3952                         [data->mclk_latency_table.count].frequency =
3953                                         dep_table->entries[i].clk;
3954                         clocks->data[clocks->num_levels].latency_in_us =
3955                         data->mclk_latency_table.entries
3956                         [data->mclk_latency_table.count].latency =
3957                                         vega10_get_mem_latency(hwmgr,
3958                                                 dep_table->entries[i].clk);
3959                         clocks->num_levels++;
3960                         data->mclk_latency_table.count++;
3961                 }
3962         }
3963 }
3964
3965 static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr,
3966                 struct pp_clock_levels_with_latency *clocks)
3967 {
3968         struct phm_ppt_v2_information *table_info =
3969                         (struct phm_ppt_v2_information *)hwmgr->pptable;
3970         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
3971                         table_info->vdd_dep_on_dcefclk;
3972         uint32_t i;
3973
3974         for (i = 0; i < dep_table->count; i++) {
3975                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk;
3976                 clocks->data[i].latency_in_us = 0;
3977                 clocks->num_levels++;
3978         }
3979 }
3980
3981 static void vega10_get_socclocks(struct pp_hwmgr *hwmgr,
3982                 struct pp_clock_levels_with_latency *clocks)
3983 {
3984         struct phm_ppt_v2_information *table_info =
3985                         (struct phm_ppt_v2_information *)hwmgr->pptable;
3986         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
3987                         table_info->vdd_dep_on_socclk;
3988         uint32_t i;
3989
3990         for (i = 0; i < dep_table->count; i++) {
3991                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk;
3992                 clocks->data[i].latency_in_us = 0;
3993                 clocks->num_levels++;
3994         }
3995 }
3996
3997 static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
3998                 enum amd_pp_clock_type type,
3999                 struct pp_clock_levels_with_latency *clocks)
4000 {
4001         switch (type) {
4002         case amd_pp_sys_clock:
4003                 vega10_get_sclks(hwmgr, clocks);
4004                 break;
4005         case amd_pp_mem_clock:
4006                 vega10_get_memclocks(hwmgr, clocks);
4007                 break;
4008         case amd_pp_dcef_clock:
4009                 vega10_get_dcefclocks(hwmgr, clocks);
4010                 break;
4011         case amd_pp_soc_clock:
4012                 vega10_get_socclocks(hwmgr, clocks);
4013                 break;
4014         default:
4015                 return -1;
4016         }
4017
4018         return 0;
4019 }
4020
4021 static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
4022                 enum amd_pp_clock_type type,
4023                 struct pp_clock_levels_with_voltage *clocks)
4024 {
4025         struct phm_ppt_v2_information *table_info =
4026                         (struct phm_ppt_v2_information *)hwmgr->pptable;
4027         struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
4028         uint32_t i;
4029
4030         switch (type) {
4031         case amd_pp_mem_clock:
4032                 dep_table = table_info->vdd_dep_on_mclk;
4033                 break;
4034         case amd_pp_dcef_clock:
4035                 dep_table = table_info->vdd_dep_on_dcefclk;
4036                 break;
4037         case amd_pp_disp_clock:
4038                 dep_table = table_info->vdd_dep_on_dispclk;
4039                 break;
4040         case amd_pp_pixel_clock:
4041                 dep_table = table_info->vdd_dep_on_pixclk;
4042                 break;
4043         case amd_pp_phy_clock:
4044                 dep_table = table_info->vdd_dep_on_phyclk;
4045                 break;
4046         default:
4047                 return -1;
4048         }
4049
4050         for (i = 0; i < dep_table->count; i++) {
4051                 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk;
4052                 clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table->
4053                                 entries[dep_table->entries[i].vddInd].us_vdd);
4054                 clocks->num_levels++;
4055         }
4056
4057         if (i < dep_table->count)
4058                 return -1;
4059
4060         return 0;
4061 }
4062
4063 static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
4064                 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
4065 {
4066         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4067         Watermarks_t *table = &(data->smc_state_table.water_marks_table);
4068         int result = 0;
4069         uint32_t i;
4070
4071         if (!data->registry_data.disable_water_mark) {
4072                 for (i = 0; i < wm_with_clock_ranges->num_wm_sets_dmif; i++) {
4073                         table->WatermarkRow[WM_DCEFCLK][i].MinClock =
4074                                 cpu_to_le16((uint16_t)
4075                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_min_dcefclk_in_khz) /
4076                                 100);
4077                         table->WatermarkRow[WM_DCEFCLK][i].MaxClock =
4078                                 cpu_to_le16((uint16_t)
4079                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_max_dcefclk_in_khz) /
4080                                 100);
4081                         table->WatermarkRow[WM_DCEFCLK][i].MinUclk =
4082                                 cpu_to_le16((uint16_t)
4083                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_min_memclk_in_khz) /
4084                                 100);
4085                         table->WatermarkRow[WM_DCEFCLK][i].MaxUclk =
4086                                 cpu_to_le16((uint16_t)
4087                                 (wm_with_clock_ranges->wm_sets_dmif[i].wm_max_memclk_in_khz) /
4088                                 100);
4089                         table->WatermarkRow[WM_DCEFCLK][i].WmSetting = (uint8_t)
4090                                         wm_with_clock_ranges->wm_sets_dmif[i].wm_set_id;
4091                 }
4092
4093                 for (i = 0; i < wm_with_clock_ranges->num_wm_sets_mcif; i++) {
4094                         table->WatermarkRow[WM_SOCCLK][i].MinClock =
4095                                 cpu_to_le16((uint16_t)
4096                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_min_socclk_in_khz) /
4097                                 100);
4098                         table->WatermarkRow[WM_SOCCLK][i].MaxClock =
4099                                 cpu_to_le16((uint16_t)
4100                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_max_socclk_in_khz) /
4101                                 100);
4102                         table->WatermarkRow[WM_SOCCLK][i].MinUclk =
4103                                 cpu_to_le16((uint16_t)
4104                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_min_memclk_in_khz) /
4105                                 100);
4106                         table->WatermarkRow[WM_SOCCLK][i].MaxUclk =
4107                                 cpu_to_le16((uint16_t)
4108                                 (wm_with_clock_ranges->wm_sets_mcif[i].wm_max_memclk_in_khz) /
4109                                 100);
4110                         table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t)
4111                                         wm_with_clock_ranges->wm_sets_mcif[i].wm_set_id;
4112                 }
4113                 data->water_marks_bitmap = WaterMarksExist;
4114         }
4115
4116         return result;
4117 }
4118
4119 static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
4120                 enum pp_clock_type type, uint32_t mask)
4121 {
4122         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4123         uint32_t i;
4124
4125         if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
4126                 return -EINVAL;
4127
4128         switch (type) {
4129         case PP_SCLK:
4130                 if (data->registry_data.sclk_dpm_key_disabled)
4131                         break;
4132
4133                 for (i = 0; i < 32; i++) {
4134                         if (mask & (1 << i))
4135                                 break;
4136                 }
4137
4138                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
4139                                 hwmgr->smumgr,
4140                                 PPSMC_MSG_SetSoftMinGfxclkByIndex,
4141                                 i),
4142                                 "Failed to set soft min sclk index!",
4143                                 return -1);
4144                 break;
4145
4146         case PP_MCLK:
4147                 if (data->registry_data.mclk_dpm_key_disabled)
4148                         break;
4149
4150                 for (i = 0; i < 32; i++) {
4151                         if (mask & (1 << i))
4152                                 break;
4153                 }
4154
4155                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
4156                                 hwmgr->smumgr,
4157                                 PPSMC_MSG_SetSoftMinUclkByIndex,
4158                                 i),
4159                                 "Failed to set soft min mclk index!",
4160                                 return -1);
4161                 break;
4162
4163         case PP_PCIE:
4164                 if (data->registry_data.pcie_dpm_key_disabled)
4165                         break;
4166
4167                 for (i = 0; i < 32; i++) {
4168                         if (mask & (1 << i))
4169                                 break;
4170                 }
4171
4172                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
4173                                 hwmgr->smumgr,
4174                                 PPSMC_MSG_SetMinLinkDpmByIndex,
4175                                 i),
4176                                 "Failed to set min pcie index!",
4177                                 return -1);
4178                 break;
4179         default:
4180                 break;
4181         }
4182
4183         return 0;
4184 }
4185
4186 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
4187                 enum pp_clock_type type, char *buf)
4188 {
4189         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4190         struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
4191         struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
4192         struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
4193         int i, now, size = 0;
4194
4195         switch (type) {
4196         case PP_SCLK:
4197                 if (data->registry_data.sclk_dpm_key_disabled)
4198                         break;
4199
4200                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr,
4201                                 PPSMC_MSG_GetCurrentGfxclkIndex),
4202                                 "Attempt to get current sclk index Failed!",
4203                                 return -1);
4204                 PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr,
4205                                 &now),
4206                                 "Attempt to read sclk index Failed!",
4207                                 return -1);
4208
4209                 for (i = 0; i < sclk_table->count; i++)
4210                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4211                                         i, sclk_table->dpm_levels[i].value / 100,
4212                                         (i == now) ? "*" : "");
4213                 break;
4214         case PP_MCLK:
4215                 if (data->registry_data.mclk_dpm_key_disabled)
4216                         break;
4217
4218                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr,
4219                                 PPSMC_MSG_GetCurrentUclkIndex),
4220                                 "Attempt to get current mclk index Failed!",
4221                                 return -1);
4222                 PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr,
4223                                 &now),
4224                                 "Attempt to read mclk index Failed!",
4225                                 return -1);
4226
4227                 for (i = 0; i < mclk_table->count; i++)
4228                         size += sprintf(buf + size, "%d: %uMhz %s\n",
4229                                         i, mclk_table->dpm_levels[i].value / 100,
4230                                         (i == now) ? "*" : "");
4231                 break;
4232         case PP_PCIE:
4233                 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr->smumgr,
4234                                 PPSMC_MSG_GetCurrentLinkIndex),
4235                                 "Attempt to get current mclk index Failed!",
4236                                 return -1);
4237                 PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr->smumgr,
4238                                 &now),
4239                                 "Attempt to read mclk index Failed!",
4240                                 return -1);
4241
4242                 for (i = 0; i < pcie_table->count; i++)
4243                         size += sprintf(buf + size, "%d: %s %s\n", i,
4244                                         (pcie_table->pcie_gen[i] == 0) ? "2.5GB, x1" :
4245                                         (pcie_table->pcie_gen[i] == 1) ? "5.0GB, x16" :
4246                                         (pcie_table->pcie_gen[i] == 2) ? "8.0GB, x16" : "",
4247                                         (i == now) ? "*" : "");
4248                 break;
4249         default:
4250                 break;
4251         }
4252         return size;
4253 }
4254
4255 static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
4256 {
4257         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4258         int result = 0;
4259         uint32_t num_turned_on_displays = 1;
4260         Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
4261         struct cgs_display_info info = {0};
4262
4263         if ((data->water_marks_bitmap & WaterMarksExist) &&
4264                         !(data->water_marks_bitmap & WaterMarksLoaded)) {
4265                 result = vega10_copy_table_to_smc(hwmgr->smumgr,
4266                         (uint8_t *)wm_table, WMTABLE);
4267                 PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL);
4268                 data->water_marks_bitmap |= WaterMarksLoaded;
4269         }
4270
4271         if (data->water_marks_bitmap & WaterMarksLoaded) {
4272                 cgs_get_active_displays_info(hwmgr->device, &info);
4273                 num_turned_on_displays = info.display_count;
4274                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
4275                         PPSMC_MSG_NumOfDisplays, num_turned_on_displays);
4276         }
4277
4278         return result;
4279 }
4280
4281 int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
4282 {
4283         struct vega10_hwmgr *data =
4284                         (struct vega10_hwmgr *)(hwmgr->backend);
4285
4286         if (data->smu_features[GNLD_DPM_UVD].supported) {
4287                 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
4288                                 enable,
4289                                 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap),
4290                                 "Attempt to Enable/Disable DPM UVD Failed!",
4291                                 return -1);
4292                 data->smu_features[GNLD_DPM_UVD].enabled = enable;
4293         }
4294         return 0;
4295 }
4296
4297 static int vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
4298 {
4299         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4300
4301         data->vce_power_gated = bgate;
4302         return vega10_enable_disable_vce_dpm(hwmgr, !bgate);
4303 }
4304
4305 static int vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
4306 {
4307         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4308
4309         data->uvd_power_gated = bgate;
4310         return vega10_enable_disable_uvd_dpm(hwmgr, !bgate);
4311 }
4312
4313 static inline bool vega10_are_power_levels_equal(
4314                                 const struct vega10_performance_level *pl1,
4315                                 const struct vega10_performance_level *pl2)
4316 {
4317         return ((pl1->soc_clock == pl2->soc_clock) &&
4318                         (pl1->gfx_clock == pl2->gfx_clock) &&
4319                         (pl1->mem_clock == pl2->mem_clock));
4320 }
4321
4322 static int vega10_check_states_equal(struct pp_hwmgr *hwmgr,
4323                                 const struct pp_hw_power_state *pstate1,
4324                         const struct pp_hw_power_state *pstate2, bool *equal)
4325 {
4326         const struct vega10_power_state *psa;
4327         const struct vega10_power_state *psb;
4328         int i;
4329
4330         if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
4331                 return -EINVAL;
4332
4333         psa = cast_const_phw_vega10_power_state(pstate1);
4334         psb = cast_const_phw_vega10_power_state(pstate2);
4335         /* If the two states don't even have the same number of performance levels they cannot be the same state. */
4336         if (psa->performance_level_count != psb->performance_level_count) {
4337                 *equal = false;
4338                 return 0;
4339         }
4340
4341         for (i = 0; i < psa->performance_level_count; i++) {
4342                 if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
4343                         /* If we have found even one performance level pair that is different the states are different. */
4344                         *equal = false;
4345                         return 0;
4346                 }
4347         }
4348
4349         /* If all performance levels are the same try to use the UVD clocks to break the tie.*/
4350         *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
4351         *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
4352         *equal &= (psa->sclk_threshold == psb->sclk_threshold);
4353
4354         return 0;
4355 }
4356
4357 static bool
4358 vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
4359 {
4360         struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
4361         bool is_update_required = false;
4362         struct cgs_display_info info = {0, 0, NULL};
4363
4364         cgs_get_active_displays_info(hwmgr->device, &info);
4365
4366         if (data->display_timing.num_existing_displays != info.display_count)
4367                 is_update_required = true;
4368
4369         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
4370                 if (data->display_timing.min_clock_in_sr != hwmgr->display_config.min_core_set_clock_in_sr)
4371                         is_update_required = true;
4372         }
4373
4374         return is_update_required;
4375 }
4376
4377 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
4378         .backend_init = vega10_hwmgr_backend_init,
4379         .backend_fini = vega10_hwmgr_backend_fini,
4380         .asic_setup = vega10_setup_asic_task,
4381         .dynamic_state_management_enable = vega10_enable_dpm_tasks,
4382         .get_num_of_pp_table_entries =
4383                         vega10_get_number_of_powerplay_table_entries,
4384         .get_power_state_size = vega10_get_power_state_size,
4385         .get_pp_table_entry = vega10_get_pp_table_entry,
4386         .patch_boot_state = vega10_patch_boot_state,
4387         .apply_state_adjust_rules = vega10_apply_state_adjust_rules,
4388         .power_state_set = vega10_set_power_state_tasks,
4389         .get_sclk = vega10_dpm_get_sclk,
4390         .get_mclk = vega10_dpm_get_mclk,
4391         .notify_smc_display_config_after_ps_adjustment =
4392                         vega10_notify_smc_display_config_after_ps_adjustment,
4393         .force_dpm_level = vega10_dpm_force_dpm_level,
4394         .get_temperature = vega10_thermal_get_temperature,
4395         .stop_thermal_controller = vega10_thermal_stop_thermal_controller,
4396         .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info,
4397         .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent,
4398         .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent,
4399         .reset_fan_speed_to_default =
4400                         vega10_fan_ctrl_reset_fan_speed_to_default,
4401         .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm,
4402         .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm,
4403         .uninitialize_thermal_controller =
4404                         vega10_thermal_ctrl_uninitialize_thermal_controller,
4405         .set_fan_control_mode = vega10_set_fan_control_mode,
4406         .get_fan_control_mode = vega10_get_fan_control_mode,
4407         .read_sensor = vega10_read_sensor,
4408         .get_dal_power_level = vega10_get_dal_power_level,
4409         .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency,
4410         .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage,
4411         .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges,
4412         .display_clock_voltage_request = vega10_display_clock_voltage_request,
4413         .force_clock_level = vega10_force_clock_level,
4414         .print_clock_levels = vega10_print_clock_levels,
4415         .display_config_changed = vega10_display_configuration_changed_task,
4416         .powergate_uvd = vega10_power_gate_uvd,
4417         .powergate_vce = vega10_power_gate_vce,
4418         .check_states_equal = vega10_check_states_equal,
4419         .check_smc_update_required_for_display_configuration =
4420                         vega10_check_smc_update_required_for_display_configuration,
4421 };
4422
4423 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
4424 {
4425         hwmgr->hwmgr_func = &vega10_hwmgr_funcs;
4426         hwmgr->pptable_func = &vega10_pptable_funcs;
4427         pp_vega10_thermal_initialize(hwmgr);
4428         return 0;
4429 }