Line data Source code
1 : /*
2 : * Copyright 2016 Advanced Micro Devices, Inc.
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the "Software"),
6 : * to deal in the Software without restriction, including without limitation
7 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : * and/or sell copies of the Software, and to permit persons to whom the
9 : * Software is furnished to do so, subject to the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 : * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 : * OTHER DEALINGS IN THE SOFTWARE.
21 : *
22 : */
23 :
24 : #include "smu7_hwmgr.h"
25 : #include "smu7_clockpowergating.h"
26 : #include "smu7_common.h"
27 :
28 : static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
29 : {
30 0 : return smum_send_msg_to_smc(hwmgr, enable ?
31 : PPSMC_MSG_UVDDPM_Enable :
32 : PPSMC_MSG_UVDDPM_Disable,
33 : NULL);
34 : }
35 :
36 : static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
37 : {
38 0 : return smum_send_msg_to_smc(hwmgr, enable ?
39 : PPSMC_MSG_VCEDPM_Enable :
40 : PPSMC_MSG_VCEDPM_Disable,
41 : NULL);
42 : }
43 :
44 0 : static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
45 : {
46 0 : if (!bgate)
47 0 : smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
48 0 : return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
49 : }
50 :
51 0 : static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
52 : {
53 0 : if (!bgate)
54 0 : smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
55 0 : return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
56 : }
57 :
58 0 : int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
59 : {
60 0 : if (phm_cf_want_uvd_power_gating(hwmgr))
61 0 : return smum_send_msg_to_smc(hwmgr,
62 : PPSMC_MSG_UVDPowerOFF,
63 : NULL);
64 : return 0;
65 : }
66 :
67 0 : static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
68 : {
69 0 : if (phm_cf_want_uvd_power_gating(hwmgr)) {
70 0 : if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
71 : PHM_PlatformCaps_UVDDynamicPowerGating)) {
72 0 : return smum_send_msg_to_smc_with_parameter(hwmgr,
73 : PPSMC_MSG_UVDPowerON, 1, NULL);
74 : } else {
75 0 : return smum_send_msg_to_smc_with_parameter(hwmgr,
76 : PPSMC_MSG_UVDPowerON, 0, NULL);
77 : }
78 : }
79 :
80 : return 0;
81 : }
82 :
83 0 : static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
84 : {
85 0 : if (phm_cf_want_vce_power_gating(hwmgr))
86 0 : return smum_send_msg_to_smc(hwmgr,
87 : PPSMC_MSG_VCEPowerOFF,
88 : NULL);
89 : return 0;
90 : }
91 :
92 0 : static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
93 : {
94 0 : if (phm_cf_want_vce_power_gating(hwmgr))
95 0 : return smum_send_msg_to_smc(hwmgr,
96 : PPSMC_MSG_VCEPowerON,
97 : NULL);
98 : return 0;
99 : }
100 :
101 0 : int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
102 : {
103 0 : struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
104 :
105 0 : data->uvd_power_gated = false;
106 0 : data->vce_power_gated = false;
107 :
108 0 : smu7_powerup_uvd(hwmgr);
109 0 : smu7_powerup_vce(hwmgr);
110 :
111 0 : return 0;
112 : }
113 :
114 0 : void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
115 : {
116 0 : struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
117 :
118 0 : data->uvd_power_gated = bgate;
119 :
120 0 : if (bgate) {
121 0 : amdgpu_device_ip_set_powergating_state(hwmgr->adev,
122 : AMD_IP_BLOCK_TYPE_UVD,
123 : AMD_PG_STATE_GATE);
124 0 : amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
125 : AMD_IP_BLOCK_TYPE_UVD,
126 : AMD_CG_STATE_GATE);
127 0 : smu7_update_uvd_dpm(hwmgr, true);
128 0 : smu7_powerdown_uvd(hwmgr);
129 : } else {
130 0 : smu7_powerup_uvd(hwmgr);
131 0 : amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
132 : AMD_IP_BLOCK_TYPE_UVD,
133 : AMD_CG_STATE_UNGATE);
134 0 : amdgpu_device_ip_set_powergating_state(hwmgr->adev,
135 : AMD_IP_BLOCK_TYPE_UVD,
136 : AMD_PG_STATE_UNGATE);
137 0 : smu7_update_uvd_dpm(hwmgr, false);
138 : }
139 :
140 0 : }
141 :
142 0 : void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
143 : {
144 0 : struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
145 :
146 0 : data->vce_power_gated = bgate;
147 :
148 0 : if (bgate) {
149 0 : amdgpu_device_ip_set_powergating_state(hwmgr->adev,
150 : AMD_IP_BLOCK_TYPE_VCE,
151 : AMD_PG_STATE_GATE);
152 0 : amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
153 : AMD_IP_BLOCK_TYPE_VCE,
154 : AMD_CG_STATE_GATE);
155 0 : smu7_update_vce_dpm(hwmgr, true);
156 0 : smu7_powerdown_vce(hwmgr);
157 : } else {
158 0 : smu7_powerup_vce(hwmgr);
159 0 : amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
160 : AMD_IP_BLOCK_TYPE_VCE,
161 : AMD_CG_STATE_UNGATE);
162 0 : amdgpu_device_ip_set_powergating_state(hwmgr->adev,
163 : AMD_IP_BLOCK_TYPE_VCE,
164 : AMD_PG_STATE_UNGATE);
165 0 : smu7_update_vce_dpm(hwmgr, false);
166 : }
167 0 : }
168 :
169 0 : 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 0 : if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
176 : return 0;
177 :
178 0 : switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
179 : case PP_GROUP_GFX:
180 0 : switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
181 : case PP_BLOCK_GFX_CG:
182 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
183 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
184 : PPSMC_MSG_EnableClockGatingFeature :
185 : PPSMC_MSG_DisableClockGatingFeature;
186 0 : value = CG_GFX_CGCG_MASK;
187 :
188 0 : if (smum_send_msg_to_smc_with_parameter(
189 : hwmgr, msg, value, NULL))
190 : return -EINVAL;
191 : }
192 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
193 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
194 : ? PPSMC_MSG_EnableClockGatingFeature
195 : : PPSMC_MSG_DisableClockGatingFeature;
196 0 : value = CG_GFX_CGLS_MASK;
197 :
198 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
206 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
207 : PPSMC_MSG_EnableClockGatingFeature :
208 : PPSMC_MSG_DisableClockGatingFeature;
209 0 : value = CG_GFX_3DCG_MASK;
210 :
211 0 : if (smum_send_msg_to_smc_with_parameter(
212 : hwmgr, msg, value, NULL))
213 : return -EINVAL;
214 : }
215 :
216 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
217 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
218 : PPSMC_MSG_EnableClockGatingFeature :
219 : PPSMC_MSG_DisableClockGatingFeature;
220 0 : value = CG_GFX_3DLS_MASK;
221 :
222 0 : 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 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
230 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
231 : PPSMC_MSG_EnableClockGatingFeature :
232 : PPSMC_MSG_DisableClockGatingFeature;
233 0 : value = CG_GFX_RLC_LS_MASK;
234 :
235 0 : 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 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
243 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
244 : PPSMC_MSG_EnableClockGatingFeature :
245 : PPSMC_MSG_DisableClockGatingFeature;
246 0 : value = CG_GFX_CP_LS_MASK;
247 :
248 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
256 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
257 : PPSMC_MSG_EnableClockGatingFeature :
258 : PPSMC_MSG_DisableClockGatingFeature;
259 0 : value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
260 : CG_GFX_OTHERS_MGCG_MASK);
261 :
262 0 : 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 0 : switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
275 : case PP_BLOCK_SYS_BIF:
276 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
277 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
278 : PPSMC_MSG_EnableClockGatingFeature :
279 : PPSMC_MSG_DisableClockGatingFeature;
280 0 : value = CG_SYS_BIF_MGCG_MASK;
281 :
282 0 : if (smum_send_msg_to_smc_with_parameter(
283 : hwmgr, msg, value, NULL))
284 : return -EINVAL;
285 : }
286 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
287 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
288 : PPSMC_MSG_EnableClockGatingFeature :
289 : PPSMC_MSG_DisableClockGatingFeature;
290 0 : value = CG_SYS_BIF_MGLS_MASK;
291 :
292 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
300 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
301 : PPSMC_MSG_EnableClockGatingFeature :
302 : PPSMC_MSG_DisableClockGatingFeature;
303 0 : value = CG_SYS_MC_MGCG_MASK;
304 :
305 0 : if (smum_send_msg_to_smc_with_parameter(
306 : hwmgr, msg, value, NULL))
307 : return -EINVAL;
308 : }
309 :
310 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
311 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
312 : PPSMC_MSG_EnableClockGatingFeature :
313 : PPSMC_MSG_DisableClockGatingFeature;
314 0 : value = CG_SYS_MC_MGLS_MASK;
315 :
316 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
324 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
325 : PPSMC_MSG_EnableClockGatingFeature :
326 : PPSMC_MSG_DisableClockGatingFeature;
327 0 : value = CG_SYS_DRM_MGCG_MASK;
328 :
329 0 : if (smum_send_msg_to_smc_with_parameter(
330 : hwmgr, msg, value, NULL))
331 : return -EINVAL;
332 : }
333 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
334 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
335 : PPSMC_MSG_EnableClockGatingFeature :
336 : PPSMC_MSG_DisableClockGatingFeature;
337 0 : value = CG_SYS_DRM_MGLS_MASK;
338 :
339 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
347 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
348 : PPSMC_MSG_EnableClockGatingFeature :
349 : PPSMC_MSG_DisableClockGatingFeature;
350 0 : value = CG_SYS_HDP_MGCG_MASK;
351 :
352 0 : if (smum_send_msg_to_smc_with_parameter(
353 : hwmgr, msg, value, NULL))
354 : return -EINVAL;
355 : }
356 :
357 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
358 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
359 : PPSMC_MSG_EnableClockGatingFeature :
360 : PPSMC_MSG_DisableClockGatingFeature;
361 0 : value = CG_SYS_HDP_MGLS_MASK;
362 :
363 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
371 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
372 : PPSMC_MSG_EnableClockGatingFeature :
373 : PPSMC_MSG_DisableClockGatingFeature;
374 0 : value = CG_SYS_SDMA_MGCG_MASK;
375 :
376 0 : if (smum_send_msg_to_smc_with_parameter(
377 : hwmgr, msg, value, NULL))
378 : return -EINVAL;
379 : }
380 :
381 0 : if (PP_STATE_SUPPORT_LS & *msg_id) {
382 0 : msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
383 : PPSMC_MSG_EnableClockGatingFeature :
384 : PPSMC_MSG_DisableClockGatingFeature;
385 0 : value = CG_SYS_SDMA_MGLS_MASK;
386 :
387 0 : 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 0 : if (PP_STATE_SUPPORT_CG & *msg_id) {
395 0 : msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
396 : PPSMC_MSG_EnableClockGatingFeature :
397 : PPSMC_MSG_DisableClockGatingFeature;
398 0 : value = CG_SYS_ROM_MASK;
399 :
400 0 : 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 : */
424 0 : int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable)
425 : {
426 0 : struct amdgpu_device *adev = hwmgr->adev;
427 :
428 0 : if (enable)
429 0 : 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 0 : return smum_send_msg_to_smc(hwmgr,
435 : PPSMC_MSG_GFX_CU_PG_DISABLE,
436 : NULL);
437 : }
|