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