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