]>
Commit | Line | Data |
---|---|---|
1f7371b2 AD |
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 | #include <linux/types.h> | |
24 | #include <linux/kernel.h> | |
25 | #include <linux/gfp.h> | |
ac885b3a | 26 | #include <linux/slab.h> |
1f7371b2 AD |
27 | #include "amd_shared.h" |
28 | #include "amd_powerplay.h" | |
ac885b3a | 29 | #include "pp_instance.h" |
577bbe01 RZ |
30 | #include "power_state.h" |
31 | #include "eventmanager.h" | |
e273b041 | 32 | #include "pp_debug.h" |
1f7371b2 | 33 | |
af223dfa | 34 | |
a969e163 RZ |
35 | #define PP_CHECK(handle) \ |
36 | do { \ | |
37 | if ((handle) == NULL || (handle)->pp_valid != PP_VALID) \ | |
38 | return -EINVAL; \ | |
39 | } while (0) | |
40 | ||
7383bcb9 RZ |
41 | #define PP_CHECK_HW(hwmgr) \ |
42 | do { \ | |
43 | if ((hwmgr) == NULL || (hwmgr)->hwmgr_func == NULL) \ | |
ba5f884c | 44 | return 0; \ |
7383bcb9 RZ |
45 | } while (0) |
46 | ||
1f7371b2 AD |
47 | static int pp_early_init(void *handle) |
48 | { | |
49 | return 0; | |
50 | } | |
51 | ||
52 | static int pp_sw_init(void *handle) | |
53 | { | |
3bace359 JZ |
54 | struct pp_instance *pp_handle; |
55 | struct pp_hwmgr *hwmgr; | |
56 | int ret = 0; | |
57 | ||
58 | if (handle == NULL) | |
59 | return -EINVAL; | |
60 | ||
61 | pp_handle = (struct pp_instance *)handle; | |
62 | hwmgr = pp_handle->hwmgr; | |
63 | ||
7383bcb9 RZ |
64 | PP_CHECK_HW(hwmgr); |
65 | ||
66 | if (hwmgr->pptable_func == NULL || | |
3bace359 JZ |
67 | hwmgr->pptable_func->pptable_init == NULL || |
68 | hwmgr->hwmgr_func->backend_init == NULL) | |
69 | return -EINVAL; | |
70 | ||
71 | ret = hwmgr->pptable_func->pptable_init(hwmgr); | |
b4eeed59 HR |
72 | if (ret) |
73 | goto err; | |
e92a0370 | 74 | |
b4eeed59 | 75 | ret = hwmgr->hwmgr_func->backend_init(hwmgr); |
9441f964 | 76 | if (ret) |
9d8f086c | 77 | goto err1; |
9441f964 | 78 | |
b4eeed59 HR |
79 | pr_info("amdgpu: powerplay initialized\n"); |
80 | ||
81 | return 0; | |
9d8f086c ML |
82 | err1: |
83 | if (hwmgr->pptable_func->pptable_fini) | |
84 | hwmgr->pptable_func->pptable_fini(hwmgr); | |
b4eeed59 HR |
85 | err: |
86 | pr_err("amdgpu: powerplay initialization failed\n"); | |
3bace359 | 87 | return ret; |
1f7371b2 AD |
88 | } |
89 | ||
90 | static int pp_sw_fini(void *handle) | |
91 | { | |
3bace359 JZ |
92 | struct pp_instance *pp_handle; |
93 | struct pp_hwmgr *hwmgr; | |
94 | int ret = 0; | |
95 | ||
96 | if (handle == NULL) | |
97 | return -EINVAL; | |
98 | ||
99 | pp_handle = (struct pp_instance *)handle; | |
100 | hwmgr = pp_handle->hwmgr; | |
101 | ||
7383bcb9 RZ |
102 | PP_CHECK_HW(hwmgr); |
103 | ||
104 | if (hwmgr->hwmgr_func->backend_fini != NULL) | |
3bace359 JZ |
105 | ret = hwmgr->hwmgr_func->backend_fini(hwmgr); |
106 | ||
9d8f086c ML |
107 | if (hwmgr->pptable_func->pptable_fini) |
108 | hwmgr->pptable_func->pptable_fini(hwmgr); | |
109 | ||
3bace359 | 110 | return ret; |
1f7371b2 AD |
111 | } |
112 | ||
113 | static int pp_hw_init(void *handle) | |
114 | { | |
ac885b3a JZ |
115 | struct pp_instance *pp_handle; |
116 | struct pp_smumgr *smumgr; | |
e92a0370 | 117 | struct pp_eventmgr *eventmgr; |
ba5f884c | 118 | struct pp_hwmgr *hwmgr; |
ac885b3a JZ |
119 | int ret = 0; |
120 | ||
121 | if (handle == NULL) | |
122 | return -EINVAL; | |
123 | ||
124 | pp_handle = (struct pp_instance *)handle; | |
125 | smumgr = pp_handle->smu_mgr; | |
ba5f884c | 126 | hwmgr = pp_handle->hwmgr; |
ac885b3a JZ |
127 | |
128 | if (smumgr == NULL || smumgr->smumgr_funcs == NULL || | |
129 | smumgr->smumgr_funcs->smu_init == NULL || | |
130 | smumgr->smumgr_funcs->start_smu == NULL) | |
131 | return -EINVAL; | |
132 | ||
133 | ret = smumgr->smumgr_funcs->smu_init(smumgr); | |
134 | if (ret) { | |
135 | printk(KERN_ERR "[ powerplay ] smc initialization failed\n"); | |
136 | return ret; | |
137 | } | |
138 | ||
139 | ret = smumgr->smumgr_funcs->start_smu(smumgr); | |
140 | if (ret) { | |
141 | printk(KERN_ERR "[ powerplay ] smc start failed\n"); | |
142 | smumgr->smumgr_funcs->smu_fini(smumgr); | |
143 | return ret; | |
144 | } | |
e92a0370 | 145 | |
ba5f884c | 146 | PP_CHECK_HW(hwmgr); |
3bace359 | 147 | |
ba5f884c RZ |
148 | hw_init_power_state_table(hwmgr); |
149 | ||
150 | eventmgr = pp_handle->eventmgr; | |
e92a0370 RZ |
151 | if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL) |
152 | return -EINVAL; | |
153 | ||
154 | ret = eventmgr->pp_eventmgr_init(eventmgr); | |
1f7371b2 AD |
155 | return 0; |
156 | } | |
157 | ||
158 | static int pp_hw_fini(void *handle) | |
159 | { | |
ac885b3a JZ |
160 | struct pp_instance *pp_handle; |
161 | struct pp_smumgr *smumgr; | |
e92a0370 | 162 | struct pp_eventmgr *eventmgr; |
ac885b3a JZ |
163 | |
164 | if (handle == NULL) | |
165 | return -EINVAL; | |
166 | ||
167 | pp_handle = (struct pp_instance *)handle; | |
e92a0370 RZ |
168 | eventmgr = pp_handle->eventmgr; |
169 | ||
d36f3e04 | 170 | if (eventmgr != NULL && eventmgr->pp_eventmgr_fini != NULL) |
e92a0370 RZ |
171 | eventmgr->pp_eventmgr_fini(eventmgr); |
172 | ||
ac885b3a JZ |
173 | smumgr = pp_handle->smu_mgr; |
174 | ||
d36f3e04 | 175 | if (smumgr != NULL && smumgr->smumgr_funcs != NULL && |
ac885b3a JZ |
176 | smumgr->smumgr_funcs->smu_fini != NULL) |
177 | smumgr->smumgr_funcs->smu_fini(smumgr); | |
178 | ||
1f7371b2 AD |
179 | return 0; |
180 | } | |
181 | ||
182 | static bool pp_is_idle(void *handle) | |
183 | { | |
ed5121a3 | 184 | return false; |
1f7371b2 AD |
185 | } |
186 | ||
187 | static int pp_wait_for_idle(void *handle) | |
188 | { | |
189 | return 0; | |
190 | } | |
191 | ||
192 | static int pp_sw_reset(void *handle) | |
193 | { | |
194 | return 0; | |
195 | } | |
196 | ||
1f7371b2 | 197 | |
465f96e2 | 198 | int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id) |
1f7371b2 | 199 | { |
03e3905f | 200 | struct pp_hwmgr *hwmgr; |
03e3905f EH |
201 | |
202 | if (handle == NULL) | |
203 | return -EINVAL; | |
204 | ||
205 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
206 | ||
7383bcb9 | 207 | PP_CHECK_HW(hwmgr); |
03e3905f | 208 | |
7383bcb9 RZ |
209 | if (hwmgr->hwmgr_func->update_clock_gatings == NULL) { |
210 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
538333f0 | 211 | return 0; |
7383bcb9 | 212 | } |
538333f0 | 213 | |
465f96e2 | 214 | return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id); |
1f7371b2 AD |
215 | } |
216 | ||
217 | static int pp_set_powergating_state(void *handle, | |
218 | enum amd_powergating_state state) | |
219 | { | |
65f85e7d EH |
220 | struct pp_hwmgr *hwmgr; |
221 | ||
222 | if (handle == NULL) | |
223 | return -EINVAL; | |
224 | ||
225 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
226 | ||
7383bcb9 RZ |
227 | PP_CHECK_HW(hwmgr); |
228 | ||
229 | if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) { | |
230 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
231 | return 0; | |
232 | } | |
65f85e7d EH |
233 | |
234 | /* Enable/disable GFX per cu powergating through SMU */ | |
235 | return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr, | |
236 | state == AMD_PG_STATE_GATE ? true : false); | |
1f7371b2 AD |
237 | } |
238 | ||
239 | static int pp_suspend(void *handle) | |
240 | { | |
577bbe01 RZ |
241 | struct pp_instance *pp_handle; |
242 | struct pp_eventmgr *eventmgr; | |
243 | struct pem_event_data event_data = { {0} }; | |
244 | ||
245 | if (handle == NULL) | |
246 | return -EINVAL; | |
247 | ||
248 | pp_handle = (struct pp_instance *)handle; | |
249 | eventmgr = pp_handle->eventmgr; | |
ba5f884c RZ |
250 | |
251 | if (eventmgr != NULL) | |
252 | pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data); | |
1f7371b2 AD |
253 | return 0; |
254 | } | |
255 | ||
256 | static int pp_resume(void *handle) | |
257 | { | |
577bbe01 RZ |
258 | struct pp_instance *pp_handle; |
259 | struct pp_eventmgr *eventmgr; | |
260 | struct pem_event_data event_data = { {0} }; | |
e0b71a7e RZ |
261 | struct pp_smumgr *smumgr; |
262 | int ret; | |
577bbe01 RZ |
263 | |
264 | if (handle == NULL) | |
265 | return -EINVAL; | |
266 | ||
267 | pp_handle = (struct pp_instance *)handle; | |
e0b71a7e RZ |
268 | smumgr = pp_handle->smu_mgr; |
269 | ||
270 | if (smumgr == NULL || smumgr->smumgr_funcs == NULL || | |
271 | smumgr->smumgr_funcs->start_smu == NULL) | |
272 | return -EINVAL; | |
273 | ||
274 | ret = smumgr->smumgr_funcs->start_smu(smumgr); | |
275 | if (ret) { | |
276 | printk(KERN_ERR "[ powerplay ] smc start failed\n"); | |
277 | smumgr->smumgr_funcs->smu_fini(smumgr); | |
278 | return ret; | |
279 | } | |
280 | ||
577bbe01 | 281 | eventmgr = pp_handle->eventmgr; |
ba5f884c RZ |
282 | if (eventmgr != NULL) |
283 | pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data); | |
e0b71a7e | 284 | |
1f7371b2 AD |
285 | return 0; |
286 | } | |
287 | ||
288 | const struct amd_ip_funcs pp_ip_funcs = { | |
88a907d6 | 289 | .name = "powerplay", |
1f7371b2 AD |
290 | .early_init = pp_early_init, |
291 | .late_init = NULL, | |
292 | .sw_init = pp_sw_init, | |
293 | .sw_fini = pp_sw_fini, | |
294 | .hw_init = pp_hw_init, | |
295 | .hw_fini = pp_hw_fini, | |
296 | .suspend = pp_suspend, | |
297 | .resume = pp_resume, | |
298 | .is_idle = pp_is_idle, | |
299 | .wait_for_idle = pp_wait_for_idle, | |
300 | .soft_reset = pp_sw_reset, | |
465f96e2 | 301 | .set_clockgating_state = NULL, |
1f7371b2 AD |
302 | .set_powergating_state = pp_set_powergating_state, |
303 | }; | |
304 | ||
305 | static int pp_dpm_load_fw(void *handle) | |
306 | { | |
307 | return 0; | |
308 | } | |
309 | ||
310 | static int pp_dpm_fw_loading_complete(void *handle) | |
311 | { | |
312 | return 0; | |
313 | } | |
314 | ||
315 | static int pp_dpm_force_performance_level(void *handle, | |
316 | enum amd_dpm_forced_level level) | |
317 | { | |
577bbe01 RZ |
318 | struct pp_instance *pp_handle; |
319 | struct pp_hwmgr *hwmgr; | |
320 | ||
321 | if (handle == NULL) | |
322 | return -EINVAL; | |
323 | ||
324 | pp_handle = (struct pp_instance *)handle; | |
325 | ||
326 | hwmgr = pp_handle->hwmgr; | |
327 | ||
7383bcb9 RZ |
328 | PP_CHECK_HW(hwmgr); |
329 | ||
330 | if (hwmgr->hwmgr_func->force_dpm_level == NULL) { | |
331 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
332 | return 0; | |
333 | } | |
577bbe01 RZ |
334 | |
335 | hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); | |
336 | ||
1f7371b2 AD |
337 | return 0; |
338 | } | |
577bbe01 | 339 | |
1f7371b2 AD |
340 | static enum amd_dpm_forced_level pp_dpm_get_performance_level( |
341 | void *handle) | |
342 | { | |
577bbe01 RZ |
343 | struct pp_hwmgr *hwmgr; |
344 | ||
345 | if (handle == NULL) | |
346 | return -EINVAL; | |
347 | ||
348 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
349 | ||
ba5f884c | 350 | PP_CHECK_HW(hwmgr); |
577bbe01 RZ |
351 | |
352 | return (((struct pp_instance *)handle)->hwmgr->dpm_level); | |
1f7371b2 | 353 | } |
577bbe01 | 354 | |
1f7371b2 AD |
355 | static int pp_dpm_get_sclk(void *handle, bool low) |
356 | { | |
577bbe01 RZ |
357 | struct pp_hwmgr *hwmgr; |
358 | ||
359 | if (handle == NULL) | |
360 | return -EINVAL; | |
361 | ||
362 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
363 | ||
7383bcb9 RZ |
364 | PP_CHECK_HW(hwmgr); |
365 | ||
366 | if (hwmgr->hwmgr_func->get_sclk == NULL) { | |
367 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
368 | return 0; | |
369 | } | |
577bbe01 RZ |
370 | |
371 | return hwmgr->hwmgr_func->get_sclk(hwmgr, low); | |
1f7371b2 | 372 | } |
577bbe01 | 373 | |
1f7371b2 AD |
374 | static int pp_dpm_get_mclk(void *handle, bool low) |
375 | { | |
577bbe01 RZ |
376 | struct pp_hwmgr *hwmgr; |
377 | ||
378 | if (handle == NULL) | |
379 | return -EINVAL; | |
380 | ||
381 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
382 | ||
7383bcb9 RZ |
383 | PP_CHECK_HW(hwmgr); |
384 | ||
385 | if (hwmgr->hwmgr_func->get_mclk == NULL) { | |
386 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
387 | return 0; | |
388 | } | |
577bbe01 RZ |
389 | |
390 | return hwmgr->hwmgr_func->get_mclk(hwmgr, low); | |
1f7371b2 | 391 | } |
577bbe01 | 392 | |
1f7371b2 AD |
393 | static int pp_dpm_powergate_vce(void *handle, bool gate) |
394 | { | |
577bbe01 RZ |
395 | struct pp_hwmgr *hwmgr; |
396 | ||
397 | if (handle == NULL) | |
398 | return -EINVAL; | |
399 | ||
400 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
401 | ||
7383bcb9 RZ |
402 | PP_CHECK_HW(hwmgr); |
403 | ||
404 | if (hwmgr->hwmgr_func->powergate_vce == NULL) { | |
405 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
406 | return 0; | |
407 | } | |
577bbe01 RZ |
408 | |
409 | return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); | |
1f7371b2 | 410 | } |
577bbe01 | 411 | |
1f7371b2 AD |
412 | static int pp_dpm_powergate_uvd(void *handle, bool gate) |
413 | { | |
577bbe01 RZ |
414 | struct pp_hwmgr *hwmgr; |
415 | ||
416 | if (handle == NULL) | |
417 | return -EINVAL; | |
418 | ||
419 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
420 | ||
7383bcb9 RZ |
421 | PP_CHECK_HW(hwmgr); |
422 | ||
423 | if (hwmgr->hwmgr_func->powergate_uvd == NULL) { | |
424 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
425 | return 0; | |
426 | } | |
577bbe01 RZ |
427 | |
428 | return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); | |
429 | } | |
430 | ||
431 | static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) | |
432 | { | |
433 | switch (state) { | |
434 | case POWER_STATE_TYPE_BATTERY: | |
435 | return PP_StateUILabel_Battery; | |
436 | case POWER_STATE_TYPE_BALANCED: | |
437 | return PP_StateUILabel_Balanced; | |
438 | case POWER_STATE_TYPE_PERFORMANCE: | |
439 | return PP_StateUILabel_Performance; | |
440 | default: | |
441 | return PP_StateUILabel_None; | |
442 | } | |
1f7371b2 AD |
443 | } |
444 | ||
f8a4c11b BX |
445 | static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, |
446 | void *input, void *output) | |
1f7371b2 | 447 | { |
577bbe01 RZ |
448 | int ret = 0; |
449 | struct pp_instance *pp_handle; | |
450 | struct pem_event_data data = { {0} }; | |
451 | ||
452 | pp_handle = (struct pp_instance *)handle; | |
453 | ||
454 | if (pp_handle == NULL) | |
455 | return -EINVAL; | |
456 | ||
ba5f884c RZ |
457 | if (pp_handle->eventmgr == NULL) |
458 | return 0; | |
459 | ||
577bbe01 RZ |
460 | switch (event_id) { |
461 | case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE: | |
462 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); | |
463 | break; | |
464 | case AMD_PP_EVENT_ENABLE_USER_STATE: | |
465 | { | |
466 | enum amd_pm_state_type ps; | |
467 | ||
468 | if (input == NULL) | |
469 | return -EINVAL; | |
470 | ps = *(unsigned long *)input; | |
471 | ||
472 | data.requested_ui_label = power_state_convert(ps); | |
473 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); | |
dc26a2a2 | 474 | break; |
577bbe01 | 475 | } |
dc26a2a2 RZ |
476 | case AMD_PP_EVENT_COMPLETE_INIT: |
477 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); | |
478 | break; | |
428bafa8 | 479 | case AMD_PP_EVENT_READJUST_POWER_STATE: |
428bafa8 EH |
480 | ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); |
481 | break; | |
577bbe01 RZ |
482 | default: |
483 | break; | |
484 | } | |
485 | return ret; | |
1f7371b2 | 486 | } |
577bbe01 | 487 | |
f8a4c11b | 488 | static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) |
1f7371b2 | 489 | { |
577bbe01 RZ |
490 | struct pp_hwmgr *hwmgr; |
491 | struct pp_power_state *state; | |
492 | ||
493 | if (handle == NULL) | |
494 | return -EINVAL; | |
495 | ||
496 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
497 | ||
498 | if (hwmgr == NULL || hwmgr->current_ps == NULL) | |
499 | return -EINVAL; | |
500 | ||
501 | state = hwmgr->current_ps; | |
502 | ||
503 | switch (state->classification.ui_label) { | |
504 | case PP_StateUILabel_Battery: | |
505 | return POWER_STATE_TYPE_BATTERY; | |
506 | case PP_StateUILabel_Balanced: | |
507 | return POWER_STATE_TYPE_BALANCED; | |
508 | case PP_StateUILabel_Performance: | |
509 | return POWER_STATE_TYPE_PERFORMANCE; | |
510 | default: | |
f3898ea1 EH |
511 | if (state->classification.flags & PP_StateClassificationFlag_Boot) |
512 | return POWER_STATE_TYPE_INTERNAL_BOOT; | |
513 | else | |
514 | return POWER_STATE_TYPE_DEFAULT; | |
577bbe01 | 515 | } |
1f7371b2 | 516 | } |
577bbe01 | 517 | |
cac9a199 RZ |
518 | static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) |
519 | { | |
520 | struct pp_hwmgr *hwmgr; | |
521 | ||
522 | if (handle == NULL) | |
523 | return -EINVAL; | |
524 | ||
525 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
526 | ||
7383bcb9 RZ |
527 | PP_CHECK_HW(hwmgr); |
528 | ||
529 | if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { | |
530 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
531 | return 0; | |
532 | } | |
cac9a199 RZ |
533 | |
534 | return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); | |
535 | } | |
536 | ||
537 | static int pp_dpm_get_fan_control_mode(void *handle) | |
538 | { | |
539 | struct pp_hwmgr *hwmgr; | |
540 | ||
541 | if (handle == NULL) | |
542 | return -EINVAL; | |
543 | ||
544 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
545 | ||
7383bcb9 RZ |
546 | PP_CHECK_HW(hwmgr); |
547 | ||
548 | if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) { | |
549 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
550 | return 0; | |
551 | } | |
cac9a199 RZ |
552 | |
553 | return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); | |
554 | } | |
555 | ||
556 | static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent) | |
557 | { | |
558 | struct pp_hwmgr *hwmgr; | |
559 | ||
560 | if (handle == NULL) | |
561 | return -EINVAL; | |
562 | ||
563 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
564 | ||
7383bcb9 RZ |
565 | PP_CHECK_HW(hwmgr); |
566 | ||
567 | if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) { | |
568 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
569 | return 0; | |
570 | } | |
cac9a199 RZ |
571 | |
572 | return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent); | |
573 | } | |
574 | ||
575 | static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed) | |
576 | { | |
577 | struct pp_hwmgr *hwmgr; | |
578 | ||
579 | if (handle == NULL) | |
580 | return -EINVAL; | |
581 | ||
582 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
583 | ||
7383bcb9 RZ |
584 | PP_CHECK_HW(hwmgr); |
585 | ||
586 | if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) { | |
587 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
588 | return 0; | |
589 | } | |
cac9a199 RZ |
590 | |
591 | return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed); | |
592 | } | |
593 | ||
72a16a9d GI |
594 | static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) |
595 | { | |
596 | struct pp_hwmgr *hwmgr; | |
597 | ||
598 | if (handle == NULL) | |
599 | return -EINVAL; | |
600 | ||
601 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
602 | ||
603 | PP_CHECK_HW(hwmgr); | |
604 | ||
605 | if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL) | |
606 | return -EINVAL; | |
607 | ||
608 | return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm); | |
609 | } | |
610 | ||
cac9a199 RZ |
611 | static int pp_dpm_get_temperature(void *handle) |
612 | { | |
613 | struct pp_hwmgr *hwmgr; | |
614 | ||
615 | if (handle == NULL) | |
616 | return -EINVAL; | |
617 | ||
618 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
619 | ||
7383bcb9 RZ |
620 | PP_CHECK_HW(hwmgr); |
621 | ||
622 | if (hwmgr->hwmgr_func->get_temperature == NULL) { | |
623 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
624 | return 0; | |
625 | } | |
cac9a199 RZ |
626 | |
627 | return hwmgr->hwmgr_func->get_temperature(hwmgr); | |
628 | } | |
577bbe01 | 629 | |
f3898ea1 EH |
630 | static int pp_dpm_get_pp_num_states(void *handle, |
631 | struct pp_states_info *data) | |
632 | { | |
633 | struct pp_hwmgr *hwmgr; | |
634 | int i; | |
635 | ||
636 | if (!handle) | |
637 | return -EINVAL; | |
638 | ||
639 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
640 | ||
641 | if (hwmgr == NULL || hwmgr->ps == NULL) | |
642 | return -EINVAL; | |
643 | ||
644 | data->nums = hwmgr->num_ps; | |
645 | ||
646 | for (i = 0; i < hwmgr->num_ps; i++) { | |
647 | struct pp_power_state *state = (struct pp_power_state *) | |
648 | ((unsigned long)hwmgr->ps + i * hwmgr->ps_size); | |
649 | switch (state->classification.ui_label) { | |
650 | case PP_StateUILabel_Battery: | |
651 | data->states[i] = POWER_STATE_TYPE_BATTERY; | |
652 | break; | |
653 | case PP_StateUILabel_Balanced: | |
654 | data->states[i] = POWER_STATE_TYPE_BALANCED; | |
655 | break; | |
656 | case PP_StateUILabel_Performance: | |
657 | data->states[i] = POWER_STATE_TYPE_PERFORMANCE; | |
658 | break; | |
659 | default: | |
660 | if (state->classification.flags & PP_StateClassificationFlag_Boot) | |
661 | data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT; | |
662 | else | |
663 | data->states[i] = POWER_STATE_TYPE_DEFAULT; | |
664 | } | |
665 | } | |
666 | ||
667 | return 0; | |
668 | } | |
669 | ||
670 | static int pp_dpm_get_pp_table(void *handle, char **table) | |
671 | { | |
672 | struct pp_hwmgr *hwmgr; | |
673 | ||
674 | if (!handle) | |
675 | return -EINVAL; | |
676 | ||
677 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
678 | ||
7383bcb9 RZ |
679 | PP_CHECK_HW(hwmgr); |
680 | ||
4dcf9e6f EH |
681 | if (!hwmgr->soft_pp_table) |
682 | return -EINVAL; | |
683 | ||
684 | *table = (char *)hwmgr->soft_pp_table; | |
f3898ea1 | 685 | |
4dcf9e6f | 686 | return hwmgr->soft_pp_table_size; |
f3898ea1 EH |
687 | } |
688 | ||
689 | static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) | |
690 | { | |
691 | struct pp_hwmgr *hwmgr; | |
692 | ||
693 | if (!handle) | |
694 | return -EINVAL; | |
695 | ||
696 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
697 | ||
7383bcb9 RZ |
698 | PP_CHECK_HW(hwmgr); |
699 | ||
4dcf9e6f | 700 | if (!hwmgr->hardcode_pp_table) { |
efdf7a93 EC |
701 | hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table, |
702 | hwmgr->soft_pp_table_size, | |
703 | GFP_KERNEL); | |
4dcf9e6f EH |
704 | |
705 | if (!hwmgr->hardcode_pp_table) | |
706 | return -ENOMEM; | |
7383bcb9 | 707 | } |
f3898ea1 | 708 | |
4dcf9e6f EH |
709 | memcpy(hwmgr->hardcode_pp_table, buf, size); |
710 | ||
711 | hwmgr->soft_pp_table = hwmgr->hardcode_pp_table; | |
712 | ||
713 | return amd_powerplay_reset(handle); | |
f3898ea1 EH |
714 | } |
715 | ||
716 | static int pp_dpm_force_clock_level(void *handle, | |
5632708f | 717 | enum pp_clock_type type, uint32_t mask) |
f3898ea1 EH |
718 | { |
719 | struct pp_hwmgr *hwmgr; | |
720 | ||
721 | if (!handle) | |
722 | return -EINVAL; | |
723 | ||
724 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
725 | ||
7383bcb9 RZ |
726 | PP_CHECK_HW(hwmgr); |
727 | ||
728 | if (hwmgr->hwmgr_func->force_clock_level == NULL) { | |
729 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
730 | return 0; | |
731 | } | |
f3898ea1 | 732 | |
5632708f | 733 | return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); |
f3898ea1 EH |
734 | } |
735 | ||
736 | static int pp_dpm_print_clock_levels(void *handle, | |
737 | enum pp_clock_type type, char *buf) | |
738 | { | |
739 | struct pp_hwmgr *hwmgr; | |
740 | ||
741 | if (!handle) | |
742 | return -EINVAL; | |
743 | ||
744 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
745 | ||
7383bcb9 | 746 | PP_CHECK_HW(hwmgr); |
f3898ea1 | 747 | |
7383bcb9 RZ |
748 | if (hwmgr->hwmgr_func->print_clock_levels == NULL) { |
749 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
750 | return 0; | |
751 | } | |
f3898ea1 EH |
752 | return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); |
753 | } | |
754 | ||
428bafa8 EH |
755 | static int pp_dpm_get_sclk_od(void *handle) |
756 | { | |
757 | struct pp_hwmgr *hwmgr; | |
758 | ||
759 | if (!handle) | |
760 | return -EINVAL; | |
761 | ||
762 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
763 | ||
764 | PP_CHECK_HW(hwmgr); | |
765 | ||
766 | if (hwmgr->hwmgr_func->get_sclk_od == NULL) { | |
767 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
768 | return 0; | |
769 | } | |
770 | ||
771 | return hwmgr->hwmgr_func->get_sclk_od(hwmgr); | |
772 | } | |
773 | ||
774 | static int pp_dpm_set_sclk_od(void *handle, uint32_t value) | |
775 | { | |
776 | struct pp_hwmgr *hwmgr; | |
777 | ||
778 | if (!handle) | |
779 | return -EINVAL; | |
780 | ||
781 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
782 | ||
783 | PP_CHECK_HW(hwmgr); | |
784 | ||
785 | if (hwmgr->hwmgr_func->set_sclk_od == NULL) { | |
786 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
787 | return 0; | |
788 | } | |
789 | ||
790 | return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); | |
791 | } | |
792 | ||
f2bdc05f EH |
793 | static int pp_dpm_get_mclk_od(void *handle) |
794 | { | |
795 | struct pp_hwmgr *hwmgr; | |
796 | ||
797 | if (!handle) | |
798 | return -EINVAL; | |
799 | ||
800 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
801 | ||
802 | PP_CHECK_HW(hwmgr); | |
803 | ||
804 | if (hwmgr->hwmgr_func->get_mclk_od == NULL) { | |
805 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
806 | return 0; | |
807 | } | |
808 | ||
809 | return hwmgr->hwmgr_func->get_mclk_od(hwmgr); | |
810 | } | |
811 | ||
812 | static int pp_dpm_set_mclk_od(void *handle, uint32_t value) | |
813 | { | |
814 | struct pp_hwmgr *hwmgr; | |
815 | ||
816 | if (!handle) | |
817 | return -EINVAL; | |
818 | ||
819 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
820 | ||
821 | PP_CHECK_HW(hwmgr); | |
822 | ||
823 | if (hwmgr->hwmgr_func->set_mclk_od == NULL) { | |
824 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
825 | return 0; | |
826 | } | |
827 | ||
828 | return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); | |
829 | } | |
830 | ||
a6e36952 TSD |
831 | static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value) |
832 | { | |
833 | struct pp_hwmgr *hwmgr; | |
834 | ||
835 | if (!handle) | |
836 | return -EINVAL; | |
837 | ||
838 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
839 | ||
840 | PP_CHECK_HW(hwmgr); | |
841 | ||
842 | if (hwmgr->hwmgr_func->read_sensor == NULL) { | |
843 | printk(KERN_INFO "%s was not implemented.\n", __func__); | |
844 | return 0; | |
845 | } | |
846 | ||
847 | return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value); | |
848 | } | |
849 | ||
597be302 AD |
850 | static struct amd_vce_state* |
851 | pp_dpm_get_vce_clock_state(void *handle, unsigned idx) | |
852 | { | |
853 | struct pp_hwmgr *hwmgr; | |
854 | ||
855 | if (handle) { | |
856 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
857 | ||
858 | if (hwmgr && idx < hwmgr->num_vce_state_tables) | |
859 | return &hwmgr->vce_states[idx]; | |
860 | } | |
861 | ||
862 | return NULL; | |
863 | } | |
864 | ||
1f7371b2 | 865 | const struct amd_powerplay_funcs pp_dpm_funcs = { |
cac9a199 | 866 | .get_temperature = pp_dpm_get_temperature, |
1f7371b2 AD |
867 | .load_firmware = pp_dpm_load_fw, |
868 | .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, | |
869 | .force_performance_level = pp_dpm_force_performance_level, | |
870 | .get_performance_level = pp_dpm_get_performance_level, | |
871 | .get_current_power_state = pp_dpm_get_current_power_state, | |
872 | .get_sclk = pp_dpm_get_sclk, | |
873 | .get_mclk = pp_dpm_get_mclk, | |
874 | .powergate_vce = pp_dpm_powergate_vce, | |
875 | .powergate_uvd = pp_dpm_powergate_uvd, | |
876 | .dispatch_tasks = pp_dpm_dispatch_tasks, | |
cac9a199 RZ |
877 | .set_fan_control_mode = pp_dpm_set_fan_control_mode, |
878 | .get_fan_control_mode = pp_dpm_get_fan_control_mode, | |
879 | .set_fan_speed_percent = pp_dpm_set_fan_speed_percent, | |
880 | .get_fan_speed_percent = pp_dpm_get_fan_speed_percent, | |
72a16a9d | 881 | .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm, |
f3898ea1 EH |
882 | .get_pp_num_states = pp_dpm_get_pp_num_states, |
883 | .get_pp_table = pp_dpm_get_pp_table, | |
884 | .set_pp_table = pp_dpm_set_pp_table, | |
885 | .force_clock_level = pp_dpm_force_clock_level, | |
886 | .print_clock_levels = pp_dpm_print_clock_levels, | |
428bafa8 EH |
887 | .get_sclk_od = pp_dpm_get_sclk_od, |
888 | .set_sclk_od = pp_dpm_set_sclk_od, | |
f2bdc05f EH |
889 | .get_mclk_od = pp_dpm_get_mclk_od, |
890 | .set_mclk_od = pp_dpm_set_mclk_od, | |
a6e36952 | 891 | .read_sensor = pp_dpm_read_sensor, |
597be302 | 892 | .get_vce_clock_state = pp_dpm_get_vce_clock_state, |
1f7371b2 AD |
893 | }; |
894 | ||
ac885b3a JZ |
895 | static int amd_pp_instance_init(struct amd_pp_init *pp_init, |
896 | struct amd_powerplay *amd_pp) | |
897 | { | |
898 | int ret; | |
899 | struct pp_instance *handle; | |
900 | ||
901 | handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL); | |
902 | if (handle == NULL) | |
903 | return -ENOMEM; | |
904 | ||
a969e163 RZ |
905 | handle->pp_valid = PP_VALID; |
906 | ||
ac885b3a JZ |
907 | ret = smum_init(pp_init, handle); |
908 | if (ret) | |
3bace359 JZ |
909 | goto fail_smum; |
910 | ||
ba5f884c RZ |
911 | |
912 | amd_pp->pp_handle = handle; | |
913 | ||
7b1e8cad TH |
914 | if ((amdgpu_dpm == 0) |
915 | || cgs_is_virtualization_enabled(pp_init->device)) | |
ba5f884c RZ |
916 | return 0; |
917 | ||
3bace359 JZ |
918 | ret = hwmgr_init(pp_init, handle); |
919 | if (ret) | |
920 | goto fail_hwmgr; | |
ac885b3a | 921 | |
e92a0370 RZ |
922 | ret = eventmgr_init(handle); |
923 | if (ret) | |
924 | goto fail_eventmgr; | |
925 | ||
ac885b3a | 926 | return 0; |
3bace359 | 927 | |
e92a0370 RZ |
928 | fail_eventmgr: |
929 | hwmgr_fini(handle->hwmgr); | |
3bace359 JZ |
930 | fail_hwmgr: |
931 | smum_fini(handle->smu_mgr); | |
932 | fail_smum: | |
933 | kfree(handle); | |
934 | return ret; | |
ac885b3a JZ |
935 | } |
936 | ||
937 | static int amd_pp_instance_fini(void *handle) | |
938 | { | |
939 | struct pp_instance *instance = (struct pp_instance *)handle; | |
e92a0370 | 940 | |
ac885b3a JZ |
941 | if (instance == NULL) |
942 | return -EINVAL; | |
943 | ||
7b1e8cad TH |
944 | if ((amdgpu_dpm != 0) |
945 | && !cgs_is_virtualization_enabled(instance->smu_mgr->device)) { | |
ba5f884c RZ |
946 | eventmgr_fini(instance->eventmgr); |
947 | hwmgr_fini(instance->hwmgr); | |
948 | } | |
3bace359 | 949 | |
ac885b3a | 950 | smum_fini(instance->smu_mgr); |
ac885b3a JZ |
951 | kfree(handle); |
952 | return 0; | |
953 | } | |
954 | ||
1f7371b2 AD |
955 | int amd_powerplay_init(struct amd_pp_init *pp_init, |
956 | struct amd_powerplay *amd_pp) | |
957 | { | |
ac885b3a JZ |
958 | int ret; |
959 | ||
1f7371b2 AD |
960 | if (pp_init == NULL || amd_pp == NULL) |
961 | return -EINVAL; | |
962 | ||
ac885b3a JZ |
963 | ret = amd_pp_instance_init(pp_init, amd_pp); |
964 | ||
965 | if (ret) | |
966 | return ret; | |
967 | ||
1f7371b2 AD |
968 | amd_pp->ip_funcs = &pp_ip_funcs; |
969 | amd_pp->pp_funcs = &pp_dpm_funcs; | |
970 | ||
971 | return 0; | |
972 | } | |
973 | ||
974 | int amd_powerplay_fini(void *handle) | |
975 | { | |
ac885b3a JZ |
976 | amd_pp_instance_fini(handle); |
977 | ||
1f7371b2 AD |
978 | return 0; |
979 | } | |
7fb72a1f | 980 | |
4dcf9e6f EH |
981 | int amd_powerplay_reset(void *handle) |
982 | { | |
983 | struct pp_instance *instance = (struct pp_instance *)handle; | |
984 | struct pp_eventmgr *eventmgr; | |
985 | struct pem_event_data event_data = { {0} }; | |
986 | int ret; | |
987 | ||
988 | if (instance == NULL) | |
989 | return -EINVAL; | |
990 | ||
991 | eventmgr = instance->eventmgr; | |
992 | if (!eventmgr || !eventmgr->pp_eventmgr_fini) | |
993 | return -EINVAL; | |
994 | ||
995 | eventmgr->pp_eventmgr_fini(eventmgr); | |
996 | ||
997 | ret = pp_sw_fini(handle); | |
998 | if (ret) | |
999 | return ret; | |
1000 | ||
1001 | kfree(instance->hwmgr->ps); | |
1002 | ||
1003 | ret = pp_sw_init(handle); | |
1004 | if (ret) | |
1005 | return ret; | |
1006 | ||
7b1e8cad TH |
1007 | if ((amdgpu_dpm == 0) |
1008 | || cgs_is_virtualization_enabled(instance->smu_mgr->device)) | |
ba5f884c RZ |
1009 | return 0; |
1010 | ||
e9efaaa0 XY |
1011 | hw_init_power_state_table(instance->hwmgr); |
1012 | ||
4dcf9e6f EH |
1013 | if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL) |
1014 | return -EINVAL; | |
1015 | ||
1016 | ret = eventmgr->pp_eventmgr_init(eventmgr); | |
1017 | if (ret) | |
1018 | return ret; | |
1019 | ||
1020 | return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data); | |
1021 | } | |
1022 | ||
7fb72a1f RZ |
1023 | /* export this function to DAL */ |
1024 | ||
155f1127 DR |
1025 | int amd_powerplay_display_configuration_change(void *handle, |
1026 | const struct amd_pp_display_configuration *display_config) | |
7fb72a1f RZ |
1027 | { |
1028 | struct pp_hwmgr *hwmgr; | |
7fb72a1f | 1029 | |
a969e163 | 1030 | PP_CHECK((struct pp_instance *)handle); |
7fb72a1f RZ |
1031 | |
1032 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
1033 | ||
ba5f884c RZ |
1034 | PP_CHECK_HW(hwmgr); |
1035 | ||
7fb72a1f | 1036 | phm_store_dal_configuration_data(hwmgr, display_config); |
e0b71a7e | 1037 | |
7fb72a1f RZ |
1038 | return 0; |
1039 | } | |
c4dd206b | 1040 | |
1c9a9082 | 1041 | int amd_powerplay_get_display_power_level(void *handle, |
47329134 | 1042 | struct amd_pp_simple_clock_info *output) |
c4dd206b VP |
1043 | { |
1044 | struct pp_hwmgr *hwmgr; | |
1045 | ||
a969e163 RZ |
1046 | PP_CHECK((struct pp_instance *)handle); |
1047 | ||
1048 | if (output == NULL) | |
c4dd206b VP |
1049 | return -EINVAL; |
1050 | ||
1051 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
1052 | ||
ba5f884c RZ |
1053 | PP_CHECK_HW(hwmgr); |
1054 | ||
1c9a9082 | 1055 | return phm_get_dal_power_level(hwmgr, output); |
c4dd206b | 1056 | } |
e273b041 RZ |
1057 | |
1058 | int amd_powerplay_get_current_clocks(void *handle, | |
155f1127 | 1059 | struct amd_pp_clock_info *clocks) |
e273b041 RZ |
1060 | { |
1061 | struct pp_hwmgr *hwmgr; | |
1062 | struct amd_pp_simple_clock_info simple_clocks; | |
1063 | struct pp_clock_info hw_clocks; | |
e273b041 | 1064 | |
fa9e6991 RZ |
1065 | PP_CHECK((struct pp_instance *)handle); |
1066 | ||
1067 | if (clocks == NULL) | |
e273b041 RZ |
1068 | return -EINVAL; |
1069 | ||
1070 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
1071 | ||
ba5f884c RZ |
1072 | PP_CHECK_HW(hwmgr); |
1073 | ||
e273b041 RZ |
1074 | phm_get_dal_power_level(hwmgr, &simple_clocks); |
1075 | ||
1076 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) { | |
1077 | if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment)) | |
1078 | PP_ASSERT_WITH_CODE(0, "Error in PHM_GetPowerContainmentClockInfo", return -1); | |
1079 | } else { | |
1080 | if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity)) | |
1081 | PP_ASSERT_WITH_CODE(0, "Error in PHM_GetClockInfo", return -1); | |
1082 | } | |
1083 | ||
1084 | clocks->min_engine_clock = hw_clocks.min_eng_clk; | |
1085 | clocks->max_engine_clock = hw_clocks.max_eng_clk; | |
1086 | clocks->min_memory_clock = hw_clocks.min_mem_clk; | |
1087 | clocks->max_memory_clock = hw_clocks.max_mem_clk; | |
1088 | clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth; | |
1089 | clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth; | |
1090 | ||
1091 | clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; | |
1092 | clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; | |
1093 | ||
1094 | clocks->max_clocks_state = simple_clocks.level; | |
1095 | ||
1096 | if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) { | |
1097 | clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; | |
1098 | clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; | |
1099 | } | |
1100 | ||
1101 | return 0; | |
1102 | ||
1103 | } | |
1104 | ||
1105 | int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) | |
1106 | { | |
1107 | int result = -1; | |
1108 | ||
1109 | struct pp_hwmgr *hwmgr; | |
1110 | ||
fa9e6991 RZ |
1111 | PP_CHECK((struct pp_instance *)handle); |
1112 | ||
1113 | if (clocks == NULL) | |
e273b041 RZ |
1114 | return -EINVAL; |
1115 | ||
1116 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
1117 | ||
ba5f884c RZ |
1118 | PP_CHECK_HW(hwmgr); |
1119 | ||
e273b041 RZ |
1120 | result = phm_get_clock_by_type(hwmgr, type, clocks); |
1121 | ||
1122 | return result; | |
1123 | } | |
1124 | ||
155f1127 DR |
1125 | int amd_powerplay_get_display_mode_validation_clocks(void *handle, |
1126 | struct amd_pp_simple_clock_info *clocks) | |
e273b041 RZ |
1127 | { |
1128 | int result = -1; | |
e273b041 RZ |
1129 | struct pp_hwmgr *hwmgr; |
1130 | ||
fa9e6991 RZ |
1131 | PP_CHECK((struct pp_instance *)handle); |
1132 | ||
1133 | if (clocks == NULL) | |
e273b041 RZ |
1134 | return -EINVAL; |
1135 | ||
1136 | hwmgr = ((struct pp_instance *)handle)->hwmgr; | |
1137 | ||
ba5f884c RZ |
1138 | PP_CHECK_HW(hwmgr); |
1139 | ||
e273b041 RZ |
1140 | if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState)) |
1141 | result = phm_get_max_high_clocks(hwmgr, clocks); | |
1142 | ||
1143 | return result; | |
1144 | } | |
1145 |