Merge tag 'drm-intel-next-fixes-2016-07-25' of git://anongit.freedesktop.org/drm...
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / hwmgr / polaris10_clockpowergating.c
CommitLineData
92c6d645
EH
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
2cc0c0b5 24#include "polaris10_clockpowergating.h"
92c6d645 25
2cc0c0b5 26int polaris10_phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
92c6d645
EH
27{
28 if (phm_cf_want_uvd_power_gating(hwmgr))
29 return smum_send_msg_to_smc(hwmgr->smumgr,
30 PPSMC_MSG_UVDPowerOFF);
31 return 0;
32}
33
2cc0c0b5 34int polaris10_phm_powerup_uvd(struct pp_hwmgr *hwmgr)
92c6d645
EH
35{
36 if (phm_cf_want_uvd_power_gating(hwmgr)) {
37 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
38 PHM_PlatformCaps_UVDDynamicPowerGating)) {
39 return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
40 PPSMC_MSG_UVDPowerON, 1);
41 } else {
42 return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
43 PPSMC_MSG_UVDPowerON, 0);
44 }
45 }
46
47 return 0;
48}
49
2cc0c0b5 50int polaris10_phm_powerdown_vce(struct pp_hwmgr *hwmgr)
92c6d645
EH
51{
52 if (phm_cf_want_vce_power_gating(hwmgr))
53 return smum_send_msg_to_smc(hwmgr->smumgr,
54 PPSMC_MSG_VCEPowerOFF);
55 return 0;
56}
57
2cc0c0b5 58int polaris10_phm_powerup_vce(struct pp_hwmgr *hwmgr)
92c6d645
EH
59{
60 if (phm_cf_want_vce_power_gating(hwmgr))
61 return smum_send_msg_to_smc(hwmgr->smumgr,
62 PPSMC_MSG_VCEPowerON);
63 return 0;
64}
65
2cc0c0b5 66int polaris10_phm_powerdown_samu(struct pp_hwmgr *hwmgr)
92c6d645
EH
67{
68 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
69 PHM_PlatformCaps_SamuPowerGating))
70 return smum_send_msg_to_smc(hwmgr->smumgr,
71 PPSMC_MSG_SAMPowerOFF);
72 return 0;
73}
74
2cc0c0b5 75int polaris10_phm_powerup_samu(struct pp_hwmgr *hwmgr)
92c6d645
EH
76{
77 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
78 PHM_PlatformCaps_SamuPowerGating))
79 return smum_send_msg_to_smc(hwmgr->smumgr,
80 PPSMC_MSG_SAMPowerON);
81 return 0;
82}
83
2cc0c0b5 84int polaris10_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
92c6d645 85{
2cc0c0b5 86 struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
92c6d645
EH
87
88 data->uvd_power_gated = false;
89 data->vce_power_gated = false;
90 data->samu_power_gated = false;
91
2cc0c0b5
FC
92 polaris10_phm_powerup_uvd(hwmgr);
93 polaris10_phm_powerup_vce(hwmgr);
94 polaris10_phm_powerup_samu(hwmgr);
92c6d645
EH
95
96 return 0;
97}
98
2cc0c0b5 99int polaris10_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
92c6d645 100{
2cc0c0b5 101 struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
92c6d645
EH
102
103 if (data->uvd_power_gated == bgate)
104 return 0;
105
106 data->uvd_power_gated = bgate;
107
108 if (bgate) {
840dd4c6
EH
109 cgs_set_clockgating_state(hwmgr->device,
110 AMD_IP_BLOCK_TYPE_UVD,
111 AMD_CG_STATE_GATE);
2cc0c0b5
FC
112 polaris10_update_uvd_dpm(hwmgr, true);
113 polaris10_phm_powerdown_uvd(hwmgr);
92c6d645 114 } else {
2cc0c0b5
FC
115 polaris10_phm_powerup_uvd(hwmgr);
116 polaris10_update_uvd_dpm(hwmgr, false);
840dd4c6
EH
117 cgs_set_clockgating_state(hwmgr->device,
118 AMD_IP_BLOCK_TYPE_UVD,
119 AMD_PG_STATE_UNGATE);
92c6d645
EH
120 }
121
122 return 0;
123}
124
2cc0c0b5 125int polaris10_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
92c6d645 126{
2cc0c0b5 127 struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
92c6d645
EH
128
129 if (data->vce_power_gated == bgate)
130 return 0;
131
b0d11345
RZ
132 data->vce_power_gated = bgate;
133
92c6d645 134 if (bgate)
2cc0c0b5 135 polaris10_phm_powerdown_vce(hwmgr);
92c6d645 136 else
2cc0c0b5 137 polaris10_phm_powerup_vce(hwmgr);
92c6d645
EH
138
139 return 0;
140}
141
2cc0c0b5 142int polaris10_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
92c6d645 143{
2cc0c0b5 144 struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
92c6d645
EH
145
146 if (data->samu_power_gated == bgate)
147 return 0;
148
149 data->samu_power_gated = bgate;
150
151 if (bgate) {
2cc0c0b5
FC
152 polaris10_update_samu_dpm(hwmgr, true);
153 polaris10_phm_powerdown_samu(hwmgr);
92c6d645 154 } else {
2cc0c0b5
FC
155 polaris10_phm_powerup_samu(hwmgr);
156 polaris10_update_samu_dpm(hwmgr, false);
92c6d645
EH
157 }
158
159 return 0;
160}
161
2cc0c0b5 162int polaris10_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
8fe3d333
EH
163 const uint32_t *msg_id)
164{
165 PPSMC_Msg msg;
166 uint32_t value;
167
168 switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
169 case PP_GROUP_GFX:
170 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
171 case PP_BLOCK_GFX_CG:
172 if (PP_STATE_SUPPORT_CG & *msg_id) {
173 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
174 PPSMC_MSG_EnableClockGatingFeature :
175 PPSMC_MSG_DisableClockGatingFeature;
176 value = CG_GFX_CGCG_MASK;
177
178 if (smum_send_msg_to_smc_with_parameter(
179 hwmgr->smumgr, msg, value))
180 return -1;
181 }
182 if (PP_STATE_SUPPORT_LS & *msg_id) {
183 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
184 ? PPSMC_MSG_EnableClockGatingFeature
185 : PPSMC_MSG_DisableClockGatingFeature;
186 value = CG_GFX_CGLS_MASK;
187
188 if (smum_send_msg_to_smc_with_parameter(
189 hwmgr->smumgr, msg, value))
190 return -1;
191 }
192 break;
193
194 case PP_BLOCK_GFX_3D:
195 if (PP_STATE_SUPPORT_CG & *msg_id) {
196 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
197 PPSMC_MSG_EnableClockGatingFeature :
198 PPSMC_MSG_DisableClockGatingFeature;
199 value = CG_GFX_3DCG_MASK;
200
201 if (smum_send_msg_to_smc_with_parameter(
202 hwmgr->smumgr, msg, value))
203 return -1;
204 }
205
206 if (PP_STATE_SUPPORT_LS & *msg_id) {
207 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
208 PPSMC_MSG_EnableClockGatingFeature :
209 PPSMC_MSG_DisableClockGatingFeature;
210 value = CG_GFX_3DLS_MASK;
211
212 if (smum_send_msg_to_smc_with_parameter(
213 hwmgr->smumgr, msg, value))
214 return -1;
215 }
216 break;
217
218 case PP_BLOCK_GFX_RLC:
219 if (PP_STATE_SUPPORT_LS & *msg_id) {
220 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
221 PPSMC_MSG_EnableClockGatingFeature :
222 PPSMC_MSG_DisableClockGatingFeature;
223 value = CG_GFX_RLC_LS_MASK;
224
225 if (smum_send_msg_to_smc_with_parameter(
226 hwmgr->smumgr, msg, value))
227 return -1;
228 }
229 break;
230
231 case PP_BLOCK_GFX_CP:
232 if (PP_STATE_SUPPORT_LS & *msg_id) {
233 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
234 PPSMC_MSG_EnableClockGatingFeature :
235 PPSMC_MSG_DisableClockGatingFeature;
236 value = CG_GFX_CP_LS_MASK;
237
238 if (smum_send_msg_to_smc_with_parameter(
239 hwmgr->smumgr, msg, value))
240 return -1;
241 }
242 break;
243
244 case PP_BLOCK_GFX_MG:
245 if (PP_STATE_SUPPORT_CG & *msg_id) {
246 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
247 PPSMC_MSG_EnableClockGatingFeature :
248 PPSMC_MSG_DisableClockGatingFeature;
249 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
250 CG_GFX_OTHERS_MGCG_MASK);
251
252 if (smum_send_msg_to_smc_with_parameter(
253 hwmgr->smumgr, msg, value))
254 return -1;
255 }
256 break;
257
258 default:
259 return -1;
260 }
261 break;
262
263 case PP_GROUP_SYS:
264 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
265 case PP_BLOCK_SYS_BIF:
266 if (PP_STATE_SUPPORT_CG & *msg_id) {
267 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
268 PPSMC_MSG_EnableClockGatingFeature :
269 PPSMC_MSG_DisableClockGatingFeature;
270 value = CG_SYS_BIF_MGCG_MASK;
271
272 if (smum_send_msg_to_smc_with_parameter(
273 hwmgr->smumgr, msg, value))
274 return -1;
275 }
276 if (PP_STATE_SUPPORT_LS & *msg_id) {
277 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
278 PPSMC_MSG_EnableClockGatingFeature :
279 PPSMC_MSG_DisableClockGatingFeature;
280 value = CG_SYS_BIF_MGLS_MASK;
281
282 if (smum_send_msg_to_smc_with_parameter(
283 hwmgr->smumgr, msg, value))
284 return -1;
285 }
286 break;
287
288 case PP_BLOCK_SYS_MC:
289 if (PP_STATE_SUPPORT_CG & *msg_id) {
290 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
291 PPSMC_MSG_EnableClockGatingFeature :
292 PPSMC_MSG_DisableClockGatingFeature;
293 value = CG_SYS_MC_MGCG_MASK;
294
295 if (smum_send_msg_to_smc_with_parameter(
296 hwmgr->smumgr, msg, value))
297 return -1;
298 }
299
300 if (PP_STATE_SUPPORT_LS & *msg_id) {
301 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
302 PPSMC_MSG_EnableClockGatingFeature :
303 PPSMC_MSG_DisableClockGatingFeature;
304 value = CG_SYS_MC_MGLS_MASK;
305
306 if (smum_send_msg_to_smc_with_parameter(
307 hwmgr->smumgr, msg, value))
308 return -1;
309 }
310 break;
311
312 case PP_BLOCK_SYS_DRM:
313 if (PP_STATE_SUPPORT_CG & *msg_id) {
314 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
315 PPSMC_MSG_EnableClockGatingFeature :
316 PPSMC_MSG_DisableClockGatingFeature;
317 value = CG_SYS_DRM_MGCG_MASK;
318
319 if (smum_send_msg_to_smc_with_parameter(
320 hwmgr->smumgr, msg, value))
321 return -1;
322 }
323 if (PP_STATE_SUPPORT_LS & *msg_id) {
324 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
325 PPSMC_MSG_EnableClockGatingFeature :
326 PPSMC_MSG_DisableClockGatingFeature;
327 value = CG_SYS_DRM_MGLS_MASK;
328
329 if (smum_send_msg_to_smc_with_parameter(
330 hwmgr->smumgr, msg, value))
331 return -1;
332 }
333 break;
334
335 case PP_BLOCK_SYS_HDP:
336 if (PP_STATE_SUPPORT_CG & *msg_id) {
337 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
338 PPSMC_MSG_EnableClockGatingFeature :
339 PPSMC_MSG_DisableClockGatingFeature;
340 value = CG_SYS_HDP_MGCG_MASK;
341
342 if (smum_send_msg_to_smc_with_parameter(
343 hwmgr->smumgr, msg, value))
344 return -1;
345 }
346
347 if (PP_STATE_SUPPORT_LS & *msg_id) {
348 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
349 PPSMC_MSG_EnableClockGatingFeature :
350 PPSMC_MSG_DisableClockGatingFeature;
351 value = CG_SYS_HDP_MGLS_MASK;
352
353 if (smum_send_msg_to_smc_with_parameter(
354 hwmgr->smumgr, msg, value))
355 return -1;
356 }
357 break;
358
359 case PP_BLOCK_SYS_SDMA:
360 if (PP_STATE_SUPPORT_CG & *msg_id) {
361 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
362 PPSMC_MSG_EnableClockGatingFeature :
363 PPSMC_MSG_DisableClockGatingFeature;
364 value = CG_SYS_SDMA_MGCG_MASK;
365
366 if (smum_send_msg_to_smc_with_parameter(
367 hwmgr->smumgr, msg, value))
368 return -1;
369 }
370
371 if (PP_STATE_SUPPORT_LS & *msg_id) {
372 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
373 PPSMC_MSG_EnableClockGatingFeature :
374 PPSMC_MSG_DisableClockGatingFeature;
375 value = CG_SYS_SDMA_MGLS_MASK;
376
377 if (smum_send_msg_to_smc_with_parameter(
378 hwmgr->smumgr, msg, value))
379 return -1;
380 }
381 break;
382
383 case PP_BLOCK_SYS_ROM:
384 if (PP_STATE_SUPPORT_CG & *msg_id) {
385 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
386 PPSMC_MSG_EnableClockGatingFeature :
387 PPSMC_MSG_DisableClockGatingFeature;
388 value = CG_SYS_ROM_MASK;
389
390 if (smum_send_msg_to_smc_with_parameter(
391 hwmgr->smumgr, msg, value))
392 return -1;
393 }
394 break;
395
396 default:
397 return -1;
398
399 }
400 break;
401
402 default:
403 return -1;
404
405 }
406
407 return 0;
408}
7df48927 409
2cc0c0b5 410/* This function is for Polaris11 only for now,
7df48927
EH
411 * Powerplay will only control the static per CU Power Gating.
412 * Dynamic per CU Power Gating will be done in gfx.
413 */
2cc0c0b5 414int polaris10_phm_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable)
7df48927
EH
415{
416 struct cgs_system_info sys_info = {0};
417 uint32_t active_cus;
418 int result;
419
420 sys_info.size = sizeof(struct cgs_system_info);
421 sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
422
423 result = cgs_query_system_info(hwmgr->device, &sys_info);
424
425 if (result)
426 return -EINVAL;
427 else
428 active_cus = sys_info.value;
429
430 if (enable)
431 return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
432 PPSMC_MSG_GFX_CU_PG_ENABLE, active_cus);
433 else
434 return smum_send_msg_to_smc(hwmgr->smumgr,
435 PPSMC_MSG_GFX_CU_PG_DISABLE);
436}