blob: bb8a345c750ac1af564dde7c33b444c0dd41137d [file] [log] [blame]
Alex Deucher1f7371b2015-12-02 17:46:21 -05001/*
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>
Jammy Zhouac885b32015-07-21 17:43:02 +080026#include <linux/slab.h>
Alex Deucher1f7371b2015-12-02 17:46:21 -050027#include "amd_shared.h"
28#include "amd_powerplay.h"
Jammy Zhouac885b32015-07-21 17:43:02 +080029#include "pp_instance.h"
Rex Zhu577bbe02015-08-28 12:56:43 +080030#include "power_state.h"
31#include "eventmanager.h"
Rex Zhue273b042015-12-07 18:44:23 +080032#include "pp_debug.h"
Alex Deucher1f7371b2015-12-02 17:46:21 -050033
Rex Zhuaf223df2016-07-28 16:51:47 +080034
Rex Zhua969e162015-12-29 13:56:03 +080035#define PP_CHECK(handle) \
36 do { \
37 if ((handle) == NULL || (handle)->pp_valid != PP_VALID) \
38 return -EINVAL; \
39 } while (0)
40
Rex Zhu7383bcb2016-03-30 11:35:50 +080041#define PP_CHECK_HW(hwmgr) \
42 do { \
43 if ((hwmgr) == NULL || (hwmgr)->hwmgr_func == NULL) \
44 return -EINVAL; \
45 } while (0)
46
Alex Deucher1f7371b2015-12-02 17:46:21 -050047static int pp_early_init(void *handle)
48{
49 return 0;
50}
51
52static int pp_sw_init(void *handle)
53{
Jammy Zhou3bace352015-07-21 21:18:15 +080054 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
Rex Zhu7383bcb2016-03-30 11:35:50 +080064 PP_CHECK_HW(hwmgr);
65
66 if (hwmgr->pptable_func == NULL ||
Jammy Zhou3bace352015-07-21 21:18:15 +080067 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);
Alex Deucher9441f962016-01-20 12:15:09 -050072 if (ret)
Huang Ruib4eeed52016-05-09 17:29:41 +080073 goto err;
Alex Deucher9441f962016-01-20 12:15:09 -050074
Huang Ruib4eeed52016-05-09 17:29:41 +080075 ret = hwmgr->hwmgr_func->backend_init(hwmgr);
76 if (ret)
Monk Liu9d8f0862016-05-30 13:43:45 +080077 goto err1;
Huang Ruib4eeed52016-05-09 17:29:41 +080078
79 pr_info("amdgpu: powerplay initialized\n");
80
81 return 0;
Monk Liu9d8f0862016-05-30 13:43:45 +080082err1:
83 if (hwmgr->pptable_func->pptable_fini)
84 hwmgr->pptable_func->pptable_fini(hwmgr);
Huang Ruib4eeed52016-05-09 17:29:41 +080085err:
86 pr_err("amdgpu: powerplay initialization failed\n");
Jammy Zhou3bace352015-07-21 21:18:15 +080087 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -050088}
89
90static int pp_sw_fini(void *handle)
91{
Jammy Zhou3bace352015-07-21 21:18:15 +080092 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
Rex Zhu7383bcb2016-03-30 11:35:50 +0800102 PP_CHECK_HW(hwmgr);
103
104 if (hwmgr->hwmgr_func->backend_fini != NULL)
Jammy Zhou3bace352015-07-21 21:18:15 +0800105 ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
106
Monk Liu9d8f0862016-05-30 13:43:45 +0800107 if (hwmgr->pptable_func->pptable_fini)
108 hwmgr->pptable_func->pptable_fini(hwmgr);
109
Jammy Zhou3bace352015-07-21 21:18:15 +0800110 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500111}
112
113static int pp_hw_init(void *handle)
114{
Jammy Zhouac885b32015-07-21 17:43:02 +0800115 struct pp_instance *pp_handle;
116 struct pp_smumgr *smumgr;
Rex Zhue92a0372015-09-23 15:14:54 +0800117 struct pp_eventmgr *eventmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800118 int ret = 0;
119
120 if (handle == NULL)
121 return -EINVAL;
122
123 pp_handle = (struct pp_instance *)handle;
124 smumgr = pp_handle->smu_mgr;
125
126 if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
127 smumgr->smumgr_funcs->smu_init == NULL ||
128 smumgr->smumgr_funcs->start_smu == NULL)
129 return -EINVAL;
130
131 ret = smumgr->smumgr_funcs->smu_init(smumgr);
132 if (ret) {
133 printk(KERN_ERR "[ powerplay ] smc initialization failed\n");
134 return ret;
135 }
136
137 ret = smumgr->smumgr_funcs->start_smu(smumgr);
138 if (ret) {
139 printk(KERN_ERR "[ powerplay ] smc start failed\n");
140 smumgr->smumgr_funcs->smu_fini(smumgr);
141 return ret;
142 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800143
Rex Zhue92a0372015-09-23 15:14:54 +0800144 hw_init_power_state_table(pp_handle->hwmgr);
145 eventmgr = pp_handle->eventmgr;
146
147 if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
148 return -EINVAL;
149
150 ret = eventmgr->pp_eventmgr_init(eventmgr);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500151 return 0;
152}
153
154static int pp_hw_fini(void *handle)
155{
Jammy Zhouac885b32015-07-21 17:43:02 +0800156 struct pp_instance *pp_handle;
157 struct pp_smumgr *smumgr;
Rex Zhue92a0372015-09-23 15:14:54 +0800158 struct pp_eventmgr *eventmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800159
160 if (handle == NULL)
161 return -EINVAL;
162
163 pp_handle = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +0800164 eventmgr = pp_handle->eventmgr;
165
Heinrich Schuchardtd36f3e02016-08-21 20:21:27 +0200166 if (eventmgr != NULL && eventmgr->pp_eventmgr_fini != NULL)
Rex Zhue92a0372015-09-23 15:14:54 +0800167 eventmgr->pp_eventmgr_fini(eventmgr);
168
Jammy Zhouac885b32015-07-21 17:43:02 +0800169 smumgr = pp_handle->smu_mgr;
170
Heinrich Schuchardtd36f3e02016-08-21 20:21:27 +0200171 if (smumgr != NULL && smumgr->smumgr_funcs != NULL &&
Jammy Zhouac885b32015-07-21 17:43:02 +0800172 smumgr->smumgr_funcs->smu_fini != NULL)
173 smumgr->smumgr_funcs->smu_fini(smumgr);
174
Alex Deucher1f7371b2015-12-02 17:46:21 -0500175 return 0;
176}
177
178static bool pp_is_idle(void *handle)
179{
Edward O'Callaghaned5121a2016-07-12 10:17:52 +1000180 return false;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500181}
182
183static int pp_wait_for_idle(void *handle)
184{
185 return 0;
186}
187
188static int pp_sw_reset(void *handle)
189{
190 return 0;
191}
192
Alex Deucher1f7371b2015-12-02 17:46:21 -0500193
Rex Zhu465f96e2016-09-18 16:52:03 +0800194int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500195{
Eric Huang03e39052016-02-09 16:26:00 -0500196 struct pp_hwmgr *hwmgr;
Eric Huang03e39052016-02-09 16:26:00 -0500197
198 if (handle == NULL)
199 return -EINVAL;
200
201 hwmgr = ((struct pp_instance *)handle)->hwmgr;
202
Rex Zhu7383bcb2016-03-30 11:35:50 +0800203 PP_CHECK_HW(hwmgr);
Eric Huang03e39052016-02-09 16:26:00 -0500204
Rex Zhu7383bcb2016-03-30 11:35:50 +0800205 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
206 printk(KERN_INFO "%s was not implemented.\n", __func__);
Flora Cui538333f2016-02-15 15:45:59 +0800207 return 0;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800208 }
Flora Cui538333f2016-02-15 15:45:59 +0800209
Rex Zhu465f96e2016-09-18 16:52:03 +0800210 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500211}
212
213static int pp_set_powergating_state(void *handle,
214 enum amd_powergating_state state)
215{
Eric Huang65f85e72016-02-11 15:54:45 -0500216 struct pp_hwmgr *hwmgr;
217
218 if (handle == NULL)
219 return -EINVAL;
220
221 hwmgr = ((struct pp_instance *)handle)->hwmgr;
222
Rex Zhu7383bcb2016-03-30 11:35:50 +0800223 PP_CHECK_HW(hwmgr);
224
225 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
226 printk(KERN_INFO "%s was not implemented.\n", __func__);
227 return 0;
228 }
Eric Huang65f85e72016-02-11 15:54:45 -0500229
230 /* Enable/disable GFX per cu powergating through SMU */
231 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
232 state == AMD_PG_STATE_GATE ? true : false);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500233}
234
235static int pp_suspend(void *handle)
236{
Rex Zhu577bbe02015-08-28 12:56:43 +0800237 struct pp_instance *pp_handle;
238 struct pp_eventmgr *eventmgr;
239 struct pem_event_data event_data = { {0} };
240
241 if (handle == NULL)
242 return -EINVAL;
243
244 pp_handle = (struct pp_instance *)handle;
245 eventmgr = pp_handle->eventmgr;
246 pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500247 return 0;
248}
249
250static int pp_resume(void *handle)
251{
Rex Zhu577bbe02015-08-28 12:56:43 +0800252 struct pp_instance *pp_handle;
253 struct pp_eventmgr *eventmgr;
254 struct pem_event_data event_data = { {0} };
Rex Zhue0b71a72015-12-29 10:25:19 +0800255 struct pp_smumgr *smumgr;
256 int ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800257
258 if (handle == NULL)
259 return -EINVAL;
260
261 pp_handle = (struct pp_instance *)handle;
Rex Zhue0b71a72015-12-29 10:25:19 +0800262 smumgr = pp_handle->smu_mgr;
263
264 if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
265 smumgr->smumgr_funcs->start_smu == NULL)
266 return -EINVAL;
267
268 ret = smumgr->smumgr_funcs->start_smu(smumgr);
269 if (ret) {
270 printk(KERN_ERR "[ powerplay ] smc start failed\n");
271 smumgr->smumgr_funcs->smu_fini(smumgr);
272 return ret;
273 }
274
Rex Zhu577bbe02015-08-28 12:56:43 +0800275 eventmgr = pp_handle->eventmgr;
276 pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
Rex Zhue0b71a72015-12-29 10:25:19 +0800277
Alex Deucher1f7371b2015-12-02 17:46:21 -0500278 return 0;
279}
280
281const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400282 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500283 .early_init = pp_early_init,
284 .late_init = NULL,
285 .sw_init = pp_sw_init,
286 .sw_fini = pp_sw_fini,
287 .hw_init = pp_hw_init,
288 .hw_fini = pp_hw_fini,
289 .suspend = pp_suspend,
290 .resume = pp_resume,
291 .is_idle = pp_is_idle,
292 .wait_for_idle = pp_wait_for_idle,
293 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800294 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500295 .set_powergating_state = pp_set_powergating_state,
296};
297
298static int pp_dpm_load_fw(void *handle)
299{
300 return 0;
301}
302
303static int pp_dpm_fw_loading_complete(void *handle)
304{
305 return 0;
306}
307
308static int pp_dpm_force_performance_level(void *handle,
309 enum amd_dpm_forced_level level)
310{
Rex Zhu577bbe02015-08-28 12:56:43 +0800311 struct pp_instance *pp_handle;
312 struct pp_hwmgr *hwmgr;
313
314 if (handle == NULL)
315 return -EINVAL;
316
317 pp_handle = (struct pp_instance *)handle;
318
319 hwmgr = pp_handle->hwmgr;
320
Rex Zhu7383bcb2016-03-30 11:35:50 +0800321 PP_CHECK_HW(hwmgr);
322
323 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
324 printk(KERN_INFO "%s was not implemented.\n", __func__);
325 return 0;
326 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800327
328 hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
329
Alex Deucher1f7371b2015-12-02 17:46:21 -0500330 return 0;
331}
Rex Zhu577bbe02015-08-28 12:56:43 +0800332
Alex Deucher1f7371b2015-12-02 17:46:21 -0500333static enum amd_dpm_forced_level pp_dpm_get_performance_level(
334 void *handle)
335{
Rex Zhu577bbe02015-08-28 12:56:43 +0800336 struct pp_hwmgr *hwmgr;
337
338 if (handle == NULL)
339 return -EINVAL;
340
341 hwmgr = ((struct pp_instance *)handle)->hwmgr;
342
343 if (hwmgr == NULL)
344 return -EINVAL;
345
346 return (((struct pp_instance *)handle)->hwmgr->dpm_level);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500347}
Rex Zhu577bbe02015-08-28 12:56:43 +0800348
Alex Deucher1f7371b2015-12-02 17:46:21 -0500349static int pp_dpm_get_sclk(void *handle, bool low)
350{
Rex Zhu577bbe02015-08-28 12:56:43 +0800351 struct pp_hwmgr *hwmgr;
352
353 if (handle == NULL)
354 return -EINVAL;
355
356 hwmgr = ((struct pp_instance *)handle)->hwmgr;
357
Rex Zhu7383bcb2016-03-30 11:35:50 +0800358 PP_CHECK_HW(hwmgr);
359
360 if (hwmgr->hwmgr_func->get_sclk == NULL) {
361 printk(KERN_INFO "%s was not implemented.\n", __func__);
362 return 0;
363 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800364
365 return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500366}
Rex Zhu577bbe02015-08-28 12:56:43 +0800367
Alex Deucher1f7371b2015-12-02 17:46:21 -0500368static int pp_dpm_get_mclk(void *handle, bool low)
369{
Rex Zhu577bbe02015-08-28 12:56:43 +0800370 struct pp_hwmgr *hwmgr;
371
372 if (handle == NULL)
373 return -EINVAL;
374
375 hwmgr = ((struct pp_instance *)handle)->hwmgr;
376
Rex Zhu7383bcb2016-03-30 11:35:50 +0800377 PP_CHECK_HW(hwmgr);
378
379 if (hwmgr->hwmgr_func->get_mclk == NULL) {
380 printk(KERN_INFO "%s was not implemented.\n", __func__);
381 return 0;
382 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800383
384 return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500385}
Rex Zhu577bbe02015-08-28 12:56:43 +0800386
Alex Deucher1f7371b2015-12-02 17:46:21 -0500387static int pp_dpm_powergate_vce(void *handle, bool gate)
388{
Rex Zhu577bbe02015-08-28 12:56:43 +0800389 struct pp_hwmgr *hwmgr;
390
391 if (handle == NULL)
392 return -EINVAL;
393
394 hwmgr = ((struct pp_instance *)handle)->hwmgr;
395
Rex Zhu7383bcb2016-03-30 11:35:50 +0800396 PP_CHECK_HW(hwmgr);
397
398 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
399 printk(KERN_INFO "%s was not implemented.\n", __func__);
400 return 0;
401 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800402
403 return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500404}
Rex Zhu577bbe02015-08-28 12:56:43 +0800405
Alex Deucher1f7371b2015-12-02 17:46:21 -0500406static int pp_dpm_powergate_uvd(void *handle, bool gate)
407{
Rex Zhu577bbe02015-08-28 12:56:43 +0800408 struct pp_hwmgr *hwmgr;
409
410 if (handle == NULL)
411 return -EINVAL;
412
413 hwmgr = ((struct pp_instance *)handle)->hwmgr;
414
Rex Zhu7383bcb2016-03-30 11:35:50 +0800415 PP_CHECK_HW(hwmgr);
416
417 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
418 printk(KERN_INFO "%s was not implemented.\n", __func__);
419 return 0;
420 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800421
422 return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
423}
424
425static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state)
426{
427 switch (state) {
428 case POWER_STATE_TYPE_BATTERY:
429 return PP_StateUILabel_Battery;
430 case POWER_STATE_TYPE_BALANCED:
431 return PP_StateUILabel_Balanced;
432 case POWER_STATE_TYPE_PERFORMANCE:
433 return PP_StateUILabel_Performance;
434 default:
435 return PP_StateUILabel_None;
436 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500437}
438
Baoyou Xief8a4c112016-09-30 17:58:42 +0800439static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
440 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500441{
Rex Zhu577bbe02015-08-28 12:56:43 +0800442 int ret = 0;
443 struct pp_instance *pp_handle;
444 struct pem_event_data data = { {0} };
445
446 pp_handle = (struct pp_instance *)handle;
447
448 if (pp_handle == NULL)
449 return -EINVAL;
450
451 switch (event_id) {
452 case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
453 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
454 break;
455 case AMD_PP_EVENT_ENABLE_USER_STATE:
456 {
457 enum amd_pm_state_type ps;
458
459 if (input == NULL)
460 return -EINVAL;
461 ps = *(unsigned long *)input;
462
463 data.requested_ui_label = power_state_convert(ps);
464 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
Rex Zhudc26a2a2016-02-25 17:16:52 +0800465 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800466 }
Rex Zhudc26a2a2016-02-25 17:16:52 +0800467 case AMD_PP_EVENT_COMPLETE_INIT:
468 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
469 break;
Eric Huang428bafa2016-05-12 14:51:21 -0400470 case AMD_PP_EVENT_READJUST_POWER_STATE:
Eric Huang428bafa2016-05-12 14:51:21 -0400471 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
472 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800473 default:
474 break;
475 }
476 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500477}
Rex Zhu577bbe02015-08-28 12:56:43 +0800478
Baoyou Xief8a4c112016-09-30 17:58:42 +0800479static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500480{
Rex Zhu577bbe02015-08-28 12:56:43 +0800481 struct pp_hwmgr *hwmgr;
482 struct pp_power_state *state;
483
484 if (handle == NULL)
485 return -EINVAL;
486
487 hwmgr = ((struct pp_instance *)handle)->hwmgr;
488
489 if (hwmgr == NULL || hwmgr->current_ps == NULL)
490 return -EINVAL;
491
492 state = hwmgr->current_ps;
493
494 switch (state->classification.ui_label) {
495 case PP_StateUILabel_Battery:
496 return POWER_STATE_TYPE_BATTERY;
497 case PP_StateUILabel_Balanced:
498 return POWER_STATE_TYPE_BALANCED;
499 case PP_StateUILabel_Performance:
500 return POWER_STATE_TYPE_PERFORMANCE;
501 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500502 if (state->classification.flags & PP_StateClassificationFlag_Boot)
503 return POWER_STATE_TYPE_INTERNAL_BOOT;
504 else
505 return POWER_STATE_TYPE_DEFAULT;
Rex Zhu577bbe02015-08-28 12:56:43 +0800506 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500507}
Rex Zhu577bbe02015-08-28 12:56:43 +0800508
Rex Zhucac9a192015-10-16 11:48:21 +0800509static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
510{
511 struct pp_hwmgr *hwmgr;
512
513 if (handle == NULL)
514 return -EINVAL;
515
516 hwmgr = ((struct pp_instance *)handle)->hwmgr;
517
Rex Zhu7383bcb2016-03-30 11:35:50 +0800518 PP_CHECK_HW(hwmgr);
519
520 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
521 printk(KERN_INFO "%s was not implemented.\n", __func__);
522 return 0;
523 }
Rex Zhucac9a192015-10-16 11:48:21 +0800524
525 return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
526}
527
528static int pp_dpm_get_fan_control_mode(void *handle)
529{
530 struct pp_hwmgr *hwmgr;
531
532 if (handle == NULL)
533 return -EINVAL;
534
535 hwmgr = ((struct pp_instance *)handle)->hwmgr;
536
Rex Zhu7383bcb2016-03-30 11:35:50 +0800537 PP_CHECK_HW(hwmgr);
538
539 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
540 printk(KERN_INFO "%s was not implemented.\n", __func__);
541 return 0;
542 }
Rex Zhucac9a192015-10-16 11:48:21 +0800543
544 return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
545}
546
547static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
548{
549 struct pp_hwmgr *hwmgr;
550
551 if (handle == NULL)
552 return -EINVAL;
553
554 hwmgr = ((struct pp_instance *)handle)->hwmgr;
555
Rex Zhu7383bcb2016-03-30 11:35:50 +0800556 PP_CHECK_HW(hwmgr);
557
558 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
559 printk(KERN_INFO "%s was not implemented.\n", __func__);
560 return 0;
561 }
Rex Zhucac9a192015-10-16 11:48:21 +0800562
563 return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
564}
565
566static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
567{
568 struct pp_hwmgr *hwmgr;
569
570 if (handle == NULL)
571 return -EINVAL;
572
573 hwmgr = ((struct pp_instance *)handle)->hwmgr;
574
Rex Zhu7383bcb2016-03-30 11:35:50 +0800575 PP_CHECK_HW(hwmgr);
576
577 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
578 printk(KERN_INFO "%s was not implemented.\n", __func__);
579 return 0;
580 }
Rex Zhucac9a192015-10-16 11:48:21 +0800581
582 return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
583}
584
585static int pp_dpm_get_temperature(void *handle)
586{
587 struct pp_hwmgr *hwmgr;
588
589 if (handle == NULL)
590 return -EINVAL;
591
592 hwmgr = ((struct pp_instance *)handle)->hwmgr;
593
Rex Zhu7383bcb2016-03-30 11:35:50 +0800594 PP_CHECK_HW(hwmgr);
595
596 if (hwmgr->hwmgr_func->get_temperature == NULL) {
597 printk(KERN_INFO "%s was not implemented.\n", __func__);
598 return 0;
599 }
Rex Zhucac9a192015-10-16 11:48:21 +0800600
601 return hwmgr->hwmgr_func->get_temperature(hwmgr);
602}
Rex Zhu577bbe02015-08-28 12:56:43 +0800603
Eric Huangf3898ea2015-12-11 16:24:34 -0500604static int pp_dpm_get_pp_num_states(void *handle,
605 struct pp_states_info *data)
606{
607 struct pp_hwmgr *hwmgr;
608 int i;
609
610 if (!handle)
611 return -EINVAL;
612
613 hwmgr = ((struct pp_instance *)handle)->hwmgr;
614
615 if (hwmgr == NULL || hwmgr->ps == NULL)
616 return -EINVAL;
617
618 data->nums = hwmgr->num_ps;
619
620 for (i = 0; i < hwmgr->num_ps; i++) {
621 struct pp_power_state *state = (struct pp_power_state *)
622 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
623 switch (state->classification.ui_label) {
624 case PP_StateUILabel_Battery:
625 data->states[i] = POWER_STATE_TYPE_BATTERY;
626 break;
627 case PP_StateUILabel_Balanced:
628 data->states[i] = POWER_STATE_TYPE_BALANCED;
629 break;
630 case PP_StateUILabel_Performance:
631 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
632 break;
633 default:
634 if (state->classification.flags & PP_StateClassificationFlag_Boot)
635 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
636 else
637 data->states[i] = POWER_STATE_TYPE_DEFAULT;
638 }
639 }
640
641 return 0;
642}
643
644static int pp_dpm_get_pp_table(void *handle, char **table)
645{
646 struct pp_hwmgr *hwmgr;
647
648 if (!handle)
649 return -EINVAL;
650
651 hwmgr = ((struct pp_instance *)handle)->hwmgr;
652
Rex Zhu7383bcb2016-03-30 11:35:50 +0800653 PP_CHECK_HW(hwmgr);
654
Eric Huang4dcf9e62016-06-01 17:08:07 -0400655 if (!hwmgr->soft_pp_table)
656 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500657
Eric Huang4dcf9e62016-06-01 17:08:07 -0400658 *table = (char *)hwmgr->soft_pp_table;
659
660 return hwmgr->soft_pp_table_size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500661}
662
663static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
664{
665 struct pp_hwmgr *hwmgr;
666
667 if (!handle)
668 return -EINVAL;
669
670 hwmgr = ((struct pp_instance *)handle)->hwmgr;
671
Rex Zhu7383bcb2016-03-30 11:35:50 +0800672 PP_CHECK_HW(hwmgr);
673
Eric Huang4dcf9e62016-06-01 17:08:07 -0400674 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000675 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
676 hwmgr->soft_pp_table_size,
677 GFP_KERNEL);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400678
679 if (!hwmgr->hardcode_pp_table)
680 return -ENOMEM;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800681 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500682
Eric Huang4dcf9e62016-06-01 17:08:07 -0400683 memcpy(hwmgr->hardcode_pp_table, buf, size);
684
685 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
686
687 return amd_powerplay_reset(handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500688}
689
690static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400691 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500692{
693 struct pp_hwmgr *hwmgr;
694
695 if (!handle)
696 return -EINVAL;
697
698 hwmgr = ((struct pp_instance *)handle)->hwmgr;
699
Rex Zhu7383bcb2016-03-30 11:35:50 +0800700 PP_CHECK_HW(hwmgr);
701
702 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
703 printk(KERN_INFO "%s was not implemented.\n", __func__);
704 return 0;
705 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500706
Eric Huang56327082016-04-12 14:57:23 -0400707 return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
Eric Huangf3898ea2015-12-11 16:24:34 -0500708}
709
710static int pp_dpm_print_clock_levels(void *handle,
711 enum pp_clock_type type, char *buf)
712{
713 struct pp_hwmgr *hwmgr;
714
715 if (!handle)
716 return -EINVAL;
717
718 hwmgr = ((struct pp_instance *)handle)->hwmgr;
719
Rex Zhu7383bcb2016-03-30 11:35:50 +0800720 PP_CHECK_HW(hwmgr);
Eric Huangf3898ea2015-12-11 16:24:34 -0500721
Rex Zhu7383bcb2016-03-30 11:35:50 +0800722 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
723 printk(KERN_INFO "%s was not implemented.\n", __func__);
724 return 0;
725 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500726 return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
727}
728
Eric Huang428bafa2016-05-12 14:51:21 -0400729static int pp_dpm_get_sclk_od(void *handle)
730{
731 struct pp_hwmgr *hwmgr;
732
733 if (!handle)
734 return -EINVAL;
735
736 hwmgr = ((struct pp_instance *)handle)->hwmgr;
737
738 PP_CHECK_HW(hwmgr);
739
740 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
741 printk(KERN_INFO "%s was not implemented.\n", __func__);
742 return 0;
743 }
744
745 return hwmgr->hwmgr_func->get_sclk_od(hwmgr);
746}
747
748static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
749{
750 struct pp_hwmgr *hwmgr;
751
752 if (!handle)
753 return -EINVAL;
754
755 hwmgr = ((struct pp_instance *)handle)->hwmgr;
756
757 PP_CHECK_HW(hwmgr);
758
759 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
760 printk(KERN_INFO "%s was not implemented.\n", __func__);
761 return 0;
762 }
763
764 return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
765}
766
Eric Huangf2bdc052016-05-24 15:11:17 -0400767static int pp_dpm_get_mclk_od(void *handle)
768{
769 struct pp_hwmgr *hwmgr;
770
771 if (!handle)
772 return -EINVAL;
773
774 hwmgr = ((struct pp_instance *)handle)->hwmgr;
775
776 PP_CHECK_HW(hwmgr);
777
778 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
779 printk(KERN_INFO "%s was not implemented.\n", __func__);
780 return 0;
781 }
782
783 return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
784}
785
786static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
787{
788 struct pp_hwmgr *hwmgr;
789
790 if (!handle)
791 return -EINVAL;
792
793 hwmgr = ((struct pp_instance *)handle)->hwmgr;
794
795 PP_CHECK_HW(hwmgr);
796
797 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
798 printk(KERN_INFO "%s was not implemented.\n", __func__);
799 return 0;
800 }
801
802 return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
803}
804
Tom St Denisa6e36952016-09-15 10:07:34 -0400805static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value)
806{
807 struct pp_hwmgr *hwmgr;
808
809 if (!handle)
810 return -EINVAL;
811
812 hwmgr = ((struct pp_instance *)handle)->hwmgr;
813
814 PP_CHECK_HW(hwmgr);
815
816 if (hwmgr->hwmgr_func->read_sensor == NULL) {
817 printk(KERN_INFO "%s was not implemented.\n", __func__);
818 return 0;
819 }
820
821 return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value);
822}
823
Alex Deucher1f7371b2015-12-02 17:46:21 -0500824const struct amd_powerplay_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +0800825 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500826 .load_firmware = pp_dpm_load_fw,
827 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
828 .force_performance_level = pp_dpm_force_performance_level,
829 .get_performance_level = pp_dpm_get_performance_level,
830 .get_current_power_state = pp_dpm_get_current_power_state,
831 .get_sclk = pp_dpm_get_sclk,
832 .get_mclk = pp_dpm_get_mclk,
833 .powergate_vce = pp_dpm_powergate_vce,
834 .powergate_uvd = pp_dpm_powergate_uvd,
835 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +0800836 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
837 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
838 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
839 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Eric Huangf3898ea2015-12-11 16:24:34 -0500840 .get_pp_num_states = pp_dpm_get_pp_num_states,
841 .get_pp_table = pp_dpm_get_pp_table,
842 .set_pp_table = pp_dpm_set_pp_table,
843 .force_clock_level = pp_dpm_force_clock_level,
844 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -0400845 .get_sclk_od = pp_dpm_get_sclk_od,
846 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -0400847 .get_mclk_od = pp_dpm_get_mclk_od,
848 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -0400849 .read_sensor = pp_dpm_read_sensor,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500850};
851
Jammy Zhouac885b32015-07-21 17:43:02 +0800852static int amd_pp_instance_init(struct amd_pp_init *pp_init,
853 struct amd_powerplay *amd_pp)
854{
855 int ret;
856 struct pp_instance *handle;
857
858 handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
859 if (handle == NULL)
860 return -ENOMEM;
861
Rex Zhua969e162015-12-29 13:56:03 +0800862 handle->pp_valid = PP_VALID;
863
Jammy Zhouac885b32015-07-21 17:43:02 +0800864 ret = smum_init(pp_init, handle);
865 if (ret)
Jammy Zhou3bace352015-07-21 21:18:15 +0800866 goto fail_smum;
867
868 ret = hwmgr_init(pp_init, handle);
869 if (ret)
870 goto fail_hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800871
Rex Zhue92a0372015-09-23 15:14:54 +0800872 ret = eventmgr_init(handle);
873 if (ret)
874 goto fail_eventmgr;
875
Jammy Zhouac885b32015-07-21 17:43:02 +0800876 amd_pp->pp_handle = handle;
877 return 0;
Jammy Zhou3bace352015-07-21 21:18:15 +0800878
Rex Zhue92a0372015-09-23 15:14:54 +0800879fail_eventmgr:
880 hwmgr_fini(handle->hwmgr);
Jammy Zhou3bace352015-07-21 21:18:15 +0800881fail_hwmgr:
882 smum_fini(handle->smu_mgr);
883fail_smum:
884 kfree(handle);
885 return ret;
Jammy Zhouac885b32015-07-21 17:43:02 +0800886}
887
888static int amd_pp_instance_fini(void *handle)
889{
890 struct pp_instance *instance = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +0800891
Jammy Zhouac885b32015-07-21 17:43:02 +0800892 if (instance == NULL)
893 return -EINVAL;
894
Rex Zhue92a0372015-09-23 15:14:54 +0800895 eventmgr_fini(instance->eventmgr);
896
Jammy Zhou3bace352015-07-21 21:18:15 +0800897 hwmgr_fini(instance->hwmgr);
898
Jammy Zhouac885b32015-07-21 17:43:02 +0800899 smum_fini(instance->smu_mgr);
900
901 kfree(handle);
902 return 0;
903}
904
Alex Deucher1f7371b2015-12-02 17:46:21 -0500905int amd_powerplay_init(struct amd_pp_init *pp_init,
906 struct amd_powerplay *amd_pp)
907{
Jammy Zhouac885b32015-07-21 17:43:02 +0800908 int ret;
909
Alex Deucher1f7371b2015-12-02 17:46:21 -0500910 if (pp_init == NULL || amd_pp == NULL)
911 return -EINVAL;
912
Jammy Zhouac885b32015-07-21 17:43:02 +0800913 ret = amd_pp_instance_init(pp_init, amd_pp);
914
915 if (ret)
916 return ret;
917
Alex Deucher1f7371b2015-12-02 17:46:21 -0500918 amd_pp->ip_funcs = &pp_ip_funcs;
919 amd_pp->pp_funcs = &pp_dpm_funcs;
920
921 return 0;
922}
923
924int amd_powerplay_fini(void *handle)
925{
Jammy Zhouac885b32015-07-21 17:43:02 +0800926 amd_pp_instance_fini(handle);
927
Alex Deucher1f7371b2015-12-02 17:46:21 -0500928 return 0;
929}
Rex Zhu7fb72a12015-11-19 13:35:30 +0800930
Eric Huang4dcf9e62016-06-01 17:08:07 -0400931int amd_powerplay_reset(void *handle)
932{
933 struct pp_instance *instance = (struct pp_instance *)handle;
934 struct pp_eventmgr *eventmgr;
935 struct pem_event_data event_data = { {0} };
936 int ret;
937
938 if (instance == NULL)
939 return -EINVAL;
940
941 eventmgr = instance->eventmgr;
942 if (!eventmgr || !eventmgr->pp_eventmgr_fini)
943 return -EINVAL;
944
945 eventmgr->pp_eventmgr_fini(eventmgr);
946
947 ret = pp_sw_fini(handle);
948 if (ret)
949 return ret;
950
951 kfree(instance->hwmgr->ps);
952
953 ret = pp_sw_init(handle);
954 if (ret)
955 return ret;
956
957 hw_init_power_state_table(instance->hwmgr);
958
959 if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
960 return -EINVAL;
961
962 ret = eventmgr->pp_eventmgr_init(eventmgr);
963 if (ret)
964 return ret;
965
966 return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
967}
968
Rex Zhu7fb72a12015-11-19 13:35:30 +0800969/* export this function to DAL */
970
David Rokhvarg155f1127c2015-12-14 10:51:39 -0500971int amd_powerplay_display_configuration_change(void *handle,
972 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +0800973{
974 struct pp_hwmgr *hwmgr;
Rex Zhu7fb72a12015-11-19 13:35:30 +0800975
Rex Zhua969e162015-12-29 13:56:03 +0800976 PP_CHECK((struct pp_instance *)handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +0800977
978 hwmgr = ((struct pp_instance *)handle)->hwmgr;
979
980 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhue0b71a72015-12-29 10:25:19 +0800981
Rex Zhu7fb72a12015-11-19 13:35:30 +0800982 return 0;
983}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -0500984
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -0500985int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +0800986 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -0500987{
988 struct pp_hwmgr *hwmgr;
989
Rex Zhua969e162015-12-29 13:56:03 +0800990 PP_CHECK((struct pp_instance *)handle);
991
992 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -0500993 return -EINVAL;
994
995 hwmgr = ((struct pp_instance *)handle)->hwmgr;
996
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -0500997 return phm_get_dal_power_level(hwmgr, output);
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -0500998}
Rex Zhue273b042015-12-07 18:44:23 +0800999
1000int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001001 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001002{
1003 struct pp_hwmgr *hwmgr;
1004 struct amd_pp_simple_clock_info simple_clocks;
1005 struct pp_clock_info hw_clocks;
Rex Zhue273b042015-12-07 18:44:23 +08001006
Rex Zhufa9e6992015-12-29 13:56:03 +08001007 PP_CHECK((struct pp_instance *)handle);
1008
1009 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001010 return -EINVAL;
1011
1012 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1013
1014 phm_get_dal_power_level(hwmgr, &simple_clocks);
1015
1016 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
1017 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment))
1018 PP_ASSERT_WITH_CODE(0, "Error in PHM_GetPowerContainmentClockInfo", return -1);
1019 } else {
1020 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity))
1021 PP_ASSERT_WITH_CODE(0, "Error in PHM_GetClockInfo", return -1);
1022 }
1023
1024 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1025 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1026 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1027 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1028 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1029 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1030
1031 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1032 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1033
1034 clocks->max_clocks_state = simple_clocks.level;
1035
1036 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1037 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1038 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1039 }
1040
1041 return 0;
1042
1043}
1044
1045int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1046{
1047 int result = -1;
1048
1049 struct pp_hwmgr *hwmgr;
1050
Rex Zhufa9e6992015-12-29 13:56:03 +08001051 PP_CHECK((struct pp_instance *)handle);
1052
1053 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001054 return -EINVAL;
1055
1056 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1057
1058 result = phm_get_clock_by_type(hwmgr, type, clocks);
1059
1060 return result;
1061}
1062
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001063int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1064 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001065{
1066 int result = -1;
Rex Zhue273b042015-12-07 18:44:23 +08001067 struct pp_hwmgr *hwmgr;
1068
Rex Zhufa9e6992015-12-29 13:56:03 +08001069 PP_CHECK((struct pp_instance *)handle);
1070
1071 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001072 return -EINVAL;
1073
1074 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1075
1076 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
1077 result = phm_get_max_high_clocks(hwmgr, clocks);
1078
1079 return result;
1080}
1081