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