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