Bug Summary

File:dev/pci/drm/radeon/sumo_dpm.c
Warning:line 743, column 18
The result of the left shift is undefined due to shifting by '4294967295', which is greater or equal to the width of type 'int'

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 sumo_dpm.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/radeon/sumo_dpm.c
1/*
2 * Copyright 2012 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 "radeon.h"
25#include "radeon_asic.h"
26#include "sumod.h"
27#include "r600_dpm.h"
28#include "cypress_dpm.h"
29#include "sumo_dpm.h"
30#include <linux/seq_file.h>
31
32#define SUMO_MAX_DEEPSLEEP_DIVIDER_ID5 5
33#define SUMO_MINIMUM_ENGINE_CLOCK800 800
34#define BOOST_DPM_LEVEL7 7
35
36static const u32 sumo_utc[SUMO_PM_NUMBER_OF_TC15] =
37{
38 SUMO_UTC_DFLT_000x48,
39 SUMO_UTC_DFLT_010x44,
40 SUMO_UTC_DFLT_020x44,
41 SUMO_UTC_DFLT_030x44,
42 SUMO_UTC_DFLT_040x44,
43 SUMO_UTC_DFLT_050x44,
44 SUMO_UTC_DFLT_060x44,
45 SUMO_UTC_DFLT_070x44,
46 SUMO_UTC_DFLT_080x44,
47 SUMO_UTC_DFLT_090x44,
48 SUMO_UTC_DFLT_100x44,
49 SUMO_UTC_DFLT_110x44,
50 SUMO_UTC_DFLT_120x44,
51 SUMO_UTC_DFLT_130x44,
52 SUMO_UTC_DFLT_140x44,
53};
54
55static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC15] =
56{
57 SUMO_DTC_DFLT_000x48,
58 SUMO_DTC_DFLT_010x44,
59 SUMO_DTC_DFLT_020x44,
60 SUMO_DTC_DFLT_030x44,
61 SUMO_DTC_DFLT_040x44,
62 SUMO_DTC_DFLT_050x44,
63 SUMO_DTC_DFLT_060x44,
64 SUMO_DTC_DFLT_070x44,
65 SUMO_DTC_DFLT_080x44,
66 SUMO_DTC_DFLT_090x44,
67 SUMO_DTC_DFLT_100x44,
68 SUMO_DTC_DFLT_110x44,
69 SUMO_DTC_DFLT_120x44,
70 SUMO_DTC_DFLT_130x44,
71 SUMO_DTC_DFLT_140x44,
72};
73
74static struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
75{
76 struct sumo_ps *ps = rps->ps_priv;
77
78 return ps;
79}
80
81struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev)
82{
83 struct sumo_power_info *pi = rdev->pm.dpm.priv;
84
85 return pi;
86}
87
88static void sumo_gfx_clockgating_enable(struct radeon_device *rdev, bool_Bool enable)
89{
90 if (enable)
91 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 7)); tmp_ |= (((1 << 7)) & ~(~(1 <<
7))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0)
;
92 else {
93 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 7)); tmp_ |= ((0) & ~(~(1 << 7))); r100_mm_wreg
(rdev, (0x644), (tmp_), 0); } while (0)
;
94 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 8)); tmp_ |= (((1 << 8)) & ~(~(1 <<
8))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0)
;
95 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 8)); tmp_ |= ((0) & ~(~(1 << 8))); r100_mm_wreg
(rdev, (0x644), (tmp_), 0); } while (0)
;
96 RREG32(GB_ADDR_CONFIG)r100_mm_rreg(rdev, (0x98f8), 0);
97 }
98}
99
100#define CGCG_CGTT_LOCAL0_MASK0xE5BFFFFF 0xE5BFFFFF
101#define CGCG_CGTT_LOCAL1_MASK0xEFFF07FF 0xEFFF07FF
102
103static void sumo_mg_clockgating_enable(struct radeon_device *rdev, bool_Bool enable)
104{
105 u32 local0;
106 u32 local1;
107
108 local0 = RREG32(CG_CGTT_LOCAL_0)r100_mm_rreg(rdev, (0x7d0), 0);
109 local1 = RREG32(CG_CGTT_LOCAL_1)r100_mm_rreg(rdev, (0x7d4), 0);
110
111 if (enable) {
112 WREG32(CG_CGTT_LOCAL_0, (0 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) )r100_mm_wreg(rdev, (0x7d0), ((0 & 0xE5BFFFFF) | (local0 &
~0xE5BFFFFF)), 0)
;
113 WREG32(CG_CGTT_LOCAL_1, (0 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) )r100_mm_wreg(rdev, (0x7d4), ((0 & 0xEFFF07FF) | (local1 &
~0xEFFF07FF)), 0)
;
114 } else {
115 WREG32(CG_CGTT_LOCAL_0, (0xFFFFFFFF & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) )r100_mm_wreg(rdev, (0x7d0), ((0xFFFFFFFF & 0xE5BFFFFF) | (
local0 & ~0xE5BFFFFF)), 0)
;
116 WREG32(CG_CGTT_LOCAL_1, (0xFFFFCFFF & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) )r100_mm_wreg(rdev, (0x7d4), ((0xFFFFCFFF & 0xEFFF07FF) | (
local1 & ~0xEFFF07FF)), 0)
;
117 }
118}
119
120static void sumo_program_git(struct radeon_device *rdev)
121{
122 u32 p, u;
123 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
124
125 r600_calculate_u_and_p(SUMO_GICST_DFLT19,
126 xclk, 16, &p, &u);
127
128 WREG32_P(CG_GIT, CG_GICST(p), ~CG_GICST_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6d8), 0); tmp_ &=
(~(0xffff << 0)); tmp_ |= ((((p) << 0)) & ~(
~(0xffff << 0))); r100_mm_wreg(rdev, (0x6d8), (tmp_), 0
); } while (0)
;
129}
130
131static void sumo_program_grsd(struct radeon_device *rdev)
132{
133 u32 p, u;
134 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
135 u32 grs = 256 * 25 / 100;
136
137 r600_calculate_u_and_p(1, xclk, 14, &p, &u);
138
139 WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u))r100_mm_wreg(rdev, (0x68c), (((grs) << 0) | ((p) <<
9) | ((u) << 23)), 0)
;
140}
141
142void sumo_gfx_clockgating_initialize(struct radeon_device *rdev)
143{
144 sumo_program_git(rdev);
145 sumo_program_grsd(rdev);
146}
147
148static void sumo_gfx_powergating_initialize(struct radeon_device *rdev)
149{
150 u32 rcu_pwr_gating_cntl;
151 u32 p, u;
152 u32 p_c, p_p, d_p;
153 u32 r_t, i_t;
154 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
155
156 if (rdev->family == CHIP_PALM) {
157 p_c = 4;
158 d_p = 10;
159 r_t = 10;
160 i_t = 4;
161 p_p = 50 + 1000/200 + 6 * 32;
162 } else {
163 p_c = 16;
164 d_p = 50;
165 r_t = 50;
166 i_t = 50;
167 p_p = 113;
168 }
169
170 WREG32(CG_SCRATCH2, 0x01B60A17)r100_mm_wreg(rdev, (0x824), (0x01B60A17), 0);
171
172 r600_calculate_u_and_p(SUMO_GFXPOWERGATINGT_DFLT100,
173 xclk, 16, &p, &u);
174
175 WREG32_P(CG_PWR_GATING_CNTL, PGP(p) | PGU(u),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &=
(~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p)
<< 8) | ((u) << 24)) & ~(~((0xffff << 8
) | (0xf << 24)))); r100_mm_wreg(rdev, (0x7ac), (tmp_),
0); } while (0)
176 ~(PGP_MASK | PGU_MASK))do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &=
(~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p)
<< 8) | ((u) << 24)) & ~(~((0xffff << 8
) | (0xf << 24)))); r100_mm_wreg(rdev, (0x7ac), (tmp_),
0); } while (0)
;
177
178 r600_calculate_u_and_p(SUMO_VOLTAGEDROPT_DFLT1,
179 xclk, 16, &p, &u);
180
181 WREG32_P(CG_CG_VOLTAGE_CNTL, PGP(p) | PGU(u),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &=
(~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p)
<< 8) | ((u) << 24)) & ~(~((0xffff << 8
) | (0xf << 24)))); r100_mm_wreg(rdev, (0x770), (tmp_),
0); } while (0)
182 ~(PGP_MASK | PGU_MASK))do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &=
(~((0xffff << 8) | (0xf << 24))); tmp_ |= ((((p)
<< 8) | ((u) << 24)) & ~(~((0xffff << 8
) | (0xf << 24)))); r100_mm_wreg(rdev, (0x770), (tmp_),
0); } while (0)
;
183
184 if (rdev->family == CHIP_PALM) {
185 WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x10103210)r600_rcu_wreg(rdev, (0x408), (0x10103210));
186 WREG32_RCU(RCU_PWR_GATING_SEQ1, 0x10101010)r600_rcu_wreg(rdev, (0x40c), (0x10101010));
187 } else {
188 WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x76543210)r600_rcu_wreg(rdev, (0x408), (0x76543210));
189 WREG32_RCU(RCU_PWR_GATING_SEQ1, 0xFEDCBA98)r600_rcu_wreg(rdev, (0x40c), (0xFEDCBA98));
190 }
191
192 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL)r600_rcu_rreg(rdev, (0x410));
193 rcu_pwr_gating_cntl &=
194 ~(RSVD_MASK(0x3 << 1) | PCV_MASK(0x1f << 3) | PGS_MASK(0xf << 28));
195 rcu_pwr_gating_cntl |= PCV(p_c)((p_c) << 3) | PGS(1)((1) << 28) | PWR_GATING_EN(1 << 0);
196 if (rdev->family == CHIP_PALM) {
197 rcu_pwr_gating_cntl &= ~PCP_MASK(0xf << 8);
198 rcu_pwr_gating_cntl |= PCP(0x77)((0x77) << 8);
199 }
200 WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x410), (rcu_pwr_gating_cntl));
201
202 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2)r600_rcu_rreg(rdev, (0x4a0));
203 rcu_pwr_gating_cntl &= ~(MPPU_MASK(0xffff << 0) | MPPD_MASK(0xffff << 16));
204 rcu_pwr_gating_cntl |= MPPU(p_p)((p_p) << 0) | MPPD(50)((50) << 16);
205 WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a0), (rcu_pwr_gating_cntl));
206
207 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3)r600_rcu_rreg(rdev, (0x4a4));
208 rcu_pwr_gating_cntl &= ~(DPPU_MASK(0xffff << 0) | DPPD_MASK(0xffff << 16));
209 rcu_pwr_gating_cntl |= DPPU(d_p)((d_p) << 0) | DPPD(50)((50) << 16);
210 WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a4), (rcu_pwr_gating_cntl));
211
212 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_4)r600_rcu_rreg(rdev, (0x4a8));
213 rcu_pwr_gating_cntl &= ~(RT_MASK(0xffff << 0) | IT_MASK(0xffff << 16));
214 rcu_pwr_gating_cntl |= RT(r_t)((r_t) << 0) | IT(i_t)((i_t) << 16);
215 WREG32_RCU(RCU_PWR_GATING_CNTL_4, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a8), (rcu_pwr_gating_cntl));
216
217 if (rdev->family == CHIP_PALM)
218 WREG32_RCU(RCU_PWR_GATING_CNTL_5, 0xA02)r600_rcu_wreg(rdev, (0x504), (0xA02));
219
220 sumo_smu_pg_init(rdev);
221
222 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL)r600_rcu_rreg(rdev, (0x410));
223 rcu_pwr_gating_cntl &=
224 ~(RSVD_MASK(0x3 << 1) | PCV_MASK(0x1f << 3) | PGS_MASK(0xf << 28));
225 rcu_pwr_gating_cntl |= PCV(p_c)((p_c) << 3) | PGS(4)((4) << 28) | PWR_GATING_EN(1 << 0);
226 if (rdev->family == CHIP_PALM) {
227 rcu_pwr_gating_cntl &= ~PCP_MASK(0xf << 8);
228 rcu_pwr_gating_cntl |= PCP(0x77)((0x77) << 8);
229 }
230 WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x410), (rcu_pwr_gating_cntl));
231
232 if (rdev->family == CHIP_PALM) {
233 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2)r600_rcu_rreg(rdev, (0x4a0));
234 rcu_pwr_gating_cntl &= ~(MPPU_MASK(0xffff << 0) | MPPD_MASK(0xffff << 16));
235 rcu_pwr_gating_cntl |= MPPU(113)((113) << 0) | MPPD(50)((50) << 16);
236 WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a0), (rcu_pwr_gating_cntl));
237
238 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3)r600_rcu_rreg(rdev, (0x4a4));
239 rcu_pwr_gating_cntl &= ~(DPPU_MASK(0xffff << 0) | DPPD_MASK(0xffff << 16));
240 rcu_pwr_gating_cntl |= DPPU(16)((16) << 0) | DPPD(50)((50) << 16);
241 WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a4), (rcu_pwr_gating_cntl));
242 }
243
244 sumo_smu_pg_init(rdev);
245
246 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL)r600_rcu_rreg(rdev, (0x410));
247 rcu_pwr_gating_cntl &=
248 ~(RSVD_MASK(0x3 << 1) | PCV_MASK(0x1f << 3) | PGS_MASK(0xf << 28));
249 rcu_pwr_gating_cntl |= PGS(5)((5) << 28) | PWR_GATING_EN(1 << 0);
250
251 if (rdev->family == CHIP_PALM) {
252 rcu_pwr_gating_cntl |= PCV(4)((4) << 3);
253 rcu_pwr_gating_cntl &= ~PCP_MASK(0xf << 8);
254 rcu_pwr_gating_cntl |= PCP(0x77)((0x77) << 8);
255 } else
256 rcu_pwr_gating_cntl |= PCV(11)((11) << 3);
257 WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x410), (rcu_pwr_gating_cntl));
258
259 if (rdev->family == CHIP_PALM) {
260 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2)r600_rcu_rreg(rdev, (0x4a0));
261 rcu_pwr_gating_cntl &= ~(MPPU_MASK(0xffff << 0) | MPPD_MASK(0xffff << 16));
262 rcu_pwr_gating_cntl |= MPPU(113)((113) << 0) | MPPD(50)((50) << 16);
263 WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a0), (rcu_pwr_gating_cntl));
264
265 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3)r600_rcu_rreg(rdev, (0x4a4));
266 rcu_pwr_gating_cntl &= ~(DPPU_MASK(0xffff << 0) | DPPD_MASK(0xffff << 16));
267 rcu_pwr_gating_cntl |= DPPU(22)((22) << 0) | DPPD(50)((50) << 16);
268 WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl)r600_rcu_wreg(rdev, (0x4a4), (rcu_pwr_gating_cntl));
269 }
270
271 sumo_smu_pg_init(rdev);
272}
273
274static void sumo_gfx_powergating_enable(struct radeon_device *rdev, bool_Bool enable)
275{
276 if (enable)
277 WREG32_P(CG_PWR_GATING_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &=
(~(1 << 0)); tmp_ |= (((1 << 0)) & ~(~(1 <<
0))); r100_mm_wreg(rdev, (0x7ac), (tmp_), 0); } while (0)
;
278 else {
279 WREG32_P(CG_PWR_GATING_CNTL, 0, ~DYN_PWR_DOWN_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x7ac), 0); tmp_ &=
(~(1 << 0)); tmp_ |= ((0) & ~(~(1 << 0))); r100_mm_wreg
(rdev, (0x7ac), (tmp_), 0); } while (0)
;
280 RREG32(GB_ADDR_CONFIG)r100_mm_rreg(rdev, (0x98f8), 0);
281 }
282}
283
284static int sumo_enable_clock_power_gating(struct radeon_device *rdev)
285{
286 struct sumo_power_info *pi = sumo_get_pi(rdev);
287
288 if (pi->enable_gfx_clock_gating)
289 sumo_gfx_clockgating_initialize(rdev);
290 if (pi->enable_gfx_power_gating)
291 sumo_gfx_powergating_initialize(rdev);
292 if (pi->enable_mg_clock_gating)
293 sumo_mg_clockgating_enable(rdev, true1);
294 if (pi->enable_gfx_clock_gating)
295 sumo_gfx_clockgating_enable(rdev, true1);
296 if (pi->enable_gfx_power_gating)
297 sumo_gfx_powergating_enable(rdev, true1);
298
299 return 0;
300}
301
302static void sumo_disable_clock_power_gating(struct radeon_device *rdev)
303{
304 struct sumo_power_info *pi = sumo_get_pi(rdev);
305
306 if (pi->enable_gfx_clock_gating)
307 sumo_gfx_clockgating_enable(rdev, false0);
308 if (pi->enable_gfx_power_gating)
309 sumo_gfx_powergating_enable(rdev, false0);
310 if (pi->enable_mg_clock_gating)
311 sumo_mg_clockgating_enable(rdev, false0);
312}
313
314static void sumo_calculate_bsp(struct radeon_device *rdev,
315 u32 high_clk)
316{
317 struct sumo_power_info *pi = sumo_get_pi(rdev);
318 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
319
320 pi->pasi = 65535 * 100 / high_clk;
321 pi->asi = 65535 * 100 / high_clk;
322
323 r600_calculate_u_and_p(pi->asi,
324 xclk, 16, &pi->bsp, &pi->bsu);
325
326 r600_calculate_u_and_p(pi->pasi,
327 xclk, 16, &pi->pbsp, &pi->pbsu);
328
329 pi->dsp = BSP(pi->bsp)((pi->bsp) << 0) | BSU(pi->bsu)((pi->bsu) << 16);
330 pi->psp = BSP(pi->pbsp)((pi->pbsp) << 0) | BSU(pi->pbsu)((pi->pbsu) << 16);
331}
332
333static void sumo_init_bsp(struct radeon_device *rdev)
334{
335 struct sumo_power_info *pi = sumo_get_pi(rdev);
336
337 WREG32(CG_BSP_0, pi->psp)r100_mm_wreg(rdev, (0x750), (pi->psp), 0);
338}
339
340
341static void sumo_program_bsp(struct radeon_device *rdev,
342 struct radeon_ps *rps)
343{
344 struct sumo_power_info *pi = sumo_get_pi(rdev);
345 struct sumo_ps *ps = sumo_get_ps(rps);
346 u32 i;
347 u32 highest_engine_clock = ps->levels[ps->num_levels - 1].sclk;
348
349 if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1))
350 highest_engine_clock = pi->boost_pl.sclk;
351
352 sumo_calculate_bsp(rdev, highest_engine_clock);
353
354 for (i = 0; i < ps->num_levels - 1; i++)
355 WREG32(CG_BSP_0 + (i * 4), pi->dsp)r100_mm_wreg(rdev, (0x750 + (i * 4)), (pi->dsp), 0);
356
357 WREG32(CG_BSP_0 + (i * 4), pi->psp)r100_mm_wreg(rdev, (0x750 + (i * 4)), (pi->psp), 0);
358
359 if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1))
360 WREG32(CG_BSP_0 + (BOOST_DPM_LEVEL * 4), pi->psp)r100_mm_wreg(rdev, (0x750 + (7 * 4)), (pi->psp), 0);
361}
362
363static void sumo_write_at(struct radeon_device *rdev,
364 u32 index, u32 value)
365{
366 if (index == 0)
367 WREG32(CG_AT_0, value)r100_mm_wreg(rdev, (0x728), (value), 0);
368 else if (index == 1)
369 WREG32(CG_AT_1, value)r100_mm_wreg(rdev, (0x72c), (value), 0);
370 else if (index == 2)
371 WREG32(CG_AT_2, value)r100_mm_wreg(rdev, (0x730), (value), 0);
372 else if (index == 3)
373 WREG32(CG_AT_3, value)r100_mm_wreg(rdev, (0x738), (value), 0);
374 else if (index == 4)
375 WREG32(CG_AT_4, value)r100_mm_wreg(rdev, (0x73c), (value), 0);
376 else if (index == 5)
377 WREG32(CG_AT_5, value)r100_mm_wreg(rdev, (0x740), (value), 0);
378 else if (index == 6)
379 WREG32(CG_AT_6, value)r100_mm_wreg(rdev, (0x744), (value), 0);
380 else if (index == 7)
381 WREG32(CG_AT_7, value)r100_mm_wreg(rdev, (0x748), (value), 0);
382}
383
384static void sumo_program_at(struct radeon_device *rdev,
385 struct radeon_ps *rps)
386{
387 struct sumo_power_info *pi = sumo_get_pi(rdev);
388 struct sumo_ps *ps = sumo_get_ps(rps);
389 u32 asi;
390 u32 i;
391 u32 m_a;
392 u32 a_t;
393 u32 r[SUMO_MAX_HARDWARE_POWERLEVELS5];
394 u32 l[SUMO_MAX_HARDWARE_POWERLEVELS5];
395
396 r[0] = SUMO_R_DFLT070;
397 r[1] = SUMO_R_DFLT170;
398 r[2] = SUMO_R_DFLT270;
399 r[3] = SUMO_R_DFLT370;
400 r[4] = SUMO_R_DFLT4100;
401
402 l[0] = SUMO_L_DFLT00;
403 l[1] = SUMO_L_DFLT120;
404 l[2] = SUMO_L_DFLT220;
405 l[3] = SUMO_L_DFLT320;
406 l[4] = SUMO_L_DFLT420;
407
408 for (i = 0; i < ps->num_levels; i++) {
409 asi = (i == ps->num_levels - 1) ? pi->pasi : pi->asi;
410
411 m_a = asi * ps->levels[i].sclk / 100;
412
413 a_t = CG_R(m_a * r[i] / 100)((m_a * r[i] / 100) << 0) | CG_L(m_a * l[i] / 100)((m_a * l[i] / 100) << 16);
414
415 sumo_write_at(rdev, i, a_t);
416 }
417
418 if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) {
419 asi = pi->pasi;
420
421 m_a = asi * pi->boost_pl.sclk / 100;
422
423 a_t = CG_R(m_a * r[ps->num_levels - 1] / 100)((m_a * r[ps->num_levels - 1] / 100) << 0) |
424 CG_L(m_a * l[ps->num_levels - 1] / 100)((m_a * l[ps->num_levels - 1] / 100) << 16);
425
426 sumo_write_at(rdev, BOOST_DPM_LEVEL7, a_t);
427 }
428}
429
430static void sumo_program_tp(struct radeon_device *rdev)
431{
432 int i;
433 enum r600_td td = R600_TD_DFLT0;
434
435 for (i = 0; i < SUMO_PM_NUMBER_OF_TC15; i++) {
436 WREG32_P(CG_FFCT_0 + (i * 4), UTC_0(sumo_utc[i]), ~UTC_0_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x694 + (i * 4)), 0)
; tmp_ &= (~(0x3ff << 0)); tmp_ |= ((((sumo_utc[i])
<< 0)) & ~(~(0x3ff << 0))); r100_mm_wreg(rdev
, (0x694 + (i * 4)), (tmp_), 0); } while (0)
;
437 WREG32_P(CG_FFCT_0 + (i * 4), DTC_0(sumo_dtc[i]), ~DTC_0_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x694 + (i * 4)), 0)
; tmp_ &= (~(0x3ff << 10)); tmp_ |= ((((sumo_dtc[i]
) << 10)) & ~(~(0x3ff << 10))); r100_mm_wreg(
rdev, (0x694 + (i * 4)), (tmp_), 0); } while (0)
;
438 }
439
440 if (td == R600_TD_AUTO)
441 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 5)); tmp_ |= ((0) & ~(~(1 << 5))); r100_mm_wreg
(rdev, (0x644), (tmp_), 0); } while (0)
;
442 else
443 WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 5)); tmp_ |= (((1 << 5)) & ~(~(1 <<
5))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0)
;
444
445 if (td == R600_TD_UP)
446 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 6)); tmp_ |= ((0) & ~(~(1 << 6))); r100_mm_wreg
(rdev, (0x644), (tmp_), 0); } while (0)
;
447
448 if (td == R600_TD_DOWN)
449 WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 6)); tmp_ |= (((1 << 6)) & ~(~(1 <<
6))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0)
;
450}
451
452void sumo_program_vc(struct radeon_device *rdev, u32 vrc)
453{
454 WREG32(CG_FTV, vrc)r100_mm_wreg(rdev, (0x690), (vrc), 0);
455}
456
457void sumo_clear_vc(struct radeon_device *rdev)
458{
459 WREG32(CG_FTV, 0)r100_mm_wreg(rdev, (0x690), (0), 0);
460}
461
462void sumo_program_sstp(struct radeon_device *rdev)
463{
464 u32 p, u;
465 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
466
467 r600_calculate_u_and_p(SUMO_SST_DFLT8,
468 xclk, 16, &p, &u);
469
470 WREG32(CG_SSP, SSTU(u) | SST(p))r100_mm_wreg(rdev, (0x6e8), (((u) << 16) | ((p) <<
0)), 0)
;
471}
472
473static void sumo_set_divider_value(struct radeon_device *rdev,
474 u32 index, u32 divider)
475{
476 u32 reg_index = index / 4;
477 u32 field_index = index % 4;
478
479 if (field_index == 0)
480 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 0)); tmp_ |= ((((divider
) << 0)) & ~(~(0x7f << 0))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
481 SCLK_FSTATE_0_DIV(divider), ~SCLK_FSTATE_0_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 0)); tmp_ |= ((((divider
) << 0)) & ~(~(0x7f << 0))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
482 else if (field_index == 1)
483 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 8)); tmp_ |= ((((divider
) << 8)) & ~(~(0x7f << 8))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
484 SCLK_FSTATE_1_DIV(divider), ~SCLK_FSTATE_1_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 8)); tmp_ |= ((((divider
) << 8)) & ~(~(0x7f << 8))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
485 else if (field_index == 2)
486 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 16)); tmp_ |= ((((divider
) << 16)) & ~(~(0x7f << 16))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
487 SCLK_FSTATE_2_DIV(divider), ~SCLK_FSTATE_2_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 16)); tmp_ |= ((((divider
) << 16)) & ~(~(0x7f << 16))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
488 else if (field_index == 3)
489 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 24)); tmp_ |= ((((divider
) << 24)) & ~(~(0x7f << 24))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
490 SCLK_FSTATE_3_DIV(divider), ~SCLK_FSTATE_3_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(0x7f << 24)); tmp_ |= ((((divider
) << 24)) & ~(~(0x7f << 24))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
491}
492
493static void sumo_set_ds_dividers(struct radeon_device *rdev,
494 u32 index, u32 divider)
495{
496 struct sumo_power_info *pi = sumo_get_pi(rdev);
497
498 if (pi->enable_sclk_ds) {
499 u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_6)r100_mm_rreg(rdev, (0x724), 0);
500
501 dpm_ctrl &= ~(0x7 << (index * 3));
502 dpm_ctrl |= (divider << (index * 3));
503 WREG32(CG_SCLK_DPM_CTRL_6, dpm_ctrl)r100_mm_wreg(rdev, (0x724), (dpm_ctrl), 0);
504 }
505}
506
507static void sumo_set_ss_dividers(struct radeon_device *rdev,
508 u32 index, u32 divider)
509{
510 struct sumo_power_info *pi = sumo_get_pi(rdev);
511
512 if (pi->enable_sclk_ds) {
513 u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_11)r100_mm_rreg(rdev, (0x830), 0);
514
515 dpm_ctrl &= ~(0x7 << (index * 3));
516 dpm_ctrl |= (divider << (index * 3));
517 WREG32(CG_SCLK_DPM_CTRL_11, dpm_ctrl)r100_mm_wreg(rdev, (0x830), (dpm_ctrl), 0);
518 }
519}
520
521static void sumo_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
522{
523 u32 voltage_cntl = RREG32(CG_DPM_VOLTAGE_CNTL)r100_mm_rreg(rdev, (0x788), 0);
524
525 voltage_cntl &= ~(DPM_STATE0_LEVEL_MASK(0x3 << 0) << (index * 2));
526 voltage_cntl |= (vid << (DPM_STATE0_LEVEL_SHIFT0 + index * 2));
527 WREG32(CG_DPM_VOLTAGE_CNTL, voltage_cntl)r100_mm_wreg(rdev, (0x788), (voltage_cntl), 0);
528}
529
530static void sumo_set_allos_gnb_slow(struct radeon_device *rdev, u32 index, u32 gnb_slow)
531{
532 struct sumo_power_info *pi = sumo_get_pi(rdev);
533 u32 temp = gnb_slow;
534 u32 cg_sclk_dpm_ctrl_3;
535
536 if (pi->driver_nbps_policy_disable)
537 temp = 1;
538
539 cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3)r100_mm_rreg(rdev, (0x6e0), 0);
540 cg_sclk_dpm_ctrl_3 &= ~(GNB_SLOW_FSTATE_0_MASK(1 << 23) << index);
541 cg_sclk_dpm_ctrl_3 |= (temp << (GNB_SLOW_FSTATE_0_SHIFT23 + index));
542
543 WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3)r100_mm_wreg(rdev, (0x6e0), (cg_sclk_dpm_ctrl_3), 0);
544}
545
546static void sumo_program_power_level(struct radeon_device *rdev,
547 struct sumo_pl *pl, u32 index)
548{
549 struct sumo_power_info *pi = sumo_get_pi(rdev);
550 int ret;
551 struct atom_clock_dividers dividers;
552 u32 ds_en = RREG32(DEEP_SLEEP_CNTL)r100_mm_rreg(rdev, (0x818), 0) & ENABLE_DS(1 << 31);
553
554 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM2,
555 pl->sclk, false0, &dividers);
556 if (ret)
557 return;
558
559 sumo_set_divider_value(rdev, index, dividers.post_div);
560
561 sumo_set_vid(rdev, index, pl->vddc_index);
562
563 if (pl->ss_divider_index == 0 || pl->ds_divider_index == 0) {
564 if (ds_en)
565 WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x818), 0); tmp_ &=
(~(1 << 31)); tmp_ |= ((0) & ~(~(1 << 31)));
r100_mm_wreg(rdev, (0x818), (tmp_), 0); } while (0)
;
566 } else {
567 sumo_set_ss_dividers(rdev, index, pl->ss_divider_index);
568 sumo_set_ds_dividers(rdev, index, pl->ds_divider_index);
569
570 if (!ds_en)
571 WREG32_P(DEEP_SLEEP_CNTL, ENABLE_DS, ~ENABLE_DS)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x818), 0); tmp_ &=
(~(1 << 31)); tmp_ |= (((1 << 31)) & ~(~(1 <<
31))); r100_mm_wreg(rdev, (0x818), (tmp_), 0); } while (0)
;
572 }
573
574 sumo_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
575
576 if (pi->enable_boost)
577 sumo_set_tdp_limit(rdev, index, pl->sclk_dpm_tdp_limit);
578}
579
580static void sumo_power_level_enable(struct radeon_device *rdev, u32 index, bool_Bool enable)
581{
582 u32 reg_index = index / 4;
583 u32 field_index = index % 4;
584
585 if (field_index == 0)
586 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 7)); tmp_ |= ((enable ? (
1 << 7) : 0) & ~(~(1 << 7))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
587 enable ? SCLK_FSTATE_0_VLD : 0, ~SCLK_FSTATE_0_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 7)); tmp_ |= ((enable ? (
1 << 7) : 0) & ~(~(1 << 7))); r100_mm_wreg(rdev
, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
588 else if (field_index == 1)
589 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 15)); tmp_ |= ((enable ? (
1 << 15) : 0) & ~(~(1 << 15))); r100_mm_wreg(
rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
590 enable ? SCLK_FSTATE_1_VLD : 0, ~SCLK_FSTATE_1_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 15)); tmp_ |= ((enable ? (
1 << 15) : 0) & ~(~(1 << 15))); r100_mm_wreg(
rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
591 else if (field_index == 2)
592 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 23)); tmp_ |= ((enable ? (
1 << 23) : 0) & ~(~(1 << 23))); r100_mm_wreg(
rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
593 enable ? SCLK_FSTATE_2_VLD : 0, ~SCLK_FSTATE_2_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 23)); tmp_ |= ((enable ? (
1 << 23) : 0) & ~(~(1 << 23))); r100_mm_wreg(
rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
594 else if (field_index == 3)
595 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((enable ? (
1 << 31) : 0) & ~(~(1 << 31))); r100_mm_wreg(
rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
596 enable ? SCLK_FSTATE_3_VLD : 0, ~SCLK_FSTATE_3_VLD)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x684 + (reg_index *
4)), 0); tmp_ &= (~(1 << 31)); tmp_ |= ((enable ? (
1 << 31) : 0) & ~(~(1 << 31))); r100_mm_wreg(
rdev, (0x684 + (reg_index * 4)), (tmp_), 0); } while (0)
;
597}
598
599static bool_Bool sumo_dpm_enabled(struct radeon_device *rdev)
600{
601 if (RREG32(CG_SCLK_DPM_CTRL_3)r100_mm_rreg(rdev, (0x6e0), 0) & DPM_SCLK_ENABLE(1 << 18))
602 return true1;
603 else
604 return false0;
605}
606
607static void sumo_start_dpm(struct radeon_device *rdev)
608{
609 WREG32_P(CG_SCLK_DPM_CTRL_3, DPM_SCLK_ENABLE, ~DPM_SCLK_ENABLE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 18)); tmp_ |= (((1 << 18)) & ~(~(1 <<
18))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
;
610}
611
612static void sumo_stop_dpm(struct radeon_device *rdev)
613{
614 WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~DPM_SCLK_ENABLE)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 18)); tmp_ |= ((0) & ~(~(1 << 18)));
r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
;
615}
616
617static void sumo_set_forced_mode(struct radeon_device *rdev, bool_Bool enable)
618{
619 if (enable)
620 WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE_EN, ~FORCE_SCLK_STATE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 3)); tmp_ |= (((1 << 3)) & ~(~(1 <<
3))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
;
621 else
622 WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_SCLK_STATE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 3)); tmp_ |= ((0) & ~(~(1 << 3))); r100_mm_wreg
(rdev, (0x6e0), (tmp_), 0); } while (0)
;
623}
624
625static void sumo_set_forced_mode_enabled(struct radeon_device *rdev)
626{
627 int i;
628
629 sumo_set_forced_mode(rdev, true1);
630 for (i = 0; i < rdev->usec_timeout; i++) {
631 if (RREG32(CG_SCLK_STATUS)r100_mm_rreg(rdev, (0x604), 0) & SCLK_OVERCLK_DETECT(1 << 2))
632 break;
633 udelay(1);
634 }
635}
636
637static void sumo_wait_for_level_0(struct radeon_device *rdev)
638{
639 int i;
640
641 for (i = 0; i < rdev->usec_timeout; i++) {
642 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_SCLK_INDEX_MASK(0x7 << 9)) == 0)
643 break;
644 udelay(1);
645 }
646 for (i = 0; i < rdev->usec_timeout; i++) {
647 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_INDEX_MASK(0x7 << 15)) == 0)
648 break;
649 udelay(1);
650 }
651}
652
653static void sumo_set_forced_mode_disabled(struct radeon_device *rdev)
654{
655 sumo_set_forced_mode(rdev, false0);
656}
657
658static void sumo_enable_power_level_0(struct radeon_device *rdev)
659{
660 sumo_power_level_enable(rdev, 0, true1);
661}
662
663static void sumo_patch_boost_state(struct radeon_device *rdev,
664 struct radeon_ps *rps)
665{
666 struct sumo_power_info *pi = sumo_get_pi(rdev);
667 struct sumo_ps *new_ps = sumo_get_ps(rps);
668
669 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1)) {
670 pi->boost_pl = new_ps->levels[new_ps->num_levels - 1];
671 pi->boost_pl.sclk = pi->sys_info.boost_sclk;
672 pi->boost_pl.vddc_index = pi->sys_info.boost_vid_2bit;
673 pi->boost_pl.sclk_dpm_tdp_limit = pi->sys_info.sclk_dpm_tdp_limit_boost;
674 }
675}
676
677static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev,
678 struct radeon_ps *new_rps,
679 struct radeon_ps *old_rps)
680{
681 struct sumo_ps *new_ps = sumo_get_ps(new_rps);
682 struct sumo_ps *old_ps = sumo_get_ps(old_rps);
683 u32 nbps1_old = 0;
684 u32 nbps1_new = 0;
685
686 if (old_ps != NULL((void *)0))
687 nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0)) ? 1 : 0;
688
689 nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0)) ? 1 : 0;
690
691 if (nbps1_old == 1 && nbps1_new == 0)
692 sumo_smu_notify_alt_vddnb_change(rdev, 0, 0);
693}
694
695static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev,
696 struct radeon_ps *new_rps,
697 struct radeon_ps *old_rps)
698{
699 struct sumo_ps *new_ps = sumo_get_ps(new_rps);
700 struct sumo_ps *old_ps = sumo_get_ps(old_rps);
701 u32 nbps1_old = 0;
702 u32 nbps1_new = 0;
703
704 if (old_ps != NULL((void *)0))
705 nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0))? 1 : 0;
706
707 nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0))? 1 : 0;
708
709 if (nbps1_old == 0 && nbps1_new == 1)
710 sumo_smu_notify_alt_vddnb_change(rdev, 1, 1);
711}
712
713static void sumo_enable_boost(struct radeon_device *rdev,
714 struct radeon_ps *rps,
715 bool_Bool enable)
716{
717 struct sumo_ps *new_ps = sumo_get_ps(rps);
718
719 if (enable) {
720 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1))
721 sumo_boost_state_enable(rdev, true1);
722 } else
723 sumo_boost_state_enable(rdev, false0);
724}
725
726static void sumo_set_forced_level(struct radeon_device *rdev, u32 index)
727{
728 WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE(index), ~FORCE_SCLK_STATE_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(0x7 << 0)); tmp_ |= ((((index) << 0)) & ~
(~(0x7 << 0))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0);
} while (0)
;
729}
730
731static void sumo_set_forced_level_0(struct radeon_device *rdev)
732{
733 sumo_set_forced_level(rdev, 0);
734}
735
736static void sumo_program_wl(struct radeon_device *rdev,
737 struct radeon_ps *rps)
738{
739 struct sumo_ps *new_ps = sumo_get_ps(rps);
740 u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4)r100_mm_rreg(rdev, (0x71c), 0);
741
742 dpm_ctrl4 &= 0xFFFFFF00;
743 dpm_ctrl4 |= (1 << (new_ps->num_levels - 1));
7
The result of the left shift is undefined due to shifting by '4294967295', which is greater or equal to the width of type 'int'
744
745 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1))
746 dpm_ctrl4 |= (1 << BOOST_DPM_LEVEL7);
747
748 WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4)r100_mm_wreg(rdev, (0x71c), (dpm_ctrl4), 0);
749}
750
751static void sumo_program_power_levels_0_to_n(struct radeon_device *rdev,
752 struct radeon_ps *new_rps,
753 struct radeon_ps *old_rps)
754{
755 struct sumo_power_info *pi = sumo_get_pi(rdev);
756 struct sumo_ps *new_ps = sumo_get_ps(new_rps);
757 struct sumo_ps *old_ps = sumo_get_ps(old_rps);
758 u32 i;
759 u32 n_current_state_levels = (old_ps == NULL((void *)0)) ? 1 : old_ps->num_levels;
760
761 for (i = 0; i < new_ps->num_levels; i++) {
762 sumo_program_power_level(rdev, &new_ps->levels[i], i);
763 sumo_power_level_enable(rdev, i, true1);
764 }
765
766 for (i = new_ps->num_levels; i < n_current_state_levels; i++)
767 sumo_power_level_enable(rdev, i, false0);
768
769 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1))
770 sumo_program_power_level(rdev, &pi->boost_pl, BOOST_DPM_LEVEL7);
771}
772
773static void sumo_enable_acpi_pm(struct radeon_device *rdev)
774{
775 WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x63c), 0); tmp_ &=
(~(1 << 1)); tmp_ |= (((1 << 1)) & ~(~(1 <<
1))); r100_mm_wreg(rdev, (0x63c), (tmp_), 0); } while (0)
;
776}
777
778static void sumo_program_power_level_enter_state(struct radeon_device *rdev)
779{
780 WREG32_P(CG_SCLK_DPM_CTRL_5, SCLK_FSTATE_BOOTUP(0), ~SCLK_FSTATE_BOOTUP_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x720), 0); tmp_ &=
(~(0x7 << 0)); tmp_ |= ((((0) << 0)) & ~(~(0x7
<< 0))); r100_mm_wreg(rdev, (0x720), (tmp_), 0); } while
(0)
;
781}
782
783static void sumo_program_acpi_power_level(struct radeon_device *rdev)
784{
785 struct sumo_power_info *pi = sumo_get_pi(rdev);
786 struct atom_clock_dividers dividers;
787 int ret;
788
789 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM2,
790 pi->acpi_pl.sclk,
791 false0, &dividers);
792 if (ret)
793 return;
794
795 WREG32_P(CG_ACPI_CNTL, SCLK_ACPI_DIV(dividers.post_div), ~SCLK_ACPI_DIV_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x70c), 0); tmp_ &=
(~(0x7f << 0)); tmp_ |= ((((dividers.post_div) <<
0)) & ~(~(0x7f << 0))); r100_mm_wreg(rdev, (0x70c)
, (tmp_), 0); } while (0)
;
796 WREG32_P(CG_ACPI_VOLTAGE_CNTL, 0, ~ACPI_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x780), 0); tmp_ &=
(~(1 << 8)); tmp_ |= ((0) & ~(~(1 << 8))); r100_mm_wreg
(rdev, (0x780), (tmp_), 0); } while (0)
;
797}
798
799static void sumo_program_bootup_state(struct radeon_device *rdev)
800{
801 struct sumo_power_info *pi = sumo_get_pi(rdev);
802 u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4)r100_mm_rreg(rdev, (0x71c), 0);
803 u32 i;
804
805 sumo_program_power_level(rdev, &pi->boot_pl, 0);
806
807 dpm_ctrl4 &= 0xFFFFFF00;
808 WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4)r100_mm_wreg(rdev, (0x71c), (dpm_ctrl4), 0);
809
810 for (i = 1; i < 8; i++)
811 sumo_power_level_enable(rdev, i, false0);
812}
813
814static void sumo_setup_uvd_clocks(struct radeon_device *rdev,
815 struct radeon_ps *new_rps,
816 struct radeon_ps *old_rps)
817{
818 struct sumo_power_info *pi = sumo_get_pi(rdev);
819
820 if (pi->enable_gfx_power_gating) {
821 sumo_gfx_powergating_enable(rdev, false0);
822 }
823
824 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk)(rdev)->asic->pm.set_uvd_clocks((rdev), (new_rps->vclk
), (new_rps->dclk))
;
825
826 if (pi->enable_gfx_power_gating) {
827 if (!pi->disable_gfx_power_gating_in_uvd ||
828 !r600_is_uvd_state(new_rps->class, new_rps->class2))
829 sumo_gfx_powergating_enable(rdev, true1);
830 }
831}
832
833static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
834 struct radeon_ps *new_rps,
835 struct radeon_ps *old_rps)
836{
837 struct sumo_ps *new_ps = sumo_get_ps(new_rps);
838 struct sumo_ps *current_ps = sumo_get_ps(old_rps);
839
840 if ((new_rps->vclk == old_rps->vclk) &&
841 (new_rps->dclk == old_rps->dclk))
842 return;
843
844 if (new_ps->levels[new_ps->num_levels - 1].sclk >=
845 current_ps->levels[current_ps->num_levels - 1].sclk)
846 return;
847
848 sumo_setup_uvd_clocks(rdev, new_rps, old_rps);
849}
850
851static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
852 struct radeon_ps *new_rps,
853 struct radeon_ps *old_rps)
854{
855 struct sumo_ps *new_ps = sumo_get_ps(new_rps);
856 struct sumo_ps *current_ps = sumo_get_ps(old_rps);
857
858 if ((new_rps->vclk == old_rps->vclk) &&
859 (new_rps->dclk == old_rps->dclk))
860 return;
861
862 if (new_ps->levels[new_ps->num_levels - 1].sclk <
863 current_ps->levels[current_ps->num_levels - 1].sclk)
864 return;
865
866 sumo_setup_uvd_clocks(rdev, new_rps, old_rps);
867}
868
869void sumo_take_smu_control(struct radeon_device *rdev, bool_Bool enable)
870{
871/* This bit selects who handles display phy powergating.
872 * Clear the bit to let atom handle it.
873 * Set it to let the driver handle it.
874 * For now we just let atom handle it.
875 */
876#if 0
877 u32 v = RREG32(DOUT_SCRATCH3)r100_mm_rreg(rdev, (0x611c), 0);
878
879 if (enable)
880 v |= 0x4;
881 else
882 v &= 0xFFFFFFFB;
883
884 WREG32(DOUT_SCRATCH3, v)r100_mm_wreg(rdev, (0x611c), (v), 0);
885#endif
886}
887
888static void sumo_enable_sclk_ds(struct radeon_device *rdev, bool_Bool enable)
889{
890 if (enable) {
891 u32 deep_sleep_cntl = RREG32(DEEP_SLEEP_CNTL)r100_mm_rreg(rdev, (0x818), 0);
892 u32 deep_sleep_cntl2 = RREG32(DEEP_SLEEP_CNTL2)r100_mm_rreg(rdev, (0x81c), 0);
893 u32 t = 1;
894
895 deep_sleep_cntl &= ~R_DIS(1 << 3);
896 deep_sleep_cntl &= ~HS_MASK(0xfff << 4);
897 deep_sleep_cntl |= HS(t > 4095 ? 4095 : t)((t > 4095 ? 4095 : t) << 4);
898
899 deep_sleep_cntl2 |= LB_UFP_EN(1 << 0);
900 deep_sleep_cntl2 &= INOUT_C_MASK(0xff << 4);
901 deep_sleep_cntl2 |= INOUT_C(0xf)((0xf) << 4);
902
903 WREG32(DEEP_SLEEP_CNTL2, deep_sleep_cntl2)r100_mm_wreg(rdev, (0x81c), (deep_sleep_cntl2), 0);
904 WREG32(DEEP_SLEEP_CNTL, deep_sleep_cntl)r100_mm_wreg(rdev, (0x818), (deep_sleep_cntl), 0);
905 } else
906 WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x818), 0); tmp_ &=
(~(1 << 31)); tmp_ |= ((0) & ~(~(1 << 31)));
r100_mm_wreg(rdev, (0x818), (tmp_), 0); } while (0)
;
907}
908
909static void sumo_program_bootup_at(struct radeon_device *rdev)
910{
911 WREG32_P(CG_AT_0, CG_R(0xffff), ~CG_R_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x728), 0); tmp_ &=
(~(0xffff << 0)); tmp_ |= ((((0xffff) << 0)) &
~(~(0xffff << 0))); r100_mm_wreg(rdev, (0x728), (tmp_)
, 0); } while (0)
;
912 WREG32_P(CG_AT_0, CG_L(0), ~CG_L_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x728), 0); tmp_ &=
(~(0xffff << 16)); tmp_ |= ((((0) << 16)) & ~
(~(0xffff << 16))); r100_mm_wreg(rdev, (0x728), (tmp_),
0); } while (0)
;
913}
914
915static void sumo_reset_am(struct radeon_device *rdev)
916{
917 WREG32_P(SCLK_PWRMGT_CNTL, FIR_RESET, ~FIR_RESET)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 4)); tmp_ |= (((1 << 4)) & ~(~(1 <<
4))); r100_mm_wreg(rdev, (0x644), (tmp_), 0); } while (0)
;
918}
919
920static void sumo_start_am(struct radeon_device *rdev)
921{
922 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_RESET)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x644), 0); tmp_ &=
(~(1 << 4)); tmp_ |= ((0) & ~(~(1 << 4))); r100_mm_wreg
(rdev, (0x644), (tmp_), 0); } while (0)
;
923}
924
925static void sumo_program_ttp(struct radeon_device *rdev)
926{
927 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
928 u32 p, u;
929 u32 cg_sclk_dpm_ctrl_5 = RREG32(CG_SCLK_DPM_CTRL_5)r100_mm_rreg(rdev, (0x720), 0);
930
931 r600_calculate_u_and_p(1000,
932 xclk, 16, &p, &u);
933
934 cg_sclk_dpm_ctrl_5 &= ~(TT_TP_MASK(0xffff << 3) | TT_TU_MASK(0xff << 19));
935 cg_sclk_dpm_ctrl_5 |= TT_TP(p)((p) << 3) | TT_TU(u)((u) << 19);
936
937 WREG32(CG_SCLK_DPM_CTRL_5, cg_sclk_dpm_ctrl_5)r100_mm_wreg(rdev, (0x720), (cg_sclk_dpm_ctrl_5), 0);
938}
939
940static void sumo_program_ttt(struct radeon_device *rdev)
941{
942 u32 cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3)r100_mm_rreg(rdev, (0x6e0), 0);
943 struct sumo_power_info *pi = sumo_get_pi(rdev);
944
945 cg_sclk_dpm_ctrl_3 &= ~(GNB_TT_MASK(0xff << 8) | GNB_THERMTHRO_MASK(1 << 16));
946 cg_sclk_dpm_ctrl_3 |= GNB_TT(pi->thermal_auto_throttling + 49)((pi->thermal_auto_throttling + 49) << 8);
947
948 WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3)r100_mm_wreg(rdev, (0x6e0), (cg_sclk_dpm_ctrl_3), 0);
949}
950
951
952static void sumo_enable_voltage_scaling(struct radeon_device *rdev, bool_Bool enable)
953{
954 if (enable) {
955 WREG32_P(CG_DPM_VOLTAGE_CNTL, DPM_VOLTAGE_EN, ~DPM_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x788), 0); tmp_ &=
(~(1 << 16)); tmp_ |= (((1 << 16)) & ~(~(1 <<
16))); r100_mm_wreg(rdev, (0x788), (tmp_), 0); } while (0)
;
956 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~CG_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &=
(~(1 << 3)); tmp_ |= ((0) & ~(~(1 << 3))); r100_mm_wreg
(rdev, (0x770), (tmp_), 0); } while (0)
;
957 } else {
958 WREG32_P(CG_CG_VOLTAGE_CNTL, CG_VOLTAGE_EN, ~CG_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x770), 0); tmp_ &=
(~(1 << 3)); tmp_ |= (((1 << 3)) & ~(~(1 <<
3))); r100_mm_wreg(rdev, (0x770), (tmp_), 0); } while (0)
;
959 WREG32_P(CG_DPM_VOLTAGE_CNTL, 0, ~DPM_VOLTAGE_EN)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x788), 0); tmp_ &=
(~(1 << 16)); tmp_ |= ((0) & ~(~(1 << 16)));
r100_mm_wreg(rdev, (0x788), (tmp_), 0); } while (0)
;
960 }
961}
962
963static void sumo_override_cnb_thermal_events(struct radeon_device *rdev)
964{
965 WREG32_P(CG_SCLK_DPM_CTRL_3, CNB_THERMTHRO_MASK_SCLK,do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 17)); tmp_ |= (((1 << 17)) & ~(~(1 <<
17))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
966 ~CNB_THERMTHRO_MASK_SCLK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 17)); tmp_ |= (((1 << 17)) & ~(~(1 <<
17))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
;
967}
968
969static void sumo_program_dc_hto(struct radeon_device *rdev)
970{
971 u32 cg_sclk_dpm_ctrl_4 = RREG32(CG_SCLK_DPM_CTRL_4)r100_mm_rreg(rdev, (0x71c), 0);
972 u32 p, u;
973 u32 xclk = radeon_get_xclk(rdev)(rdev)->asic->get_xclk((rdev));
974
975 r600_calculate_u_and_p(100000,
976 xclk, 14, &p, &u);
977
978 cg_sclk_dpm_ctrl_4 &= ~(DC_HDC_MASK(0x3fff << 14) | DC_HU_MASK(0xf << 28));
979 cg_sclk_dpm_ctrl_4 |= DC_HDC(p)((p) << 14) | DC_HU(u)((u) << 28);
980
981 WREG32(CG_SCLK_DPM_CTRL_4, cg_sclk_dpm_ctrl_4)r100_mm_wreg(rdev, (0x71c), (cg_sclk_dpm_ctrl_4), 0);
982}
983
984static void sumo_force_nbp_state(struct radeon_device *rdev,
985 struct radeon_ps *rps)
986{
987 struct sumo_power_info *pi = sumo_get_pi(rdev);
988 struct sumo_ps *new_ps = sumo_get_ps(rps);
989
990 if (!pi->driver_nbps_policy_disable) {
991 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0))
992 WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_NB_PSTATE_1, ~FORCE_NB_PSTATE_1)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 31)); tmp_ |= (((1 << 31)) & ~(~(1 <<
31))); r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
;
993 else
994 WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_NB_PSTATE_1)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x6e0), 0); tmp_ &=
(~(1 << 31)); tmp_ |= ((0) & ~(~(1 << 31)));
r100_mm_wreg(rdev, (0x6e0), (tmp_), 0); } while (0)
;
995 }
996}
997
998u32 sumo_get_sleep_divider_from_id(u32 id)
999{
1000 return 1 << id;
1001}
1002
1003u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1004 u32 sclk,
1005 u32 min_sclk_in_sr)
1006{
1007 struct sumo_power_info *pi = sumo_get_pi(rdev);
1008 u32 i;
1009 u32 temp;
1010 u32 min = (min_sclk_in_sr > SUMO_MINIMUM_ENGINE_CLOCK800) ?
1011 min_sclk_in_sr : SUMO_MINIMUM_ENGINE_CLOCK800;
1012
1013 if (sclk < min)
1014 return 0;
1015
1016 if (!pi->enable_sclk_ds)
1017 return 0;
1018
1019 for (i = SUMO_MAX_DEEPSLEEP_DIVIDER_ID5; ; i--) {
1020 temp = sclk / sumo_get_sleep_divider_from_id(i);
1021
1022 if (temp >= min || i == 0)
1023 break;
1024 }
1025 return i;
1026}
1027
1028static u32 sumo_get_valid_engine_clock(struct radeon_device *rdev,
1029 u32 lower_limit)
1030{
1031 struct sumo_power_info *pi = sumo_get_pi(rdev);
1032 u32 i;
1033
1034 for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1035 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1036 return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1037 }
1038
1039 return pi->sys_info.sclk_voltage_mapping_table.entries[pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1].sclk_frequency;
1040}
1041
1042static void sumo_patch_thermal_state(struct radeon_device *rdev,
1043 struct sumo_ps *ps,
1044 struct sumo_ps *current_ps)
1045{
1046 struct sumo_power_info *pi = sumo_get_pi(rdev);
1047 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1048 u32 current_vddc;
1049 u32 current_sclk;
1050 u32 current_index = 0;
1051
1052 if (current_ps) {
1053 current_vddc = current_ps->levels[current_index].vddc_index;
1054 current_sclk = current_ps->levels[current_index].sclk;
1055 } else {
1056 current_vddc = pi->boot_pl.vddc_index;
1057 current_sclk = pi->boot_pl.sclk;
1058 }
1059
1060 ps->levels[0].vddc_index = current_vddc;
1061
1062 if (ps->levels[0].sclk > current_sclk)
1063 ps->levels[0].sclk = current_sclk;
1064
1065 ps->levels[0].ss_divider_index =
1066 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1067
1068 ps->levels[0].ds_divider_index =
1069 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, SUMO_MINIMUM_ENGINE_CLOCK800);
1070
1071 if (ps->levels[0].ds_divider_index > ps->levels[0].ss_divider_index + 1)
1072 ps->levels[0].ds_divider_index = ps->levels[0].ss_divider_index + 1;
1073
1074 if (ps->levels[0].ss_divider_index == ps->levels[0].ds_divider_index) {
1075 if (ps->levels[0].ss_divider_index > 1)
1076 ps->levels[0].ss_divider_index = ps->levels[0].ss_divider_index - 1;
1077 }
1078
1079 if (ps->levels[0].ss_divider_index == 0)
1080 ps->levels[0].ds_divider_index = 0;
1081
1082 if (ps->levels[0].ds_divider_index == 0)
1083 ps->levels[0].ss_divider_index = 0;
1084}
1085
1086static void sumo_apply_state_adjust_rules(struct radeon_device *rdev,
1087 struct radeon_ps *new_rps,
1088 struct radeon_ps *old_rps)
1089{
1090 struct sumo_ps *ps = sumo_get_ps(new_rps);
1091 struct sumo_ps *current_ps = sumo_get_ps(old_rps);
1092 struct sumo_power_info *pi = sumo_get_pi(rdev);
1093 u32 min_voltage = 0; /* ??? */
1094 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
1095 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1096 u32 i;
1097
1098 if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL0x0010)
1099 return sumo_patch_thermal_state(rdev, ps, current_ps);
1100
1101 if (pi->enable_boost) {
1102 if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE5)
1103 ps->flags |= SUMO_POWERSTATE_FLAGS_BOOST_STATE(1 << 1);
1104 }
1105
1106 if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY1) ||
1107 (new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE0x8000) ||
1108 (new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE0x4000))
1109 ps->flags |= SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0);
1110
1111 for (i = 0; i < ps->num_levels; i++) {
1112 if (ps->levels[i].vddc_index < min_voltage)
1113 ps->levels[i].vddc_index = min_voltage;
1114
1115 if (ps->levels[i].sclk < min_sclk)
1116 ps->levels[i].sclk =
1117 sumo_get_valid_engine_clock(rdev, min_sclk);
1118
1119 ps->levels[i].ss_divider_index =
1120 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1121
1122 ps->levels[i].ds_divider_index =
1123 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, SUMO_MINIMUM_ENGINE_CLOCK800);
1124
1125 if (ps->levels[i].ds_divider_index > ps->levels[i].ss_divider_index + 1)
1126 ps->levels[i].ds_divider_index = ps->levels[i].ss_divider_index + 1;
1127
1128 if (ps->levels[i].ss_divider_index == ps->levels[i].ds_divider_index) {
1129 if (ps->levels[i].ss_divider_index > 1)
1130 ps->levels[i].ss_divider_index = ps->levels[i].ss_divider_index - 1;
1131 }
1132
1133 if (ps->levels[i].ss_divider_index == 0)
1134 ps->levels[i].ds_divider_index = 0;
1135
1136 if (ps->levels[i].ds_divider_index == 0)
1137 ps->levels[i].ss_divider_index = 0;
1138
1139 if (ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE(1 << 0))
1140 ps->levels[i].allow_gnb_slow = 1;
1141 else if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE0x0400) ||
1142 (new_rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC0x0004))
1143 ps->levels[i].allow_gnb_slow = 0;
1144 else if (i == ps->num_levels - 1)
1145 ps->levels[i].allow_gnb_slow = 0;
1146 else
1147 ps->levels[i].allow_gnb_slow = 1;
1148 }
1149}
1150
1151static void sumo_cleanup_asic(struct radeon_device *rdev)
1152{
1153 sumo_take_smu_control(rdev, false0);
1154}
1155
1156static int sumo_set_thermal_temperature_range(struct radeon_device *rdev,
1157 int min_temp, int max_temp)
1158{
1159 int low_temp = 0 * 1000;
1160 int high_temp = 255 * 1000;
1161
1162 if (low_temp < min_temp)
1163 low_temp = min_temp;
1164 if (high_temp > max_temp)
1165 high_temp = max_temp;
1166 if (high_temp < low_temp) {
1167 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp)__drm_err("invalid thermal range: %d - %d\n", low_temp, high_temp
)
;
1168 return -EINVAL22;
1169 }
1170
1171 WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x734), 0); tmp_ &=
(~0x0000FF00); tmp_ |= ((((49 + (high_temp / 1000)) <<
8)) & ~(~0x0000FF00)); r100_mm_wreg(rdev, (0x734), (tmp_
), 0); } while (0)
;
1172 WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK)do { uint32_t tmp_ = r100_mm_rreg(rdev, (0x734), 0); tmp_ &=
(~0x00FF0000); tmp_ |= ((((49 + (low_temp / 1000)) << 16
)) & ~(~0x00FF0000)); r100_mm_wreg(rdev, (0x734), (tmp_),
0); } while (0)
;
1173
1174 rdev->pm.dpm.thermal.min_temp = low_temp;
1175 rdev->pm.dpm.thermal.max_temp = high_temp;
1176
1177 return 0;
1178}
1179
1180static void sumo_update_current_ps(struct radeon_device *rdev,
1181 struct radeon_ps *rps)
1182{
1183 struct sumo_ps *new_ps = sumo_get_ps(rps);
1184 struct sumo_power_info *pi = sumo_get_pi(rdev);
1185
1186 pi->current_rps = *rps;
1187 pi->current_ps = *new_ps;
1188 pi->current_rps.ps_priv = &pi->current_ps;
1189}
1190
1191static void sumo_update_requested_ps(struct radeon_device *rdev,
1192 struct radeon_ps *rps)
1193{
1194 struct sumo_ps *new_ps = sumo_get_ps(rps);
1195 struct sumo_power_info *pi = sumo_get_pi(rdev);
1196
1197 pi->requested_rps = *rps;
1198 pi->requested_ps = *new_ps;
1199 pi->requested_rps.ps_priv = &pi->requested_ps;
1200}
1201
1202int sumo_dpm_enable(struct radeon_device *rdev)
1203{
1204 struct sumo_power_info *pi = sumo_get_pi(rdev);
1205
1206 if (sumo_dpm_enabled(rdev))
1207 return -EINVAL22;
1208
1209 sumo_program_bootup_state(rdev);
1210 sumo_init_bsp(rdev);
1211 sumo_reset_am(rdev);
1212 sumo_program_tp(rdev);
1213 sumo_program_bootup_at(rdev);
1214 sumo_start_am(rdev);
1215 if (pi->enable_auto_thermal_throttling) {
1216 sumo_program_ttp(rdev);
1217 sumo_program_ttt(rdev);
1218 }
1219 sumo_program_dc_hto(rdev);
1220 sumo_program_power_level_enter_state(rdev);
1221 sumo_enable_voltage_scaling(rdev, true1);
1222 sumo_program_sstp(rdev);
1223 sumo_program_vc(rdev, SUMO_VRC_DFLT0x30033);
1224 sumo_override_cnb_thermal_events(rdev);
1225 sumo_start_dpm(rdev);
1226 sumo_wait_for_level_0(rdev);
1227 if (pi->enable_sclk_ds)
1228 sumo_enable_sclk_ds(rdev, true1);
1229 if (pi->enable_boost)
1230 sumo_enable_boost_timer(rdev);
1231
1232 sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1233
1234 return 0;
1235}
1236
1237int sumo_dpm_late_enable(struct radeon_device *rdev)
1238{
1239 int ret;
1240
1241 ret = sumo_enable_clock_power_gating(rdev);
1242 if (ret)
1243 return ret;
1244
1245 if (rdev->irq.installed &&
1246 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1247 ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN(90 * 1000), R600_TEMP_RANGE_MAX(120 * 1000));
1248 if (ret)
1249 return ret;
1250 rdev->irq.dpm_thermal = true1;
1251 radeon_irq_set(rdev)(rdev)->asic->irq.set((rdev));
1252 }
1253
1254 return 0;
1255}
1256
1257void sumo_dpm_disable(struct radeon_device *rdev)
1258{
1259 struct sumo_power_info *pi = sumo_get_pi(rdev);
1260
1261 if (!sumo_dpm_enabled(rdev))
1262 return;
1263 sumo_disable_clock_power_gating(rdev);
1264 if (pi->enable_sclk_ds)
1265 sumo_enable_sclk_ds(rdev, false0);
1266 sumo_clear_vc(rdev);
1267 sumo_wait_for_level_0(rdev);
1268 sumo_stop_dpm(rdev);
1269 sumo_enable_voltage_scaling(rdev, false0);
1270
1271 if (rdev->irq.installed &&
1272 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1273 rdev->irq.dpm_thermal = false0;
1274 radeon_irq_set(rdev)(rdev)->asic->irq.set((rdev));
1275 }
1276
1277 sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1278}
1279
1280int sumo_dpm_pre_set_power_state(struct radeon_device *rdev)
1281{
1282 struct sumo_power_info *pi = sumo_get_pi(rdev);
1283 struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
1284 struct radeon_ps *new_ps = &requested_ps;
1285
1286 sumo_update_requested_ps(rdev, new_ps);
1287
1288 if (pi->enable_dynamic_patch_ps)
1289 sumo_apply_state_adjust_rules(rdev,
1290 &pi->requested_rps,
1291 &pi->current_rps);
1292
1293 return 0;
1294}
1295
1296int sumo_dpm_set_power_state(struct radeon_device *rdev)
1297{
1298 struct sumo_power_info *pi = sumo_get_pi(rdev);
1299 struct radeon_ps *new_ps = &pi->requested_rps;
1300 struct radeon_ps *old_ps = &pi->current_rps;
1301
1302 if (pi->enable_dpm)
1
Assuming field 'enable_dpm' is true
2
Taking true branch
1303 sumo_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
1304 if (pi->enable_boost) {
3
Assuming field 'enable_boost' is false
4
Taking false branch
1305 sumo_enable_boost(rdev, new_ps, false0);
1306 sumo_patch_boost_state(rdev, new_ps);
1307 }
1308 if (pi->enable_dpm
4.1
Field 'enable_dpm' is true
) {
5
Taking true branch
1309 sumo_pre_notify_alt_vddnb_change(rdev, new_ps, old_ps);
1310 sumo_enable_power_level_0(rdev);
1311 sumo_set_forced_level_0(rdev);
1312 sumo_set_forced_mode_enabled(rdev);
1313 sumo_wait_for_level_0(rdev);
1314 sumo_program_power_levels_0_to_n(rdev, new_ps, old_ps);
1315 sumo_program_wl(rdev, new_ps);
6
Calling 'sumo_program_wl'
1316 sumo_program_bsp(rdev, new_ps);
1317 sumo_program_at(rdev, new_ps);
1318 sumo_force_nbp_state(rdev, new_ps);
1319 sumo_set_forced_mode_disabled(rdev);
1320 sumo_set_forced_mode_enabled(rdev);
1321 sumo_set_forced_mode_disabled(rdev);
1322 sumo_post_notify_alt_vddnb_change(rdev, new_ps, old_ps);
1323 }
1324 if (pi->enable_boost)
1325 sumo_enable_boost(rdev, new_ps, true1);
1326 if (pi->enable_dpm)
1327 sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1328
1329 return 0;
1330}
1331
1332void sumo_dpm_post_set_power_state(struct radeon_device *rdev)
1333{
1334 struct sumo_power_info *pi = sumo_get_pi(rdev);
1335 struct radeon_ps *new_ps = &pi->requested_rps;
1336
1337 sumo_update_current_ps(rdev, new_ps);
1338}
1339
1340#if 0
1341void sumo_dpm_reset_asic(struct radeon_device *rdev)
1342{
1343 sumo_program_bootup_state(rdev);
1344 sumo_enable_power_level_0(rdev);
1345 sumo_set_forced_level_0(rdev);
1346 sumo_set_forced_mode_enabled(rdev);
1347 sumo_wait_for_level_0(rdev);
1348 sumo_set_forced_mode_disabled(rdev);
1349 sumo_set_forced_mode_enabled(rdev);
1350 sumo_set_forced_mode_disabled(rdev);
1351}
1352#endif
1353
1354void sumo_dpm_setup_asic(struct radeon_device *rdev)
1355{
1356 struct sumo_power_info *pi = sumo_get_pi(rdev);
1357
1358 sumo_initialize_m3_arb(rdev);
1359 pi->fw_version = sumo_get_running_fw_version(rdev);
1360 DRM_INFO("Found smc ucode version: 0x%08x\n", pi->fw_version)printk("\0016" "[" "drm" "] " "Found smc ucode version: 0x%08x\n"
, pi->fw_version)
;
1361 sumo_program_acpi_power_level(rdev);
1362 sumo_enable_acpi_pm(rdev);
1363 sumo_take_smu_control(rdev, true1);
1364}
1365
1366void sumo_dpm_display_configuration_changed(struct radeon_device *rdev)
1367{
1368
1369}
1370
1371union power_info {
1372 struct _ATOM_POWERPLAY_INFO info;
1373 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1374 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1375 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1376 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1377 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1378};
1379
1380union pplib_clock_info {
1381 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1382 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1383 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1384 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1385};
1386
1387union pplib_power_state {
1388 struct _ATOM_PPLIB_STATE v1;
1389 struct _ATOM_PPLIB_STATE_V2 v2;
1390};
1391
1392static void sumo_patch_boot_state(struct radeon_device *rdev,
1393 struct sumo_ps *ps)
1394{
1395 struct sumo_power_info *pi = sumo_get_pi(rdev);
1396
1397 ps->num_levels = 1;
1398 ps->flags = 0;
1399 ps->levels[0] = pi->boot_pl;
1400}
1401
1402static void sumo_parse_pplib_non_clock_info(struct radeon_device *rdev,
1403 struct radeon_ps *rps,
1404 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1405 u8 table_rev)
1406{
1407 struct sumo_ps *ps = sumo_get_ps(rps);
1408
1409 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings)((__uint32_t)(non_clock_info->ulCapsAndSettings));
1410 rps->class = le16_to_cpu(non_clock_info->usClassification)((__uint16_t)(non_clock_info->usClassification));
1411 rps->class2 = le16_to_cpu(non_clock_info->usClassification2)((__uint16_t)(non_clock_info->usClassification2));
1412
1413 if (ATOM_PPLIB_NONCLOCKINFO_VER112 < table_rev) {
1414 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK)((__uint32_t)(non_clock_info->ulVCLK));
1415 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK)((__uint32_t)(non_clock_info->ulDCLK));
1416 } else {
1417 rps->vclk = 0;
1418 rps->dclk = 0;
1419 }
1420
1421 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT0x0008) {
1422 rdev->pm.dpm.boot_ps = rps;
1423 sumo_patch_boot_state(rdev, ps);
1424 }
1425 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE0x0400)
1426 rdev->pm.dpm.uvd_ps = rps;
1427}
1428
1429static void sumo_parse_pplib_clock_info(struct radeon_device *rdev,
1430 struct radeon_ps *rps, int index,
1431 union pplib_clock_info *clock_info)
1432{
1433 struct sumo_power_info *pi = sumo_get_pi(rdev);
1434 struct sumo_ps *ps = sumo_get_ps(rps);
1435 struct sumo_pl *pl = &ps->levels[index];
1436 u32 sclk;
1437
1438 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow)((__uint16_t)(clock_info->sumo.usEngineClockLow));
1439 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1440 pl->sclk = sclk;
1441 pl->vddc_index = clock_info->sumo.vddcIndex;
1442 pl->sclk_dpm_tdp_limit = clock_info->sumo.tdpLimit;
1443
1444 ps->num_levels = index + 1;
1445
1446 if (pi->enable_sclk_ds) {
1447 pl->ds_divider_index = 5;
1448 pl->ss_divider_index = 4;
1449 }
1450}
1451
1452static int sumo_parse_power_table(struct radeon_device *rdev)
1453{
1454 struct radeon_mode_info *mode_info = &rdev->mode_info;
1455 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1456 union pplib_power_state *power_state;
1457 int i, j, k, non_clock_array_index, clock_array_index;
1458 union pplib_clock_info *clock_info;
1459 struct _StateArray *state_array;
1460 struct _ClockInfoArray *clock_info_array;
1461 struct _NonClockInfoArray *non_clock_info_array;
1462 union power_info *power_info;
1463 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo)(((char*)(&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->PowerPlayInfo
)-(char*)0)/sizeof(USHORT))
;
1464 u16 data_offset;
1465 u8 frev, crev;
1466 u8 *power_state_offset;
1467 struct sumo_ps *ps;
1468
1469 if (!atom_parse_data_header(mode_info->atom_context, index, NULL((void *)0),
1470 &frev, &crev, &data_offset))
1471 return -EINVAL22;
1472 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1473
1474 state_array = (struct _StateArray *)
1475 (mode_info->atom_context->bios + data_offset +
1476 le16_to_cpu(power_info->pplib.usStateArrayOffset)((__uint16_t)(power_info->pplib.usStateArrayOffset)));
1477 clock_info_array = (struct _ClockInfoArray *)
1478 (mode_info->atom_context->bios + data_offset +
1479 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)((__uint16_t)(power_info->pplib.usClockInfoArrayOffset)));
1480 non_clock_info_array = (struct _NonClockInfoArray *)
1481 (mode_info->atom_context->bios + data_offset +
1482 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)((__uint16_t)(power_info->pplib.usNonClockInfoArrayOffset)
)
);
1483
1484 rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
1485 sizeof(struct radeon_ps),
1486 GFP_KERNEL(0x0001 | 0x0004));
1487 if (!rdev->pm.dpm.ps)
1488 return -ENOMEM12;
1489 power_state_offset = (u8 *)state_array->states;
1490 for (i = 0; i < state_array->ucNumEntries; i++) {
1491 u8 *idx;
1492 power_state = (union pplib_power_state *)power_state_offset;
1493 non_clock_array_index = power_state->v2.nonClockInfoIndex;
1494 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1495 &non_clock_info_array->nonClockInfo[non_clock_array_index];
1496 if (!rdev->pm.power_state[i].clock_info)
1497 return -EINVAL22;
1498 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL(0x0001 | 0x0004));
1499 if (ps == NULL((void *)0)) {
1500 kfree(rdev->pm.dpm.ps);
1501 return -ENOMEM12;
1502 }
1503 rdev->pm.dpm.ps[i].ps_priv = ps;
1504 k = 0;
1505 idx = (u8 *)&power_state->v2.clockInfoIndex[0];
1506 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1507 clock_array_index = idx[j];
1508 if (k >= SUMO_MAX_HARDWARE_POWERLEVELS5)
1509 break;
1510
1511 clock_info = (union pplib_clock_info *)
1512 ((u8 *)&clock_info_array->clockInfo[0] +
1513 (clock_array_index * clock_info_array->ucEntrySize));
1514 sumo_parse_pplib_clock_info(rdev,
1515 &rdev->pm.dpm.ps[i], k,
1516 clock_info);
1517 k++;
1518 }
1519 sumo_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1520 non_clock_info,
1521 non_clock_info_array->ucEntrySize);
1522 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1523 }
1524 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1525 return 0;
1526}
1527
1528u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
1529 struct sumo_vid_mapping_table *vid_mapping_table,
1530 u32 vid_2bit)
1531{
1532 u32 i;
1533
1534 for (i = 0; i < vid_mapping_table->num_entries; i++) {
1535 if (vid_mapping_table->entries[i].vid_2bit == vid_2bit)
1536 return vid_mapping_table->entries[i].vid_7bit;
1537 }
1538
1539 return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit;
1540}
1541
1542#if 0
1543u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev,
1544 struct sumo_vid_mapping_table *vid_mapping_table,
1545 u32 vid_7bit)
1546{
1547 u32 i;
1548
1549 for (i = 0; i < vid_mapping_table->num_entries; i++) {
1550 if (vid_mapping_table->entries[i].vid_7bit == vid_7bit)
1551 return vid_mapping_table->entries[i].vid_2bit;
1552 }
1553
1554 return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit;
1555}
1556#endif
1557
1558static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
1559 u32 vid_2bit)
1560{
1561 struct sumo_power_info *pi = sumo_get_pi(rdev);
1562 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1563
1564 if (vid_7bit > 0x7C)
1565 return 0;
1566
1567 return (15500 - vid_7bit * 125 + 5) / 10;
1568}
1569
1570static void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev,
1571 struct sumo_disp_clock_voltage_mapping_table *disp_clk_voltage_mapping_table,
1572 ATOM_CLK_VOLT_CAPABILITY *table)
1573{
1574 u32 i;
1575
1576 for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES4; i++) {
1577 if (table[i].ulMaximumSupportedCLK == 0)
1578 break;
1579
1580 disp_clk_voltage_mapping_table->display_clock_frequency[i] =
1581 table[i].ulMaximumSupportedCLK;
1582 }
1583
1584 disp_clk_voltage_mapping_table->num_max_voltage_levels = i;
1585
1586 if (disp_clk_voltage_mapping_table->num_max_voltage_levels == 0) {
1587 disp_clk_voltage_mapping_table->display_clock_frequency[0] = 80000;
1588 disp_clk_voltage_mapping_table->num_max_voltage_levels = 1;
1589 }
1590}
1591
1592void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
1593 struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
1594 ATOM_AVAILABLE_SCLK_LIST *table)
1595{
1596 u32 i;
1597 u32 n = 0;
1598 u32 prev_sclk = 0;
1599
1600 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS5; i++) {
1601 if (table[i].ulSupportedSCLK > prev_sclk) {
1602 sclk_voltage_mapping_table->entries[n].sclk_frequency =
1603 table[i].ulSupportedSCLK;
1604 sclk_voltage_mapping_table->entries[n].vid_2bit =
1605 table[i].usVoltageIndex;
1606 prev_sclk = table[i].ulSupportedSCLK;
1607 n++;
1608 }
1609 }
1610
1611 sclk_voltage_mapping_table->num_max_dpm_entries = n;
1612}
1613
1614void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
1615 struct sumo_vid_mapping_table *vid_mapping_table,
1616 ATOM_AVAILABLE_SCLK_LIST *table)
1617{
1618 u32 i, j;
1619
1620 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS5; i++) {
1621 if (table[i].ulSupportedSCLK != 0) {
1622 vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
1623 table[i].usVoltageID;
1624 vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
1625 table[i].usVoltageIndex;
1626 }
1627 }
1628
1629 for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES4; i++) {
1630 if (vid_mapping_table->entries[i].vid_7bit == 0) {
1631 for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES4; j++) {
1632 if (vid_mapping_table->entries[j].vid_7bit != 0) {
1633 vid_mapping_table->entries[i] =
1634 vid_mapping_table->entries[j];
1635 vid_mapping_table->entries[j].vid_7bit = 0;
1636 break;
1637 }
1638 }
1639
1640 if (j == SUMO_MAX_NUMBER_VOLTAGES4)
1641 break;
1642 }
1643 }
1644
1645 vid_mapping_table->num_entries = i;
1646}
1647
1648union igp_info {
1649 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1650 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1651 struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1652 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1653};
1654
1655static int sumo_parse_sys_info_table(struct radeon_device *rdev)
1656{
1657 struct sumo_power_info *pi = sumo_get_pi(rdev);
1658 struct radeon_mode_info *mode_info = &rdev->mode_info;
1659 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo)(((char*)(&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->IntegratedSystemInfo
)-(char*)0)/sizeof(USHORT))
;
1660 union igp_info *igp_info;
1661 u8 frev, crev;
1662 u16 data_offset;
1663 int i;
1664
1665 if (atom_parse_data_header(mode_info->atom_context, index, NULL((void *)0),
1666 &frev, &crev, &data_offset)) {
1667 igp_info = (union igp_info *)(mode_info->atom_context->bios +
1668 data_offset);
1669
1670 if (crev != 6) {
1671 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev)__drm_err("Unsupported IGP table: %d %d\n", frev, crev);
1672 return -EINVAL22;
1673 }
1674 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_6.ulBootUpEngineClock)((__uint32_t)(igp_info->info_6.ulBootUpEngineClock));
1675 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_6.ulMinEngineClock)((__uint32_t)(igp_info->info_6.ulMinEngineClock));
1676 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_6.ulBootUpUMAClock)((__uint32_t)(igp_info->info_6.ulBootUpUMAClock));
1677 pi->sys_info.bootup_nb_voltage_index =
1678 le16_to_cpu(igp_info->info_6.usBootUpNBVoltage)((__uint16_t)(igp_info->info_6.usBootUpNBVoltage));
1679 if (igp_info->info_6.ucHtcTmpLmt == 0)
1680 pi->sys_info.htc_tmp_lmt = 203;
1681 else
1682 pi->sys_info.htc_tmp_lmt = igp_info->info_6.ucHtcTmpLmt;
1683 if (igp_info->info_6.ucHtcHystLmt == 0)
1684 pi->sys_info.htc_hyst_lmt = 5;
1685 else
1686 pi->sys_info.htc_hyst_lmt = igp_info->info_6.ucHtcHystLmt;
1687 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1688 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n")__drm_err("The htcTmpLmt should be larger than htcHystLmt.\n"
)
;
1689 }
1690 for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS10; i++) {
1691 pi->sys_info.csr_m3_arb_cntl_default[i] =
1692 le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i])((__uint32_t)(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i
]))
;
1693 pi->sys_info.csr_m3_arb_cntl_uvd[i] =
1694 le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i])((__uint32_t)(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i]));
1695 pi->sys_info.csr_m3_arb_cntl_fs3d[i] =
1696 le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i])((__uint32_t)(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i]));
1697 }
1698 pi->sys_info.sclk_dpm_boost_margin =
1699 le32_to_cpu(igp_info->info_6.SclkDpmBoostMargin)((__uint32_t)(igp_info->info_6.SclkDpmBoostMargin));
1700 pi->sys_info.sclk_dpm_throttle_margin =
1701 le32_to_cpu(igp_info->info_6.SclkDpmThrottleMargin)((__uint32_t)(igp_info->info_6.SclkDpmThrottleMargin));
1702 pi->sys_info.sclk_dpm_tdp_limit_pg =
1703 le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitPG)((__uint16_t)(igp_info->info_6.SclkDpmTdpLimitPG));
1704 pi->sys_info.gnb_tdp_limit = le16_to_cpu(igp_info->info_6.GnbTdpLimit)((__uint16_t)(igp_info->info_6.GnbTdpLimit));
1705 pi->sys_info.sclk_dpm_tdp_limit_boost =
1706 le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitBoost)((__uint16_t)(igp_info->info_6.SclkDpmTdpLimitBoost));
1707 pi->sys_info.boost_sclk = le32_to_cpu(igp_info->info_6.ulBoostEngineCLock)((__uint32_t)(igp_info->info_6.ulBoostEngineCLock));
1708 pi->sys_info.boost_vid_2bit = igp_info->info_6.ulBoostVid_2bit;
1709 if (igp_info->info_6.EnableBoost)
1710 pi->sys_info.enable_boost = true1;
1711 else
1712 pi->sys_info.enable_boost = false0;
1713 sumo_construct_display_voltage_mapping_table(rdev,
1714 &pi->sys_info.disp_clk_voltage_mapping_table,
1715 igp_info->info_6.sDISPCLK_Voltage);
1716 sumo_construct_sclk_voltage_mapping_table(rdev,
1717 &pi->sys_info.sclk_voltage_mapping_table,
1718 igp_info->info_6.sAvail_SCLK);
1719 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1720 igp_info->info_6.sAvail_SCLK);
1721
1722 }
1723 return 0;
1724}
1725
1726static void sumo_construct_boot_and_acpi_state(struct radeon_device *rdev)
1727{
1728 struct sumo_power_info *pi = sumo_get_pi(rdev);
1729
1730 pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1731 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1732 pi->boot_pl.ds_divider_index = 0;
1733 pi->boot_pl.ss_divider_index = 0;
1734 pi->boot_pl.allow_gnb_slow = 1;
1735 pi->acpi_pl = pi->boot_pl;
1736 pi->current_ps.num_levels = 1;
1737 pi->current_ps.levels[0] = pi->boot_pl;
1738}
1739
1740int sumo_dpm_init(struct radeon_device *rdev)
1741{
1742 struct sumo_power_info *pi;
1743 u32 hw_rev = (RREG32(HW_REV)r100_mm_rreg(rdev, (0x5564), 0) & ATI_REV_ID_MASK(0xf << 28)) >> ATI_REV_ID_SHIFT28;
1744 int ret;
1745
1746 pi = kzalloc(sizeof(struct sumo_power_info), GFP_KERNEL(0x0001 | 0x0004));
1747 if (pi == NULL((void *)0))
1748 return -ENOMEM12;
1749 rdev->pm.dpm.priv = pi;
1750
1751 pi->driver_nbps_policy_disable = false0;
1752 if ((rdev->family == CHIP_PALM) && (hw_rev < 3))
1753 pi->disable_gfx_power_gating_in_uvd = true1;
1754 else
1755 pi->disable_gfx_power_gating_in_uvd = false0;
1756 pi->enable_alt_vddnb = true1;
1757 pi->enable_sclk_ds = true1;
1758 pi->enable_dynamic_m3_arbiter = false0;
1759 pi->enable_dynamic_patch_ps = true1;
1760 /* Some PALM chips don't seem to properly ungate gfx when UVD is in use;
1761 * for now just disable gfx PG.
1762 */
1763 if (rdev->family == CHIP_PALM)
1764 pi->enable_gfx_power_gating = false0;
1765 else
1766 pi->enable_gfx_power_gating = true1;
1767 pi->enable_gfx_clock_gating = true1;
1768 pi->enable_mg_clock_gating = true1;
1769 pi->enable_auto_thermal_throttling = true1;
1770
1771 ret = sumo_parse_sys_info_table(rdev);
1772 if (ret)
1773 return ret;
1774
1775 sumo_construct_boot_and_acpi_state(rdev);
1776
1777 ret = r600_get_platform_caps(rdev);
1778 if (ret)
1779 return ret;
1780
1781 ret = sumo_parse_power_table(rdev);
1782 if (ret)
1783 return ret;
1784
1785 pi->pasi = CYPRESS_HASI_DFLT400000;
1786 pi->asi = RV770_ASI_DFLT1000;
1787 pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1788 pi->enable_boost = pi->sys_info.enable_boost;
1789 pi->enable_dpm = true1;
1790
1791 return 0;
1792}
1793
1794void sumo_dpm_print_power_state(struct radeon_device *rdev,
1795 struct radeon_ps *rps)
1796{
1797 int i;
1798 struct sumo_ps *ps = sumo_get_ps(rps);
1799
1800 r600_dpm_print_class_info(rps->class, rps->class2);
1801 r600_dpm_print_cap_info(rps->caps);
1802 printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1803 for (i = 0; i < ps->num_levels; i++) {
1804 struct sumo_pl *pl = &ps->levels[i];
1805 printk("\t\tpower level %d sclk: %u vddc: %u\n",
1806 i, pl->sclk,
1807 sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
1808 }
1809 r600_dpm_print_ps_status(rdev, rps);
1810}
1811
1812void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
1813 struct seq_file *m)
1814{
1815 struct sumo_power_info *pi = sumo_get_pi(rdev);
1816 struct radeon_ps *rps = &pi->current_rps;
1817 struct sumo_ps *ps = sumo_get_ps(rps);
1818 struct sumo_pl *pl;
1819 u32 current_index =
1820 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_INDEX_MASK(0x7 << 15)) >>
1821 CURR_INDEX_SHIFT15;
1822
1823 if (current_index == BOOST_DPM_LEVEL7) {
1824 pl = &pi->boost_pl;
1825 seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1826 seq_printf(m, "power level %d sclk: %u vddc: %u\n",
1827 current_index, pl->sclk,
1828 sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
1829 } else if (current_index >= ps->num_levels) {
1830 seq_printf(m, "invalid dpm profile %d\n", current_index);
1831 } else {
1832 pl = &ps->levels[current_index];
1833 seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1834 seq_printf(m, "power level %d sclk: %u vddc: %u\n",
1835 current_index, pl->sclk,
1836 sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
1837 }
1838}
1839
1840u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev)
1841{
1842 struct sumo_power_info *pi = sumo_get_pi(rdev);
1843 struct radeon_ps *rps = &pi->current_rps;
1844 struct sumo_ps *ps = sumo_get_ps(rps);
1845 struct sumo_pl *pl;
1846 u32 current_index =
1847 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX)r100_mm_rreg(rdev, (0x66c), 0) & CURR_INDEX_MASK(0x7 << 15)) >>
1848 CURR_INDEX_SHIFT15;
1849
1850 if (current_index == BOOST_DPM_LEVEL7) {
1851 pl = &pi->boost_pl;
1852 return pl->sclk;
1853 } else if (current_index >= ps->num_levels) {
1854 return 0;
1855 } else {
1856 pl = &ps->levels[current_index];
1857 return pl->sclk;
1858 }
1859}
1860
1861u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev)
1862{
1863 struct sumo_power_info *pi = sumo_get_pi(rdev);
1864
1865 return pi->sys_info.bootup_uma_clk;
1866}
1867
1868void sumo_dpm_fini(struct radeon_device *rdev)
1869{
1870 int i;
1871
1872 sumo_cleanup_asic(rdev); /* ??? */
1873
1874 for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
1875 kfree(rdev->pm.dpm.ps[i].ps_priv);
1876 }
1877 kfree(rdev->pm.dpm.ps);
1878 kfree(rdev->pm.dpm.priv);
1879}
1880
1881u32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool_Bool low)
1882{
1883 struct sumo_power_info *pi = sumo_get_pi(rdev);
1884 struct sumo_ps *requested_state = sumo_get_ps(&pi->requested_rps);
1885
1886 if (low)
1887 return requested_state->levels[0].sclk;
1888 else
1889 return requested_state->levels[requested_state->num_levels - 1].sclk;
1890}
1891
1892u32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool_Bool low)
1893{
1894 struct sumo_power_info *pi = sumo_get_pi(rdev);
1895
1896 return pi->sys_info.bootup_uma_clk;
1897}
1898
1899int sumo_dpm_force_performance_level(struct radeon_device *rdev,
1900 enum radeon_dpm_forced_level level)
1901{
1902 struct sumo_power_info *pi = sumo_get_pi(rdev);
1903 struct radeon_ps *rps = &pi->current_rps;
1904 struct sumo_ps *ps = sumo_get_ps(rps);
1905 int i;
1906
1907 if (ps->num_levels <= 1)
1908 return 0;
1909
1910 if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
1911 if (pi->enable_boost)
1912 sumo_enable_boost(rdev, rps, false0);
1913 sumo_power_level_enable(rdev, ps->num_levels - 1, true1);
1914 sumo_set_forced_level(rdev, ps->num_levels - 1);
1915 sumo_set_forced_mode_enabled(rdev);
1916 for (i = 0; i < ps->num_levels - 1; i++) {
1917 sumo_power_level_enable(rdev, i, false0);
1918 }
1919 sumo_set_forced_mode(rdev, false0);
1920 sumo_set_forced_mode_enabled(rdev);
1921 sumo_set_forced_mode(rdev, false0);
1922 } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
1923 if (pi->enable_boost)
1924 sumo_enable_boost(rdev, rps, false0);
1925 sumo_power_level_enable(rdev, 0, true1);
1926 sumo_set_forced_level(rdev, 0);
1927 sumo_set_forced_mode_enabled(rdev);
1928 for (i = 1; i < ps->num_levels; i++) {
1929 sumo_power_level_enable(rdev, i, false0);
1930 }
1931 sumo_set_forced_mode(rdev, false0);
1932 sumo_set_forced_mode_enabled(rdev);
1933 sumo_set_forced_mode(rdev, false0);
1934 } else {
1935 for (i = 0; i < ps->num_levels; i++) {
1936 sumo_power_level_enable(rdev, i, true1);
1937 }
1938 if (pi->enable_boost)
1939 sumo_enable_boost(rdev, rps, true1);
1940 }
1941
1942 rdev->pm.dpm.forced_level = level;
1943
1944 return 0;
1945}