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 "smu7_hwmgr.h"
25 #include "smu7_clockpowergating.h"
26 #include "smu7_common.h"
27
smu7_enable_disable_uvd_dpm(struct pp_hwmgr * hwmgr,bool enable)28 static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
29 {
30 return smum_send_msg_to_smc(hwmgr, enable ?
31 PPSMC_MSG_UVDDPM_Enable :
32 PPSMC_MSG_UVDDPM_Disable,
33 NULL);
34 }
35
smu7_enable_disable_vce_dpm(struct pp_hwmgr * hwmgr,bool enable)36 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
37 {
38 return smum_send_msg_to_smc(hwmgr, enable ?
39 PPSMC_MSG_VCEDPM_Enable :
40 PPSMC_MSG_VCEDPM_Disable,
41 NULL);
42 }
43
smu7_update_uvd_dpm(struct pp_hwmgr * hwmgr,bool bgate)44 static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
45 {
46 if (!bgate)
47 smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
48 return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
49 }
50
smu7_update_vce_dpm(struct pp_hwmgr * hwmgr,bool bgate)51 static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
52 {
53 if (!bgate)
54 smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
55 return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
56 }
57
smu7_powerdown_uvd(struct pp_hwmgr * hwmgr)58 int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
59 {
60 if (phm_cf_want_uvd_power_gating(hwmgr))
61 return smum_send_msg_to_smc(hwmgr,
62 PPSMC_MSG_UVDPowerOFF,
63 NULL);
64 return 0;
65 }
66
smu7_powerup_uvd(struct pp_hwmgr * hwmgr)67 static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
68 {
69 if (phm_cf_want_uvd_power_gating(hwmgr)) {
70 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
71 PHM_PlatformCaps_UVDDynamicPowerGating)) {
72 return smum_send_msg_to_smc_with_parameter(hwmgr,
73 PPSMC_MSG_UVDPowerON, 1, NULL);
74 } else {
75 return smum_send_msg_to_smc_with_parameter(hwmgr,
76 PPSMC_MSG_UVDPowerON, 0, NULL);
77 }
78 }
79
80 return 0;
81 }
82
smu7_powerdown_vce(struct pp_hwmgr * hwmgr)83 static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
84 {
85 if (phm_cf_want_vce_power_gating(hwmgr))
86 return smum_send_msg_to_smc(hwmgr,
87 PPSMC_MSG_VCEPowerOFF,
88 NULL);
89 return 0;
90 }
91
smu7_powerup_vce(struct pp_hwmgr * hwmgr)92 static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
93 {
94 if (phm_cf_want_vce_power_gating(hwmgr))
95 return smum_send_msg_to_smc(hwmgr,
96 PPSMC_MSG_VCEPowerON,
97 NULL);
98 return 0;
99 }
100
smu7_disable_clock_power_gating(struct pp_hwmgr * hwmgr)101 int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
102 {
103 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
104
105 data->uvd_power_gated = false;
106 data->vce_power_gated = false;
107
108 smu7_powerup_uvd(hwmgr);
109 smu7_powerup_vce(hwmgr);
110
111 return 0;
112 }
113
smu7_powergate_uvd(struct pp_hwmgr * hwmgr,bool bgate)114 void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
115 {
116 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
117
118 data->uvd_power_gated = bgate;
119
120 if (bgate) {
121 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
122 AMD_IP_BLOCK_TYPE_UVD,
123 AMD_PG_STATE_GATE);
124 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
125 AMD_IP_BLOCK_TYPE_UVD,
126 AMD_CG_STATE_GATE);
127 smu7_update_uvd_dpm(hwmgr, true);
128 smu7_powerdown_uvd(hwmgr);
129 } else {
130 smu7_powerup_uvd(hwmgr);
131 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
132 AMD_IP_BLOCK_TYPE_UVD,
133 AMD_CG_STATE_UNGATE);
134 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
135 AMD_IP_BLOCK_TYPE_UVD,
136 AMD_PG_STATE_UNGATE);
137 smu7_update_uvd_dpm(hwmgr, false);
138 }
139
140 }
141
smu7_powergate_vce(struct pp_hwmgr * hwmgr,bool bgate)142 void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
143 {
144 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
145
146 data->vce_power_gated = bgate;
147
148 if (bgate) {
149 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
150 AMD_IP_BLOCK_TYPE_VCE,
151 AMD_PG_STATE_GATE);
152 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
153 AMD_IP_BLOCK_TYPE_VCE,
154 AMD_CG_STATE_GATE);
155 smu7_update_vce_dpm(hwmgr, true);
156 smu7_powerdown_vce(hwmgr);
157 } else {
158 smu7_powerup_vce(hwmgr);
159 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
160 AMD_IP_BLOCK_TYPE_VCE,
161 AMD_CG_STATE_UNGATE);
162 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
163 AMD_IP_BLOCK_TYPE_VCE,
164 AMD_PG_STATE_UNGATE);
165 smu7_update_vce_dpm(hwmgr, false);
166 }
167 }
168
smu7_update_clock_gatings(struct pp_hwmgr * hwmgr,const uint32_t * msg_id)169 int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
170 const uint32_t *msg_id)
171 {
172 PPSMC_Msg msg;
173 uint32_t value;
174
175 if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
176 return 0;
177
178 switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
179 case PP_GROUP_GFX:
180 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
181 case PP_BLOCK_GFX_CG:
182 if (PP_STATE_SUPPORT_CG & *msg_id) {
183 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
184 PPSMC_MSG_EnableClockGatingFeature :
185 PPSMC_MSG_DisableClockGatingFeature;
186 value = CG_GFX_CGCG_MASK;
187
188 if (smum_send_msg_to_smc_with_parameter(
189 hwmgr, msg, value, NULL))
190 return -EINVAL;
191 }
192 if (PP_STATE_SUPPORT_LS & *msg_id) {
193 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
194 ? PPSMC_MSG_EnableClockGatingFeature
195 : PPSMC_MSG_DisableClockGatingFeature;
196 value = CG_GFX_CGLS_MASK;
197
198 if (smum_send_msg_to_smc_with_parameter(
199 hwmgr, msg, value, NULL))
200 return -EINVAL;
201 }
202 break;
203
204 case PP_BLOCK_GFX_3D:
205 if (PP_STATE_SUPPORT_CG & *msg_id) {
206 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
207 PPSMC_MSG_EnableClockGatingFeature :
208 PPSMC_MSG_DisableClockGatingFeature;
209 value = CG_GFX_3DCG_MASK;
210
211 if (smum_send_msg_to_smc_with_parameter(
212 hwmgr, msg, value, NULL))
213 return -EINVAL;
214 }
215
216 if (PP_STATE_SUPPORT_LS & *msg_id) {
217 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
218 PPSMC_MSG_EnableClockGatingFeature :
219 PPSMC_MSG_DisableClockGatingFeature;
220 value = CG_GFX_3DLS_MASK;
221
222 if (smum_send_msg_to_smc_with_parameter(
223 hwmgr, msg, value, NULL))
224 return -EINVAL;
225 }
226 break;
227
228 case PP_BLOCK_GFX_RLC:
229 if (PP_STATE_SUPPORT_LS & *msg_id) {
230 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
231 PPSMC_MSG_EnableClockGatingFeature :
232 PPSMC_MSG_DisableClockGatingFeature;
233 value = CG_GFX_RLC_LS_MASK;
234
235 if (smum_send_msg_to_smc_with_parameter(
236 hwmgr, msg, value, NULL))
237 return -EINVAL;
238 }
239 break;
240
241 case PP_BLOCK_GFX_CP:
242 if (PP_STATE_SUPPORT_LS & *msg_id) {
243 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
244 PPSMC_MSG_EnableClockGatingFeature :
245 PPSMC_MSG_DisableClockGatingFeature;
246 value = CG_GFX_CP_LS_MASK;
247
248 if (smum_send_msg_to_smc_with_parameter(
249 hwmgr, msg, value, NULL))
250 return -EINVAL;
251 }
252 break;
253
254 case PP_BLOCK_GFX_MG:
255 if (PP_STATE_SUPPORT_CG & *msg_id) {
256 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
257 PPSMC_MSG_EnableClockGatingFeature :
258 PPSMC_MSG_DisableClockGatingFeature;
259 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
260 CG_GFX_OTHERS_MGCG_MASK);
261
262 if (smum_send_msg_to_smc_with_parameter(
263 hwmgr, msg, value, NULL))
264 return -EINVAL;
265 }
266 break;
267
268 default:
269 return -EINVAL;
270 }
271 break;
272
273 case PP_GROUP_SYS:
274 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
275 case PP_BLOCK_SYS_BIF:
276 if (PP_STATE_SUPPORT_CG & *msg_id) {
277 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
278 PPSMC_MSG_EnableClockGatingFeature :
279 PPSMC_MSG_DisableClockGatingFeature;
280 value = CG_SYS_BIF_MGCG_MASK;
281
282 if (smum_send_msg_to_smc_with_parameter(
283 hwmgr, msg, value, NULL))
284 return -EINVAL;
285 }
286 if (PP_STATE_SUPPORT_LS & *msg_id) {
287 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
288 PPSMC_MSG_EnableClockGatingFeature :
289 PPSMC_MSG_DisableClockGatingFeature;
290 value = CG_SYS_BIF_MGLS_MASK;
291
292 if (smum_send_msg_to_smc_with_parameter(
293 hwmgr, msg, value, NULL))
294 return -EINVAL;
295 }
296 break;
297
298 case PP_BLOCK_SYS_MC:
299 if (PP_STATE_SUPPORT_CG & *msg_id) {
300 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
301 PPSMC_MSG_EnableClockGatingFeature :
302 PPSMC_MSG_DisableClockGatingFeature;
303 value = CG_SYS_MC_MGCG_MASK;
304
305 if (smum_send_msg_to_smc_with_parameter(
306 hwmgr, msg, value, NULL))
307 return -EINVAL;
308 }
309
310 if (PP_STATE_SUPPORT_LS & *msg_id) {
311 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
312 PPSMC_MSG_EnableClockGatingFeature :
313 PPSMC_MSG_DisableClockGatingFeature;
314 value = CG_SYS_MC_MGLS_MASK;
315
316 if (smum_send_msg_to_smc_with_parameter(
317 hwmgr, msg, value, NULL))
318 return -EINVAL;
319 }
320 break;
321
322 case PP_BLOCK_SYS_DRM:
323 if (PP_STATE_SUPPORT_CG & *msg_id) {
324 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
325 PPSMC_MSG_EnableClockGatingFeature :
326 PPSMC_MSG_DisableClockGatingFeature;
327 value = CG_SYS_DRM_MGCG_MASK;
328
329 if (smum_send_msg_to_smc_with_parameter(
330 hwmgr, msg, value, NULL))
331 return -EINVAL;
332 }
333 if (PP_STATE_SUPPORT_LS & *msg_id) {
334 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
335 PPSMC_MSG_EnableClockGatingFeature :
336 PPSMC_MSG_DisableClockGatingFeature;
337 value = CG_SYS_DRM_MGLS_MASK;
338
339 if (smum_send_msg_to_smc_with_parameter(
340 hwmgr, msg, value, NULL))
341 return -EINVAL;
342 }
343 break;
344
345 case PP_BLOCK_SYS_HDP:
346 if (PP_STATE_SUPPORT_CG & *msg_id) {
347 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
348 PPSMC_MSG_EnableClockGatingFeature :
349 PPSMC_MSG_DisableClockGatingFeature;
350 value = CG_SYS_HDP_MGCG_MASK;
351
352 if (smum_send_msg_to_smc_with_parameter(
353 hwmgr, msg, value, NULL))
354 return -EINVAL;
355 }
356
357 if (PP_STATE_SUPPORT_LS & *msg_id) {
358 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
359 PPSMC_MSG_EnableClockGatingFeature :
360 PPSMC_MSG_DisableClockGatingFeature;
361 value = CG_SYS_HDP_MGLS_MASK;
362
363 if (smum_send_msg_to_smc_with_parameter(
364 hwmgr, msg, value, NULL))
365 return -EINVAL;
366 }
367 break;
368
369 case PP_BLOCK_SYS_SDMA:
370 if (PP_STATE_SUPPORT_CG & *msg_id) {
371 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
372 PPSMC_MSG_EnableClockGatingFeature :
373 PPSMC_MSG_DisableClockGatingFeature;
374 value = CG_SYS_SDMA_MGCG_MASK;
375
376 if (smum_send_msg_to_smc_with_parameter(
377 hwmgr, msg, value, NULL))
378 return -EINVAL;
379 }
380
381 if (PP_STATE_SUPPORT_LS & *msg_id) {
382 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
383 PPSMC_MSG_EnableClockGatingFeature :
384 PPSMC_MSG_DisableClockGatingFeature;
385 value = CG_SYS_SDMA_MGLS_MASK;
386
387 if (smum_send_msg_to_smc_with_parameter(
388 hwmgr, msg, value, NULL))
389 return -EINVAL;
390 }
391 break;
392
393 case PP_BLOCK_SYS_ROM:
394 if (PP_STATE_SUPPORT_CG & *msg_id) {
395 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
396 PPSMC_MSG_EnableClockGatingFeature :
397 PPSMC_MSG_DisableClockGatingFeature;
398 value = CG_SYS_ROM_MASK;
399
400 if (smum_send_msg_to_smc_with_parameter(
401 hwmgr, msg, value, NULL))
402 return -EINVAL;
403 }
404 break;
405
406 default:
407 return -EINVAL;
408
409 }
410 break;
411
412 default:
413 return -EINVAL;
414
415 }
416
417 return 0;
418 }
419
420 /* This function is for Polaris11 only for now,
421 * Powerplay will only control the static per CU Power Gating.
422 * Dynamic per CU Power Gating will be done in gfx.
423 */
smu7_powergate_gfx(struct pp_hwmgr * hwmgr,bool enable)424 int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable)
425 {
426 struct amdgpu_device *adev = hwmgr->adev;
427
428 if (enable)
429 return smum_send_msg_to_smc_with_parameter(hwmgr,
430 PPSMC_MSG_GFX_CU_PG_ENABLE,
431 adev->gfx.cu_info.number,
432 NULL);
433 else
434 return smum_send_msg_to_smc(hwmgr,
435 PPSMC_MSG_GFX_CU_PG_DISABLE,
436 NULL);
437 }
438