Merge remote-tracking branch 'asoc/fix/intel' into asoc-linus
[cascardo/linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / tonga_clockpowergating.c
1 /*
2  * Copyright 2015 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 "hwmgr.h"
25 #include "tonga_clockpowergating.h"
26 #include "tonga_ppsmc.h"
27 #include "tonga_hwmgr.h"
28
29 int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
30 {
31         if (phm_cf_want_uvd_power_gating(hwmgr))
32                 return smum_send_msg_to_smc(hwmgr->smumgr,
33                                                      PPSMC_MSG_UVDPowerOFF);
34         return 0;
35 }
36
37 int tonga_phm_powerup_uvd(struct pp_hwmgr *hwmgr)
38 {
39         if (phm_cf_want_uvd_power_gating(hwmgr)) {
40                 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
41                                   PHM_PlatformCaps_UVDDynamicPowerGating)) {
42                         return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
43                                                                 PPSMC_MSG_UVDPowerON, 1);
44                 } else {
45                         return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
46                                                                 PPSMC_MSG_UVDPowerON, 0);
47                 }
48         }
49
50         return 0;
51 }
52
53 int tonga_phm_powerdown_vce(struct pp_hwmgr *hwmgr)
54 {
55         if (phm_cf_want_vce_power_gating(hwmgr))
56                 return smum_send_msg_to_smc(hwmgr->smumgr,
57                                                   PPSMC_MSG_VCEPowerOFF);
58         return 0;
59 }
60
61 int tonga_phm_powerup_vce(struct pp_hwmgr *hwmgr)
62 {
63         if (phm_cf_want_vce_power_gating(hwmgr))
64                 return smum_send_msg_to_smc(hwmgr->smumgr,
65                                                   PPSMC_MSG_VCEPowerON);
66         return 0;
67 }
68
69 int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
70 {
71         int ret = 0;
72
73         switch (block) {
74         case PHM_AsicBlock_UVD_MVC:
75         case PHM_AsicBlock_UVD:
76         case PHM_AsicBlock_UVD_HD:
77         case PHM_AsicBlock_UVD_SD:
78                 if (gating == PHM_ClockGateSetting_StaticOff)
79                         ret = tonga_phm_powerdown_uvd(hwmgr);
80                 else
81                         ret = tonga_phm_powerup_uvd(hwmgr);
82                 break;
83         case PHM_AsicBlock_GFX:
84         default:
85                 break;
86         }
87
88         return ret;
89 }
90
91 int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
92 {
93         struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
94
95         data->uvd_power_gated = false;
96         data->vce_power_gated = false;
97
98         tonga_phm_powerup_uvd(hwmgr);
99         tonga_phm_powerup_vce(hwmgr);
100
101         return 0;
102 }
103
104 int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
105 {
106         struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
107
108         if (data->uvd_power_gated == bgate)
109                 return 0;
110
111         data->uvd_power_gated = bgate;
112
113         if (bgate) {
114                 cgs_set_clockgating_state(hwmgr->device,
115                                                 AMD_IP_BLOCK_TYPE_UVD,
116                                                 AMD_CG_STATE_UNGATE);
117                 cgs_set_powergating_state(hwmgr->device,
118                                                 AMD_IP_BLOCK_TYPE_UVD,
119                                                 AMD_PG_STATE_GATE);
120                 tonga_update_uvd_dpm(hwmgr, true);
121                 tonga_phm_powerdown_uvd(hwmgr);
122         } else {
123                 tonga_phm_powerup_uvd(hwmgr);
124                 cgs_set_powergating_state(hwmgr->device,
125                                                 AMD_IP_BLOCK_TYPE_UVD,
126                                                 AMD_PG_STATE_UNGATE);
127                 cgs_set_clockgating_state(hwmgr->device,
128                                                 AMD_IP_BLOCK_TYPE_UVD,
129                                                 AMD_PG_STATE_GATE);
130
131                 tonga_update_uvd_dpm(hwmgr, false);
132         }
133
134         return 0;
135 }
136
137 int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
138 {
139         struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
140         struct phm_set_power_state_input states;
141         const struct pp_power_state  *pcurrent;
142         struct pp_power_state  *requested;
143
144         pcurrent = hwmgr->current_ps;
145         requested = hwmgr->request_ps;
146
147         states.pcurrent_state = &(pcurrent->hardware);
148         states.pnew_state = &(requested->hardware);
149
150         if (phm_cf_want_vce_power_gating(hwmgr)) {
151                 if (data->vce_power_gated != bgate) {
152                         if (bgate) {
153                                 cgs_set_clockgating_state(
154                                                         hwmgr->device,
155                                                         AMD_IP_BLOCK_TYPE_VCE,
156                                                         AMD_CG_STATE_UNGATE);
157                                 cgs_set_powergating_state(
158                                                         hwmgr->device,
159                                                         AMD_IP_BLOCK_TYPE_VCE,
160                                                         AMD_PG_STATE_GATE);
161                                 tonga_enable_disable_vce_dpm(hwmgr, false);
162                                 data->vce_power_gated = true;
163                         } else {
164                                 tonga_phm_powerup_vce(hwmgr);
165                                 data->vce_power_gated = false;
166                                 cgs_set_powergating_state(
167                                                         hwmgr->device,
168                                                         AMD_IP_BLOCK_TYPE_VCE,
169                                                         AMD_PG_STATE_UNGATE);
170                                 cgs_set_clockgating_state(
171                                                         hwmgr->device,
172                                                         AMD_IP_BLOCK_TYPE_VCE,
173                                                         AMD_PG_STATE_GATE);
174
175                                 tonga_update_vce_dpm(hwmgr, &states);
176                                 tonga_enable_disable_vce_dpm(hwmgr, true);
177                                 return 0;
178                         }
179                 }
180         } else {
181                 tonga_update_vce_dpm(hwmgr, &states);
182                 tonga_enable_disable_vce_dpm(hwmgr, true);
183                 return 0;
184         }
185
186         if (!data->vce_power_gated)
187                 tonga_update_vce_dpm(hwmgr, &states);
188
189         return 0;
190 }
191
192 int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
193                                         const uint32_t *msg_id)
194 {
195         PPSMC_Msg msg;
196         uint32_t value;
197
198         switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
199         case PP_GROUP_GFX:
200                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
201                 case PP_BLOCK_GFX_CG:
202                         if (PP_STATE_SUPPORT_CG & *msg_id) {
203                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
204                                   ? PPSMC_MSG_EnableClockGatingFeature
205                                   : PPSMC_MSG_DisableClockGatingFeature;
206                                 value = CG_GFX_CGCG_MASK;
207
208                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
209                                         return -1;
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_CGLS_MASK;
216
217                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
218                                         return -1;
219                         }
220                         break;
221
222                 case PP_BLOCK_GFX_MG:
223                         /* For GFX MGCG, there are three different ones;
224                          * CPF, RLC, and all others.  CPF MGCG will not be used for Tonga.
225                          * For GFX MGLS, Tonga will not support it.
226                          * */
227                         if (PP_STATE_SUPPORT_CG & *msg_id) {
228                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
229                                 ? PPSMC_MSG_EnableClockGatingFeature
230                                 : PPSMC_MSG_DisableClockGatingFeature;
231                                 value = (CG_RLC_MGCG_MASK | CG_GFX_OTHERS_MGCG_MASK);
232
233                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
234                                         return -1;
235                         }
236                         break;
237
238                 default:
239                         return -1;
240                 }
241                 break;
242
243         case PP_GROUP_SYS:
244                 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
245                 case PP_BLOCK_SYS_BIF:
246                         if (PP_STATE_SUPPORT_LS & *msg_id) {
247                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
248                                 ? PPSMC_MSG_EnableClockGatingFeature
249                                 : PPSMC_MSG_DisableClockGatingFeature;
250                                 value = CG_SYS_BIF_MGLS_MASK;
251
252                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
253                                         return -1;
254                         }
255                         break;
256
257                 case PP_BLOCK_SYS_MC:
258                         if (PP_STATE_SUPPORT_CG & *msg_id) {
259                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
260                                 ? PPSMC_MSG_EnableClockGatingFeature
261                                 : PPSMC_MSG_DisableClockGatingFeature;
262                                 value = CG_SYS_MC_MGCG_MASK;
263
264                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
265                                         return -1;
266                         }
267
268                         if (PP_STATE_SUPPORT_LS & *msg_id) {
269                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
270                                 ? PPSMC_MSG_EnableClockGatingFeature
271                                 : PPSMC_MSG_DisableClockGatingFeature;
272                                 value = CG_SYS_MC_MGLS_MASK;
273
274                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
275                                         return -1;
276
277                         }
278                         break;
279
280                 case PP_BLOCK_SYS_HDP:
281                         if (PP_STATE_SUPPORT_CG & *msg_id) {
282                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
283                                         ? PPSMC_MSG_EnableClockGatingFeature
284                                         : PPSMC_MSG_DisableClockGatingFeature;
285                                 value = CG_SYS_HDP_MGCG_MASK;
286
287                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
288                                         return -1;
289                         }
290
291                         if (PP_STATE_SUPPORT_LS & *msg_id) {
292                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
293                                         ? PPSMC_MSG_EnableClockGatingFeature
294                                         : PPSMC_MSG_DisableClockGatingFeature;
295
296                                 value = CG_SYS_HDP_MGLS_MASK;
297
298                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
299                                         return -1;
300                         }
301                         break;
302
303                 case PP_BLOCK_SYS_SDMA:
304                         if (PP_STATE_SUPPORT_CG & *msg_id) {
305                                 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
306                                 ? PPSMC_MSG_EnableClockGatingFeature
307                                 : PPSMC_MSG_DisableClockGatingFeature;
308                                 value = CG_SYS_SDMA_MGCG_MASK;
309
310                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
311                                         return -1;
312                         }
313
314                         if (PP_STATE_SUPPORT_LS & *msg_id) {
315                                 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
316                                 ? PPSMC_MSG_EnableClockGatingFeature
317                                 : PPSMC_MSG_DisableClockGatingFeature;
318
319                                 value = CG_SYS_SDMA_MGLS_MASK;
320
321                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
322                                         return -1;
323                         }
324                         break;
325
326                 case PP_BLOCK_SYS_ROM:
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_ROM_MASK;
332
333                                 if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
334                                         return -1;
335                         }
336                         break;
337
338                 default:
339                         return -1;
340
341                 }
342                 break;
343
344         default:
345                 return -1;
346
347         }
348
349         return 0;
350 }