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