GNU Linux-libre 4.14.251-gnu1
[releases.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_PG_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         data->vce_power_gated = bgate;
177
178         if (bgate) {
179                 cgs_set_powergating_state(hwmgr->device,
180                                                 AMD_IP_BLOCK_TYPE_VCE,
181                                                 AMD_PG_STATE_GATE);
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                 cgs_set_clockgating_state(hwmgr->device,
190                                 AMD_IP_BLOCK_TYPE_VCE,
191                                 AMD_CG_STATE_UNGATE);
192                 cgs_set_powergating_state(hwmgr->device,
193                                                 AMD_IP_BLOCK_TYPE_VCE,
194                                                 AMD_PG_STATE_UNGATE);
195                 smu7_update_vce_dpm(hwmgr, false);
196         }
197         return 0;
198 }
199
200 int smu7_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
201 {
202         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
203
204         if (data->samu_power_gated == bgate)
205                 return 0;
206
207         data->samu_power_gated = bgate;
208
209         if (bgate) {
210                 smu7_update_samu_dpm(hwmgr, true);
211                 smu7_powerdown_samu(hwmgr);
212         } else {
213                 smu7_powerup_samu(hwmgr);
214                 smu7_update_samu_dpm(hwmgr, false);
215         }
216
217         return 0;
218 }
219
220 int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
221                                         const uint32_t *msg_id)
222 {
223         PPSMC_Msg msg;
224         uint32_t value;
225
226         if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
227                 return 0;
228
229         switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
230         case PP_GROUP_GFX:
231                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
232                 case PP_BLOCK_GFX_CG:
233                         if (PP_STATE_SUPPORT_CG & *msg_id) {
234                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
235                                                 PPSMC_MSG_EnableClockGatingFeature :
236                                                 PPSMC_MSG_DisableClockGatingFeature;
237                                 value = CG_GFX_CGCG_MASK;
238
239                                 if (smum_send_msg_to_smc_with_parameter(
240                                                 hwmgr->smumgr, msg, value))
241                                         return -EINVAL;
242                         }
243                         if (PP_STATE_SUPPORT_LS & *msg_id) {
244                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
245                                         ? PPSMC_MSG_EnableClockGatingFeature
246                                         : PPSMC_MSG_DisableClockGatingFeature;
247                                 value = CG_GFX_CGLS_MASK;
248
249                                 if (smum_send_msg_to_smc_with_parameter(
250                                                 hwmgr->smumgr, msg, value))
251                                         return -EINVAL;
252                         }
253                         break;
254
255                 case PP_BLOCK_GFX_3D:
256                         if (PP_STATE_SUPPORT_CG & *msg_id) {
257                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
258                                                 PPSMC_MSG_EnableClockGatingFeature :
259                                                 PPSMC_MSG_DisableClockGatingFeature;
260                                 value = CG_GFX_3DCG_MASK;
261
262                                 if (smum_send_msg_to_smc_with_parameter(
263                                                 hwmgr->smumgr, msg, value))
264                                         return -EINVAL;
265                         }
266
267                         if  (PP_STATE_SUPPORT_LS & *msg_id) {
268                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
269                                                 PPSMC_MSG_EnableClockGatingFeature :
270                                                 PPSMC_MSG_DisableClockGatingFeature;
271                                 value = CG_GFX_3DLS_MASK;
272
273                                 if (smum_send_msg_to_smc_with_parameter(
274                                                 hwmgr->smumgr, msg, value))
275                                         return -EINVAL;
276                         }
277                         break;
278
279                 case PP_BLOCK_GFX_RLC:
280                         if (PP_STATE_SUPPORT_LS & *msg_id) {
281                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
282                                                 PPSMC_MSG_EnableClockGatingFeature :
283                                                 PPSMC_MSG_DisableClockGatingFeature;
284                                 value = CG_GFX_RLC_LS_MASK;
285
286                                 if (smum_send_msg_to_smc_with_parameter(
287                                                 hwmgr->smumgr, msg, value))
288                                         return -EINVAL;
289                         }
290                         break;
291
292                 case PP_BLOCK_GFX_CP:
293                         if (PP_STATE_SUPPORT_LS & *msg_id) {
294                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
295                                                 PPSMC_MSG_EnableClockGatingFeature :
296                                                 PPSMC_MSG_DisableClockGatingFeature;
297                                 value = CG_GFX_CP_LS_MASK;
298
299                                 if (smum_send_msg_to_smc_with_parameter(
300                                                 hwmgr->smumgr, msg, value))
301                                         return -EINVAL;
302                         }
303                         break;
304
305                 case PP_BLOCK_GFX_MG:
306                         if (PP_STATE_SUPPORT_CG & *msg_id) {
307                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
308                                                 PPSMC_MSG_EnableClockGatingFeature :
309                                                 PPSMC_MSG_DisableClockGatingFeature;
310                                 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
311                                                 CG_GFX_OTHERS_MGCG_MASK);
312
313                                 if (smum_send_msg_to_smc_with_parameter(
314                                                 hwmgr->smumgr, msg, value))
315                                         return -EINVAL;
316                         }
317                         break;
318
319                 default:
320                         return -EINVAL;
321                 }
322                 break;
323
324         case PP_GROUP_SYS:
325                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
326                 case PP_BLOCK_SYS_BIF:
327                         if (PP_STATE_SUPPORT_CG & *msg_id) {
328                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
329                                                 PPSMC_MSG_EnableClockGatingFeature :
330                                                 PPSMC_MSG_DisableClockGatingFeature;
331                                 value = CG_SYS_BIF_MGCG_MASK;
332
333                                 if (smum_send_msg_to_smc_with_parameter(
334                                                 hwmgr->smumgr, msg, value))
335                                         return -EINVAL;
336                         }
337                         if  (PP_STATE_SUPPORT_LS & *msg_id) {
338                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
339                                                 PPSMC_MSG_EnableClockGatingFeature :
340                                                 PPSMC_MSG_DisableClockGatingFeature;
341                                 value = CG_SYS_BIF_MGLS_MASK;
342
343                                 if (smum_send_msg_to_smc_with_parameter(
344                                                 hwmgr->smumgr, msg, value))
345                                         return -EINVAL;
346                         }
347                         break;
348
349                 case PP_BLOCK_SYS_MC:
350                         if (PP_STATE_SUPPORT_CG & *msg_id) {
351                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
352                                                 PPSMC_MSG_EnableClockGatingFeature :
353                                                 PPSMC_MSG_DisableClockGatingFeature;
354                                 value = CG_SYS_MC_MGCG_MASK;
355
356                                 if (smum_send_msg_to_smc_with_parameter(
357                                                 hwmgr->smumgr, msg, value))
358                                         return -EINVAL;
359                         }
360
361                         if (PP_STATE_SUPPORT_LS & *msg_id) {
362                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
363                                                 PPSMC_MSG_EnableClockGatingFeature :
364                                                 PPSMC_MSG_DisableClockGatingFeature;
365                                 value = CG_SYS_MC_MGLS_MASK;
366
367                                 if (smum_send_msg_to_smc_with_parameter(
368                                                 hwmgr->smumgr, msg, value))
369                                         return -EINVAL;
370                         }
371                         break;
372
373                 case PP_BLOCK_SYS_DRM:
374                         if (PP_STATE_SUPPORT_CG & *msg_id) {
375                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
376                                                 PPSMC_MSG_EnableClockGatingFeature :
377                                                 PPSMC_MSG_DisableClockGatingFeature;
378                                 value = CG_SYS_DRM_MGCG_MASK;
379
380                                 if (smum_send_msg_to_smc_with_parameter(
381                                                 hwmgr->smumgr, msg, value))
382                                         return -EINVAL;
383                         }
384                         if (PP_STATE_SUPPORT_LS & *msg_id) {
385                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
386                                                 PPSMC_MSG_EnableClockGatingFeature :
387                                                 PPSMC_MSG_DisableClockGatingFeature;
388                                 value = CG_SYS_DRM_MGLS_MASK;
389
390                                 if (smum_send_msg_to_smc_with_parameter(
391                                                 hwmgr->smumgr, msg, value))
392                                         return -EINVAL;
393                         }
394                         break;
395
396                 case PP_BLOCK_SYS_HDP:
397                         if (PP_STATE_SUPPORT_CG & *msg_id) {
398                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
399                                                 PPSMC_MSG_EnableClockGatingFeature :
400                                                 PPSMC_MSG_DisableClockGatingFeature;
401                                 value = CG_SYS_HDP_MGCG_MASK;
402
403                                 if (smum_send_msg_to_smc_with_parameter(
404                                                 hwmgr->smumgr, msg, value))
405                                         return -EINVAL;
406                         }
407
408                         if (PP_STATE_SUPPORT_LS & *msg_id) {
409                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
410                                                 PPSMC_MSG_EnableClockGatingFeature :
411                                                 PPSMC_MSG_DisableClockGatingFeature;
412                                 value = CG_SYS_HDP_MGLS_MASK;
413
414                                 if (smum_send_msg_to_smc_with_parameter(
415                                                 hwmgr->smumgr, msg, value))
416                                         return -EINVAL;
417                         }
418                         break;
419
420                 case PP_BLOCK_SYS_SDMA:
421                         if (PP_STATE_SUPPORT_CG & *msg_id) {
422                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
423                                                 PPSMC_MSG_EnableClockGatingFeature :
424                                                 PPSMC_MSG_DisableClockGatingFeature;
425                                 value = CG_SYS_SDMA_MGCG_MASK;
426
427                                 if (smum_send_msg_to_smc_with_parameter(
428                                                 hwmgr->smumgr, msg, value))
429                                         return -EINVAL;
430                         }
431
432                         if (PP_STATE_SUPPORT_LS & *msg_id) {
433                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
434                                                 PPSMC_MSG_EnableClockGatingFeature :
435                                                 PPSMC_MSG_DisableClockGatingFeature;
436                                 value = CG_SYS_SDMA_MGLS_MASK;
437
438                                 if (smum_send_msg_to_smc_with_parameter(
439                                                 hwmgr->smumgr, msg, value))
440                                         return -EINVAL;
441                         }
442                         break;
443
444                 case PP_BLOCK_SYS_ROM:
445                         if (PP_STATE_SUPPORT_CG & *msg_id) {
446                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
447                                                 PPSMC_MSG_EnableClockGatingFeature :
448                                                 PPSMC_MSG_DisableClockGatingFeature;
449                                 value = CG_SYS_ROM_MASK;
450
451                                 if (smum_send_msg_to_smc_with_parameter(
452                                                 hwmgr->smumgr, msg, value))
453                                         return -EINVAL;
454                         }
455                         break;
456
457                 default:
458                         return -EINVAL;
459
460                 }
461                 break;
462
463         default:
464                 return -EINVAL;
465
466         }
467
468         return 0;
469 }
470
471 /* This function is for Polaris11 only for now,
472  * Powerplay will only control the static per CU Power Gating.
473  * Dynamic per CU Power Gating will be done in gfx.
474  */
475 int smu7_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable)
476 {
477         struct cgs_system_info sys_info = {0};
478         uint32_t active_cus;
479         int result;
480
481         sys_info.size = sizeof(struct cgs_system_info);
482         sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
483
484         result = cgs_query_system_info(hwmgr->device, &sys_info);
485
486         if (result)
487                 return -EINVAL;
488
489         active_cus = sys_info.value;
490
491         if (enable)
492                 return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
493                                 PPSMC_MSG_GFX_CU_PG_ENABLE, active_cus);
494         else
495                 return smum_send_msg_to_smc(hwmgr->smumgr,
496                                 PPSMC_MSG_GFX_CU_PG_DISABLE);
497 }