]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
943bdf29e3d66e452d458e0be760440d65437985
[karo-tx-linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / smu7_clockpowergating.c
1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23
24 #include "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         return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
31                         PPSMC_MSG_UVDDPM_Enable :
32                         PPSMC_MSG_UVDDPM_Disable);
33 }
34
35 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
36 {
37         return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
38                         PPSMC_MSG_VCEDPM_Enable :
39                         PPSMC_MSG_VCEDPM_Disable);
40 }
41
42 static int smu7_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable)
43 {
44         return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
45                         PPSMC_MSG_SAMUDPM_Enable :
46                         PPSMC_MSG_SAMUDPM_Disable);
47 }
48
49 static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
50 {
51         if (!bgate)
52                 smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
53         return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
54 }
55
56 static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
57 {
58         if (!bgate)
59                 smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
60         return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
61 }
62
63 static int smu7_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate)
64 {
65         if (!bgate)
66                 smum_update_smc_table(hwmgr, SMU_SAMU_TABLE);
67         return smu7_enable_disable_samu_dpm(hwmgr, !bgate);
68 }
69
70 int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
71 {
72         if (phm_cf_want_uvd_power_gating(hwmgr))
73                 return smum_send_msg_to_smc(hwmgr->smumgr,
74                                 PPSMC_MSG_UVDPowerOFF);
75         return 0;
76 }
77
78 static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
79 {
80         if (phm_cf_want_uvd_power_gating(hwmgr)) {
81                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
82                                   PHM_PlatformCaps_UVDDynamicPowerGating)) {
83                         return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
84                                         PPSMC_MSG_UVDPowerON, 1);
85                 } else {
86                         return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
87                                         PPSMC_MSG_UVDPowerON, 0);
88                 }
89         }
90
91         return 0;
92 }
93
94 static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
95 {
96         if (phm_cf_want_vce_power_gating(hwmgr))
97                 return smum_send_msg_to_smc(hwmgr->smumgr,
98                                 PPSMC_MSG_VCEPowerOFF);
99         return 0;
100 }
101
102 static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
103 {
104         if (phm_cf_want_vce_power_gating(hwmgr))
105                 return smum_send_msg_to_smc(hwmgr->smumgr,
106                                 PPSMC_MSG_VCEPowerON);
107         return 0;
108 }
109
110 static int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
111 {
112         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
113                         PHM_PlatformCaps_SamuPowerGating))
114                 return smum_send_msg_to_smc(hwmgr->smumgr,
115                                 PPSMC_MSG_SAMPowerOFF);
116         return 0;
117 }
118
119 static int smu7_powerup_samu(struct pp_hwmgr *hwmgr)
120 {
121         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
122                         PHM_PlatformCaps_SamuPowerGating))
123                 return smum_send_msg_to_smc(hwmgr->smumgr,
124                                 PPSMC_MSG_SAMPowerON);
125         return 0;
126 }
127
128 int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
129 {
130         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
131
132         data->uvd_power_gated = false;
133         data->vce_power_gated = false;
134         data->samu_power_gated = false;
135
136         smu7_powerup_uvd(hwmgr);
137         smu7_powerup_vce(hwmgr);
138         smu7_powerup_samu(hwmgr);
139
140         return 0;
141 }
142
143 int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
144 {
145         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
146
147         data->uvd_power_gated = bgate;
148
149         if (bgate) {
150                 cgs_set_powergating_state(hwmgr->device,
151                                                 AMD_IP_BLOCK_TYPE_UVD,
152                                                 AMD_PG_STATE_GATE);
153                 cgs_set_clockgating_state(hwmgr->device,
154                                 AMD_IP_BLOCK_TYPE_UVD,
155                                 AMD_CG_STATE_GATE);
156                 smu7_update_uvd_dpm(hwmgr, true);
157                 smu7_powerdown_uvd(hwmgr);
158         } else {
159                 smu7_powerup_uvd(hwmgr);
160                 cgs_set_clockgating_state(hwmgr->device,
161                                 AMD_IP_BLOCK_TYPE_UVD,
162                                 AMD_CG_STATE_UNGATE);
163                 cgs_set_powergating_state(hwmgr->device,
164                                                 AMD_IP_BLOCK_TYPE_UVD,
165                                                 AMD_CG_STATE_UNGATE);
166                 smu7_update_uvd_dpm(hwmgr, false);
167         }
168
169         return 0;
170 }
171
172 int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
173 {
174         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
175
176         if (data->vce_power_gated == bgate)
177                 return 0;
178
179         data->vce_power_gated = bgate;
180
181         if (bgate) {
182                 cgs_set_clockgating_state(hwmgr->device,
183                                 AMD_IP_BLOCK_TYPE_VCE,
184                                 AMD_CG_STATE_GATE);
185                 smu7_update_vce_dpm(hwmgr, true);
186                 smu7_powerdown_vce(hwmgr);
187         } else {
188                 smu7_powerup_vce(hwmgr);
189                 smu7_update_vce_dpm(hwmgr, false);
190                 cgs_set_clockgating_state(hwmgr->device,
191                                 AMD_IP_BLOCK_TYPE_VCE,
192                                 AMD_CG_STATE_UNGATE);
193         }
194         return 0;
195 }
196
197 int smu7_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
198 {
199         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
200
201         if (data->samu_power_gated == bgate)
202                 return 0;
203
204         data->samu_power_gated = bgate;
205
206         if (bgate) {
207                 smu7_update_samu_dpm(hwmgr, true);
208                 smu7_powerdown_samu(hwmgr);
209         } else {
210                 smu7_powerup_samu(hwmgr);
211                 smu7_update_samu_dpm(hwmgr, false);
212         }
213
214         return 0;
215 }
216
217 int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
218                                         const uint32_t *msg_id)
219 {
220         PPSMC_Msg msg;
221         uint32_t value;
222
223         if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
224                 return 0;
225
226         switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
227         case PP_GROUP_GFX:
228                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
229                 case PP_BLOCK_GFX_CG:
230                         if (PP_STATE_SUPPORT_CG & *msg_id) {
231                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
232                                                 PPSMC_MSG_EnableClockGatingFeature :
233                                                 PPSMC_MSG_DisableClockGatingFeature;
234                                 value = CG_GFX_CGCG_MASK;
235
236                                 if (smum_send_msg_to_smc_with_parameter(
237                                                 hwmgr->smumgr, msg, value))
238                                         return -EINVAL;
239                         }
240                         if (PP_STATE_SUPPORT_LS & *msg_id) {
241                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
242                                         ? PPSMC_MSG_EnableClockGatingFeature
243                                         : PPSMC_MSG_DisableClockGatingFeature;
244                                 value = CG_GFX_CGLS_MASK;
245
246                                 if (smum_send_msg_to_smc_with_parameter(
247                                                 hwmgr->smumgr, msg, value))
248                                         return -EINVAL;
249                         }
250                         break;
251
252                 case PP_BLOCK_GFX_3D:
253                         if (PP_STATE_SUPPORT_CG & *msg_id) {
254                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
255                                                 PPSMC_MSG_EnableClockGatingFeature :
256                                                 PPSMC_MSG_DisableClockGatingFeature;
257                                 value = CG_GFX_3DCG_MASK;
258
259                                 if (smum_send_msg_to_smc_with_parameter(
260                                                 hwmgr->smumgr, msg, value))
261                                         return -EINVAL;
262                         }
263
264                         if  (PP_STATE_SUPPORT_LS & *msg_id) {
265                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
266                                                 PPSMC_MSG_EnableClockGatingFeature :
267                                                 PPSMC_MSG_DisableClockGatingFeature;
268                                 value = CG_GFX_3DLS_MASK;
269
270                                 if (smum_send_msg_to_smc_with_parameter(
271                                                 hwmgr->smumgr, msg, value))
272                                         return -EINVAL;
273                         }
274                         break;
275
276                 case PP_BLOCK_GFX_RLC:
277                         if (PP_STATE_SUPPORT_LS & *msg_id) {
278                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
279                                                 PPSMC_MSG_EnableClockGatingFeature :
280                                                 PPSMC_MSG_DisableClockGatingFeature;
281                                 value = CG_GFX_RLC_LS_MASK;
282
283                                 if (smum_send_msg_to_smc_with_parameter(
284                                                 hwmgr->smumgr, msg, value))
285                                         return -EINVAL;
286                         }
287                         break;
288
289                 case PP_BLOCK_GFX_CP:
290                         if (PP_STATE_SUPPORT_LS & *msg_id) {
291                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
292                                                 PPSMC_MSG_EnableClockGatingFeature :
293                                                 PPSMC_MSG_DisableClockGatingFeature;
294                                 value = CG_GFX_CP_LS_MASK;
295
296                                 if (smum_send_msg_to_smc_with_parameter(
297                                                 hwmgr->smumgr, msg, value))
298                                         return -EINVAL;
299                         }
300                         break;
301
302                 case PP_BLOCK_GFX_MG:
303                         if (PP_STATE_SUPPORT_CG & *msg_id) {
304                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
305                                                 PPSMC_MSG_EnableClockGatingFeature :
306                                                 PPSMC_MSG_DisableClockGatingFeature;
307                                 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
308                                                 CG_GFX_OTHERS_MGCG_MASK);
309
310                                 if (smum_send_msg_to_smc_with_parameter(
311                                                 hwmgr->smumgr, msg, value))
312                                         return -EINVAL;
313                         }
314                         break;
315
316                 default:
317                         return -EINVAL;
318                 }
319                 break;
320
321         case PP_GROUP_SYS:
322                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
323                 case PP_BLOCK_SYS_BIF:
324                         if (PP_STATE_SUPPORT_CG & *msg_id) {
325                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
326                                                 PPSMC_MSG_EnableClockGatingFeature :
327                                                 PPSMC_MSG_DisableClockGatingFeature;
328                                 value = CG_SYS_BIF_MGCG_MASK;
329
330                                 if (smum_send_msg_to_smc_with_parameter(
331                                                 hwmgr->smumgr, msg, value))
332                                         return -EINVAL;
333                         }
334                         if  (PP_STATE_SUPPORT_LS & *msg_id) {
335                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
336                                                 PPSMC_MSG_EnableClockGatingFeature :
337                                                 PPSMC_MSG_DisableClockGatingFeature;
338                                 value = CG_SYS_BIF_MGLS_MASK;
339
340                                 if (smum_send_msg_to_smc_with_parameter(
341                                                 hwmgr->smumgr, msg, value))
342                                         return -EINVAL;
343                         }
344                         break;
345
346                 case PP_BLOCK_SYS_MC:
347                         if (PP_STATE_SUPPORT_CG & *msg_id) {
348                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
349                                                 PPSMC_MSG_EnableClockGatingFeature :
350                                                 PPSMC_MSG_DisableClockGatingFeature;
351                                 value = CG_SYS_MC_MGCG_MASK;
352
353                                 if (smum_send_msg_to_smc_with_parameter(
354                                                 hwmgr->smumgr, msg, value))
355                                         return -EINVAL;
356                         }
357
358                         if (PP_STATE_SUPPORT_LS & *msg_id) {
359                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
360                                                 PPSMC_MSG_EnableClockGatingFeature :
361                                                 PPSMC_MSG_DisableClockGatingFeature;
362                                 value = CG_SYS_MC_MGLS_MASK;
363
364                                 if (smum_send_msg_to_smc_with_parameter(
365                                                 hwmgr->smumgr, msg, value))
366                                         return -EINVAL;
367                         }
368                         break;
369
370                 case PP_BLOCK_SYS_DRM:
371                         if (PP_STATE_SUPPORT_CG & *msg_id) {
372                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
373                                                 PPSMC_MSG_EnableClockGatingFeature :
374                                                 PPSMC_MSG_DisableClockGatingFeature;
375                                 value = CG_SYS_DRM_MGCG_MASK;
376
377                                 if (smum_send_msg_to_smc_with_parameter(
378                                                 hwmgr->smumgr, msg, value))
379                                         return -EINVAL;
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_DRM_MGLS_MASK;
386
387                                 if (smum_send_msg_to_smc_with_parameter(
388                                                 hwmgr->smumgr, msg, value))
389                                         return -EINVAL;
390                         }
391                         break;
392
393                 case PP_BLOCK_SYS_HDP:
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_HDP_MGCG_MASK;
399
400                                 if (smum_send_msg_to_smc_with_parameter(
401                                                 hwmgr->smumgr, msg, value))
402                                         return -EINVAL;
403                         }
404
405                         if (PP_STATE_SUPPORT_LS & *msg_id) {
406                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
407                                                 PPSMC_MSG_EnableClockGatingFeature :
408                                                 PPSMC_MSG_DisableClockGatingFeature;
409                                 value = CG_SYS_HDP_MGLS_MASK;
410
411                                 if (smum_send_msg_to_smc_with_parameter(
412                                                 hwmgr->smumgr, msg, value))
413                                         return -EINVAL;
414                         }
415                         break;
416
417                 case PP_BLOCK_SYS_SDMA:
418                         if (PP_STATE_SUPPORT_CG & *msg_id) {
419                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
420                                                 PPSMC_MSG_EnableClockGatingFeature :
421                                                 PPSMC_MSG_DisableClockGatingFeature;
422                                 value = CG_SYS_SDMA_MGCG_MASK;
423
424                                 if (smum_send_msg_to_smc_with_parameter(
425                                                 hwmgr->smumgr, msg, value))
426                                         return -EINVAL;
427                         }
428
429                         if (PP_STATE_SUPPORT_LS & *msg_id) {
430                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
431                                                 PPSMC_MSG_EnableClockGatingFeature :
432                                                 PPSMC_MSG_DisableClockGatingFeature;
433                                 value = CG_SYS_SDMA_MGLS_MASK;
434
435                                 if (smum_send_msg_to_smc_with_parameter(
436                                                 hwmgr->smumgr, msg, value))
437                                         return -EINVAL;
438                         }
439                         break;
440
441                 case PP_BLOCK_SYS_ROM:
442                         if (PP_STATE_SUPPORT_CG & *msg_id) {
443                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
444                                                 PPSMC_MSG_EnableClockGatingFeature :
445                                                 PPSMC_MSG_DisableClockGatingFeature;
446                                 value = CG_SYS_ROM_MASK;
447
448                                 if (smum_send_msg_to_smc_with_parameter(
449                                                 hwmgr->smumgr, msg, value))
450                                         return -EINVAL;
451                         }
452                         break;
453
454                 default:
455                         return -EINVAL;
456
457                 }
458                 break;
459
460         default:
461                 return -EINVAL;
462
463         }
464
465         return 0;
466 }
467
468 /* This function is for Polaris11 only for now,
469  * Powerplay will only control the static per CU Power Gating.
470  * Dynamic per CU Power Gating will be done in gfx.
471  */
472 int smu7_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable)
473 {
474         struct cgs_system_info sys_info = {0};
475         uint32_t active_cus;
476         int result;
477
478         sys_info.size = sizeof(struct cgs_system_info);
479         sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
480
481         result = cgs_query_system_info(hwmgr->device, &sys_info);
482
483         if (result)
484                 return -EINVAL;
485
486         active_cus = sys_info.value;
487
488         if (enable)
489                 return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
490                                 PPSMC_MSG_GFX_CU_PG_ENABLE, active_cus);
491         else
492                 return smum_send_msg_to_smc(hwmgr->smumgr,
493                                 PPSMC_MSG_GFX_CU_PG_DISABLE);
494 }