Bug Summary

File:dev/pci/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
Warning:line 3207, column 2
Value stored to 'result' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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