drm/amd/pm: correct Polaris powertune table setup
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / pm / 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                         NULL);
34 }
35
36 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
37 {
38         return smum_send_msg_to_smc(hwmgr, enable ?
39                         PPSMC_MSG_VCEDPM_Enable :
40                         PPSMC_MSG_VCEDPM_Disable,
41                         NULL);
42 }
43
44 static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
45 {
46         if (!bgate)
47                 smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
48         return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
49 }
50
51 static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
52 {
53         if (!bgate)
54                 smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
55         return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
56 }
57
58 int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
59 {
60         if (phm_cf_want_uvd_power_gating(hwmgr))
61                 return smum_send_msg_to_smc(hwmgr,
62                                 PPSMC_MSG_UVDPowerOFF,
63                                 NULL);
64         return 0;
65 }
66
67 static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
68 {
69         if (phm_cf_want_uvd_power_gating(hwmgr)) {
70                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
71                                   PHM_PlatformCaps_UVDDynamicPowerGating)) {
72                         return smum_send_msg_to_smc_with_parameter(hwmgr,
73                                         PPSMC_MSG_UVDPowerON, 1, NULL);
74                 } else {
75                         return smum_send_msg_to_smc_with_parameter(hwmgr,
76                                         PPSMC_MSG_UVDPowerON, 0, NULL);
77                 }
78         }
79
80         return 0;
81 }
82
83 static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
84 {
85         if (phm_cf_want_vce_power_gating(hwmgr))
86                 return smum_send_msg_to_smc(hwmgr,
87                                 PPSMC_MSG_VCEPowerOFF,
88                                 NULL);
89         return 0;
90 }
91
92 static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
93 {
94         if (phm_cf_want_vce_power_gating(hwmgr))
95                 return smum_send_msg_to_smc(hwmgr,
96                                 PPSMC_MSG_VCEPowerON,
97                                 NULL);
98         return 0;
99 }
100
101 int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
102 {
103         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
104
105         data->uvd_power_gated = false;
106         data->vce_power_gated = false;
107
108         smu7_powerup_uvd(hwmgr);
109         smu7_powerup_vce(hwmgr);
110
111         return 0;
112 }
113
114 void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
115 {
116         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
117
118         data->uvd_power_gated = bgate;
119
120         if (bgate) {
121                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
122                                                 AMD_IP_BLOCK_TYPE_UVD,
123                                                 AMD_PG_STATE_GATE);
124                 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
125                                 AMD_IP_BLOCK_TYPE_UVD,
126                                 AMD_CG_STATE_GATE);
127                 smu7_update_uvd_dpm(hwmgr, true);
128                 smu7_powerdown_uvd(hwmgr);
129         } else {
130                 smu7_powerup_uvd(hwmgr);
131                 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
132                                 AMD_IP_BLOCK_TYPE_UVD,
133                                 AMD_CG_STATE_UNGATE);
134                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
135                                                 AMD_IP_BLOCK_TYPE_UVD,
136                                                 AMD_PG_STATE_UNGATE);
137                 smu7_update_uvd_dpm(hwmgr, false);
138         }
139
140 }
141
142 void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
143 {
144         struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
145
146         data->vce_power_gated = bgate;
147
148         if (bgate) {
149                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
150                                                 AMD_IP_BLOCK_TYPE_VCE,
151                                                 AMD_PG_STATE_GATE);
152                 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
153                                 AMD_IP_BLOCK_TYPE_VCE,
154                                 AMD_CG_STATE_GATE);
155                 smu7_update_vce_dpm(hwmgr, true);
156                 smu7_powerdown_vce(hwmgr);
157         } else {
158                 smu7_powerup_vce(hwmgr);
159                 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
160                                 AMD_IP_BLOCK_TYPE_VCE,
161                                 AMD_CG_STATE_UNGATE);
162                 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
163                                                 AMD_IP_BLOCK_TYPE_VCE,
164                                                 AMD_PG_STATE_UNGATE);
165                 smu7_update_vce_dpm(hwmgr, false);
166         }
167 }
168
169 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         if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
176                 return 0;
177
178         switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
179         case PP_GROUP_GFX:
180                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
181                 case PP_BLOCK_GFX_CG:
182                         if (PP_STATE_SUPPORT_CG & *msg_id) {
183                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
184                                                 PPSMC_MSG_EnableClockGatingFeature :
185                                                 PPSMC_MSG_DisableClockGatingFeature;
186                                 value = CG_GFX_CGCG_MASK;
187
188                                 if (smum_send_msg_to_smc_with_parameter(
189                                                 hwmgr, msg, value, NULL))
190                                         return -EINVAL;
191                         }
192                         if (PP_STATE_SUPPORT_LS & *msg_id) {
193                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
194                                         ? PPSMC_MSG_EnableClockGatingFeature
195                                         : PPSMC_MSG_DisableClockGatingFeature;
196                                 value = CG_GFX_CGLS_MASK;
197
198                                 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                         if (PP_STATE_SUPPORT_CG & *msg_id) {
206                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
207                                                 PPSMC_MSG_EnableClockGatingFeature :
208                                                 PPSMC_MSG_DisableClockGatingFeature;
209                                 value = CG_GFX_3DCG_MASK;
210
211                                 if (smum_send_msg_to_smc_with_parameter(
212                                                 hwmgr, msg, value, NULL))
213                                         return -EINVAL;
214                         }
215
216                         if  (PP_STATE_SUPPORT_LS & *msg_id) {
217                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
218                                                 PPSMC_MSG_EnableClockGatingFeature :
219                                                 PPSMC_MSG_DisableClockGatingFeature;
220                                 value = CG_GFX_3DLS_MASK;
221
222                                 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                         if (PP_STATE_SUPPORT_LS & *msg_id) {
230                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
231                                                 PPSMC_MSG_EnableClockGatingFeature :
232                                                 PPSMC_MSG_DisableClockGatingFeature;
233                                 value = CG_GFX_RLC_LS_MASK;
234
235                                 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                         if (PP_STATE_SUPPORT_LS & *msg_id) {
243                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
244                                                 PPSMC_MSG_EnableClockGatingFeature :
245                                                 PPSMC_MSG_DisableClockGatingFeature;
246                                 value = CG_GFX_CP_LS_MASK;
247
248                                 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                         if (PP_STATE_SUPPORT_CG & *msg_id) {
256                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
257                                                 PPSMC_MSG_EnableClockGatingFeature :
258                                                 PPSMC_MSG_DisableClockGatingFeature;
259                                 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
260                                                 CG_GFX_OTHERS_MGCG_MASK);
261
262                                 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                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
275                 case PP_BLOCK_SYS_BIF:
276                         if (PP_STATE_SUPPORT_CG & *msg_id) {
277                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
278                                                 PPSMC_MSG_EnableClockGatingFeature :
279                                                 PPSMC_MSG_DisableClockGatingFeature;
280                                 value = CG_SYS_BIF_MGCG_MASK;
281
282                                 if (smum_send_msg_to_smc_with_parameter(
283                                                 hwmgr, msg, value, NULL))
284                                         return -EINVAL;
285                         }
286                         if  (PP_STATE_SUPPORT_LS & *msg_id) {
287                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
288                                                 PPSMC_MSG_EnableClockGatingFeature :
289                                                 PPSMC_MSG_DisableClockGatingFeature;
290                                 value = CG_SYS_BIF_MGLS_MASK;
291
292                                 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                         if (PP_STATE_SUPPORT_CG & *msg_id) {
300                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
301                                                 PPSMC_MSG_EnableClockGatingFeature :
302                                                 PPSMC_MSG_DisableClockGatingFeature;
303                                 value = CG_SYS_MC_MGCG_MASK;
304
305                                 if (smum_send_msg_to_smc_with_parameter(
306                                                 hwmgr, msg, value, NULL))
307                                         return -EINVAL;
308                         }
309
310                         if (PP_STATE_SUPPORT_LS & *msg_id) {
311                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
312                                                 PPSMC_MSG_EnableClockGatingFeature :
313                                                 PPSMC_MSG_DisableClockGatingFeature;
314                                 value = CG_SYS_MC_MGLS_MASK;
315
316                                 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                         if (PP_STATE_SUPPORT_CG & *msg_id) {
324                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
325                                                 PPSMC_MSG_EnableClockGatingFeature :
326                                                 PPSMC_MSG_DisableClockGatingFeature;
327                                 value = CG_SYS_DRM_MGCG_MASK;
328
329                                 if (smum_send_msg_to_smc_with_parameter(
330                                                 hwmgr, msg, value, NULL))
331                                         return -EINVAL;
332                         }
333                         if (PP_STATE_SUPPORT_LS & *msg_id) {
334                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
335                                                 PPSMC_MSG_EnableClockGatingFeature :
336                                                 PPSMC_MSG_DisableClockGatingFeature;
337                                 value = CG_SYS_DRM_MGLS_MASK;
338
339                                 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                         if (PP_STATE_SUPPORT_CG & *msg_id) {
347                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
348                                                 PPSMC_MSG_EnableClockGatingFeature :
349                                                 PPSMC_MSG_DisableClockGatingFeature;
350                                 value = CG_SYS_HDP_MGCG_MASK;
351
352                                 if (smum_send_msg_to_smc_with_parameter(
353                                                 hwmgr, msg, value, NULL))
354                                         return -EINVAL;
355                         }
356
357                         if (PP_STATE_SUPPORT_LS & *msg_id) {
358                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
359                                                 PPSMC_MSG_EnableClockGatingFeature :
360                                                 PPSMC_MSG_DisableClockGatingFeature;
361                                 value = CG_SYS_HDP_MGLS_MASK;
362
363                                 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                         if (PP_STATE_SUPPORT_CG & *msg_id) {
371                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
372                                                 PPSMC_MSG_EnableClockGatingFeature :
373                                                 PPSMC_MSG_DisableClockGatingFeature;
374                                 value = CG_SYS_SDMA_MGCG_MASK;
375
376                                 if (smum_send_msg_to_smc_with_parameter(
377                                                 hwmgr, msg, value, NULL))
378                                         return -EINVAL;
379                         }
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_SDMA_MGLS_MASK;
386
387                                 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                         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_ROM_MASK;
399
400                                 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 int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable)
425 {
426         struct amdgpu_device *adev = hwmgr->adev;
427
428         if (enable)
429                 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                 return smum_send_msg_to_smc(hwmgr,
435                                 PPSMC_MSG_GFX_CU_PG_DISABLE,
436                                 NULL);
437 }