blob: 726425809eedbd9d85dd00356b400d9c94108f88 [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 */
Huang Rui7bd55422016-12-26 14:05:30 +080023#include "pp_debug.h"
Alex Deucher1f7371b2015-12-02 17:46:21 -050024#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/gfp.h>
Jammy Zhouac885b32015-07-21 17:43:02 +080027#include <linux/slab.h>
Alex Deucher1f7371b2015-12-02 17:46:21 -050028#include "amd_shared.h"
29#include "amd_powerplay.h"
Jammy Zhouac885b32015-07-21 17:43:02 +080030#include "pp_instance.h"
Rex Zhu577bbe02015-08-28 12:56:43 +080031#include "power_state.h"
Alex Deucher1f7371b2015-12-02 17:46:21 -050032
Rex Zhue5f23732017-09-29 13:57:54 +080033#define PP_DPM_DISABLED 0xCCCC
34
Rex Zhu6d07fe72017-09-25 18:51:50 +080035static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
36 void *input, void *output);
37
Rex Zhu1c863802016-12-28 19:43:23 +080038static inline int pp_check(struct pp_instance *handle)
39{
Rex Zhue1827a32017-09-28 16:12:51 +080040 if (handle == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080041 return -EINVAL;
Rex Zhua969e162015-12-29 13:56:03 +080042
Rex Zhub3b03052017-09-26 13:28:27 -040043 if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080044 return -EINVAL;
45
46 if (handle->pm_en == 0)
47 return PP_DPM_DISABLED;
48
Rex Zhub3b03052017-09-26 13:28:27 -040049 if (handle->hwmgr->hwmgr_func == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080050 return PP_DPM_DISABLED;
51
52 return 0;
53}
Rex Zhu7383bcb2016-03-30 11:35:50 +080054
Rex Zhu139a2852017-09-25 20:46:37 +080055static int amd_powerplay_create(struct amd_pp_init *pp_init,
56 void **handle)
57{
58 struct pp_instance *instance;
59
60 if (pp_init == NULL || handle == NULL)
61 return -EINVAL;
62
63 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
64 if (instance == NULL)
65 return -ENOMEM;
66
Rex Zhu139a2852017-09-25 20:46:37 +080067 instance->chip_family = pp_init->chip_family;
68 instance->chip_id = pp_init->chip_id;
69 instance->pm_en = pp_init->pm_en;
70 instance->feature_mask = pp_init->feature_mask;
71 instance->device = pp_init->device;
72 mutex_init(&instance->pp_lock);
73 *handle = instance;
74 return 0;
75}
76
77static int amd_powerplay_destroy(void *handle)
78{
79 struct pp_instance *instance = (struct pp_instance *)handle;
80
Eric Huang7b38a492017-10-31 17:35:28 -040081 kfree(instance->hwmgr->hardcode_pp_table);
82 instance->hwmgr->hardcode_pp_table = NULL;
83
Rex Zhu139a2852017-09-25 20:46:37 +080084 kfree(instance->hwmgr);
85 instance->hwmgr = NULL;
86
87 kfree(instance);
88 instance = NULL;
89 return 0;
90}
91
Alex Deucher1f7371b2015-12-02 17:46:21 -050092static int pp_early_init(void *handle)
93{
Rex Zhu1c863802016-12-28 19:43:23 +080094 int ret;
Rex Zhu139a2852017-09-25 20:46:37 +080095 struct pp_instance *pp_handle = NULL;
96
97 pp_handle = cgs_register_pp_handle(handle, amd_powerplay_create);
98
99 if (!pp_handle)
100 return -EINVAL;
Rex Zhu1c863802016-12-28 19:43:23 +0800101
Rex Zhub3b03052017-09-26 13:28:27 -0400102 ret = hwmgr_early_init(pp_handle);
Rex Zhu1c863802016-12-28 19:43:23 +0800103 if (ret)
Rex Zhub3b03052017-09-26 13:28:27 -0400104 return -EINVAL;
Rex Zhu1c863802016-12-28 19:43:23 +0800105
Alex Deucher1f7371b2015-12-02 17:46:21 -0500106 return 0;
107}
108
109static int pp_sw_init(void *handle)
110{
Rex Zhub3b03052017-09-26 13:28:27 -0400111 struct pp_hwmgr *hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800112 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800113 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800114
Rex Zhu1c863802016-12-28 19:43:23 +0800115 ret = pp_check(pp_handle);
Jammy Zhou3bace352015-07-21 21:18:15 +0800116
Rex Zhue5f23732017-09-29 13:57:54 +0800117 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400118 hwmgr = pp_handle->hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800119
Rex Zhub3b03052017-09-26 13:28:27 -0400120 if (hwmgr->smumgr_funcs->smu_init == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800121 return -EINVAL;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800122
Rex Zhub3b03052017-09-26 13:28:27 -0400123 ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
Jammy Zhou3bace352015-07-21 21:18:15 +0800124
pding9953b722017-10-26 09:30:38 +0800125 pr_debug("amdgpu: powerplay sw initialized\n");
Huang Rui167112b2016-12-14 16:26:54 +0800126 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800127 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500128}
129
130static int pp_sw_fini(void *handle)
131{
Rex Zhub3b03052017-09-26 13:28:27 -0400132 struct pp_hwmgr *hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800133 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800134 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800135
Rex Zhu1c863802016-12-28 19:43:23 +0800136 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800137 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400138 hwmgr = pp_handle->hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800139
Rex Zhub3b03052017-09-26 13:28:27 -0400140 if (hwmgr->smumgr_funcs->smu_fini == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800141 return -EINVAL;
Jammy Zhou3bace352015-07-21 21:18:15 +0800142
Rex Zhub3b03052017-09-26 13:28:27 -0400143 ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhu1c863802016-12-28 19:43:23 +0800144 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800145 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500146}
147
148static int pp_hw_init(void *handle)
149{
Jammy Zhouac885b32015-07-21 17:43:02 +0800150 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800151 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhub3b03052017-09-26 13:28:27 -0400152 struct pp_hwmgr *hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800153
Rex Zhu1c863802016-12-28 19:43:23 +0800154 ret = pp_check(pp_handle);
Jammy Zhouac885b32015-07-21 17:43:02 +0800155
Rex Zhue5f23732017-09-29 13:57:54 +0800156 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400157 hwmgr = pp_handle->hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800158
Rex Zhub3b03052017-09-26 13:28:27 -0400159 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800160 return -EINVAL;
Jammy Zhouac885b32015-07-21 17:43:02 +0800161
Rex Zhub3b03052017-09-26 13:28:27 -0400162 if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Rex Zhu1c863802016-12-28 19:43:23 +0800163 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400164 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhu1c863802016-12-28 19:43:23 +0800165 return -EINVAL;;
166 }
167 if (ret == PP_DPM_DISABLED)
Rex Zhue5f23732017-09-29 13:57:54 +0800168 goto exit;
169 ret = hwmgr_hw_init(pp_handle);
170 if (ret)
171 goto exit;
Jammy Zhouac885b32015-07-21 17:43:02 +0800172 }
Rex Zhue5f23732017-09-29 13:57:54 +0800173 return ret;
174exit:
Rex Zhu1c863802016-12-28 19:43:23 +0800175 pp_handle->pm_en = 0;
Rex Zhue5f23732017-09-29 13:57:54 +0800176 cgs_notify_dpm_enabled(hwmgr->device, false);
177 return 0;
178
Alex Deucher1f7371b2015-12-02 17:46:21 -0500179}
180
181static int pp_hw_fini(void *handle)
182{
Rex Zhu1c863802016-12-28 19:43:23 +0800183 struct pp_instance *pp_handle = (struct pp_instance *)handle;
184 int ret = 0;
Jammy Zhouac885b32015-07-21 17:43:02 +0800185
Rex Zhu1c863802016-12-28 19:43:23 +0800186 ret = pp_check(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800187 if (ret == 0)
Rex Zhu1c863802016-12-28 19:43:23 +0800188 hwmgr_hw_fini(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800189
Alex Deucher1f7371b2015-12-02 17:46:21 -0500190 return 0;
191}
192
Rex Zhu6d07fe72017-09-25 18:51:50 +0800193static int pp_late_init(void *handle)
194{
195 struct pp_instance *pp_handle = (struct pp_instance *)handle;
196 int ret = 0;
197
198 ret = pp_check(pp_handle);
199 if (ret == 0)
200 pp_dpm_dispatch_tasks(pp_handle,
201 AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
202
203 return 0;
204}
205
Rex Zhu139a2852017-09-25 20:46:37 +0800206static void pp_late_fini(void *handle)
207{
208 amd_powerplay_destroy(handle);
209}
210
211
Alex Deucher1f7371b2015-12-02 17:46:21 -0500212static bool pp_is_idle(void *handle)
213{
Edward O'Callaghaned5121a2016-07-12 10:17:52 +1000214 return false;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500215}
216
217static int pp_wait_for_idle(void *handle)
218{
219 return 0;
220}
221
222static int pp_sw_reset(void *handle)
223{
224 return 0;
225}
226
Alex Deucher1f7371b2015-12-02 17:46:21 -0500227static int pp_set_powergating_state(void *handle,
228 enum amd_powergating_state state)
229{
Eric Huang65f85e72016-02-11 15:54:45 -0500230 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800231 struct pp_instance *pp_handle = (struct pp_instance *)handle;
232 int ret = 0;
Eric Huang65f85e72016-02-11 15:54:45 -0500233
Rex Zhu1c863802016-12-28 19:43:23 +0800234 ret = pp_check(pp_handle);
Eric Huang65f85e72016-02-11 15:54:45 -0500235
Rex Zhuae979882017-09-29 14:36:15 +0800236 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800237 return ret;
Eric Huang65f85e72016-02-11 15:54:45 -0500238
Rex Zhu1c863802016-12-28 19:43:23 +0800239 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800240
241 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800242 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800243 return 0;
244 }
Eric Huang65f85e72016-02-11 15:54:45 -0500245
246 /* Enable/disable GFX per cu powergating through SMU */
247 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
Andrew F. Davis93a4aec2017-03-15 11:20:24 -0500248 state == AMD_PG_STATE_GATE);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500249}
250
251static int pp_suspend(void *handle)
252{
Rex Zhu1c863802016-12-28 19:43:23 +0800253 struct pp_instance *pp_handle = (struct pp_instance *)handle;
254 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800255
Rex Zhu1c863802016-12-28 19:43:23 +0800256 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800257 if (ret == 0)
258 hwmgr_hw_suspend(pp_handle);
259 return 0;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500260}
261
262static int pp_resume(void *handle)
263{
Rex Zhub3b03052017-09-26 13:28:27 -0400264 struct pp_hwmgr *hwmgr;
Rex Zhue5f23732017-09-29 13:57:54 +0800265 int ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800266 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800267
Rex Zhue5f23732017-09-29 13:57:54 +0800268 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800269
Rex Zhue5f23732017-09-29 13:57:54 +0800270 if (ret < 0)
271 return ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800272
Rex Zhub3b03052017-09-26 13:28:27 -0400273 hwmgr = pp_handle->hwmgr;
Rex Zhue0b71a72015-12-29 10:25:19 +0800274
Rex Zhub3b03052017-09-26 13:28:27 -0400275 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800276 return -EINVAL;
277
Rex Zhue5f23732017-09-29 13:57:54 +0800278 if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800279 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400280 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhue5f23732017-09-29 13:57:54 +0800281 return -EINVAL;
Rex Zhue0b71a72015-12-29 10:25:19 +0800282 }
283
Rex Zhue5f23732017-09-29 13:57:54 +0800284 if (ret == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800285 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800286
Rex Zhudf1e6392017-09-01 13:46:20 +0800287 return hwmgr_hw_resume(pp_handle);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500288}
289
290const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400291 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500292 .early_init = pp_early_init,
Rex Zhu6d07fe72017-09-25 18:51:50 +0800293 .late_init = pp_late_init,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500294 .sw_init = pp_sw_init,
295 .sw_fini = pp_sw_fini,
296 .hw_init = pp_hw_init,
297 .hw_fini = pp_hw_fini,
Rex Zhu139a2852017-09-25 20:46:37 +0800298 .late_fini = pp_late_fini,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500299 .suspend = pp_suspend,
300 .resume = pp_resume,
301 .is_idle = pp_is_idle,
302 .wait_for_idle = pp_wait_for_idle,
303 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800304 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500305 .set_powergating_state = pp_set_powergating_state,
306};
307
308static int pp_dpm_load_fw(void *handle)
309{
310 return 0;
311}
312
313static int pp_dpm_fw_loading_complete(void *handle)
314{
315 return 0;
316}
317
Rex Zhu3811f8f2017-09-26 13:39:38 +0800318static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
319{
320 struct pp_hwmgr *hwmgr;
321 struct pp_instance *pp_handle = (struct pp_instance *)handle;
322 int ret = 0;
323
324 ret = pp_check(pp_handle);
325
326 if (ret)
327 return ret;
328
329 hwmgr = pp_handle->hwmgr;
330
331 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
332 pr_info("%s was not implemented.\n", __func__);
333 return 0;
334 }
335
336 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
337}
338
Rex Zhu9947f702017-08-29 16:08:56 +0800339static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
340 enum amd_dpm_forced_level *level)
341{
342 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
343 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
344 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
345 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
346
347 if (!(hwmgr->dpm_level & profile_mode_mask)) {
348 /* enter umd pstate, save current level, disable gfx cg*/
349 if (*level & profile_mode_mask) {
350 hwmgr->saved_dpm_level = hwmgr->dpm_level;
351 hwmgr->en_umd_pstate = true;
352 cgs_set_clockgating_state(hwmgr->device,
353 AMD_IP_BLOCK_TYPE_GFX,
354 AMD_CG_STATE_UNGATE);
355 cgs_set_powergating_state(hwmgr->device,
356 AMD_IP_BLOCK_TYPE_GFX,
357 AMD_PG_STATE_UNGATE);
358 }
359 } else {
360 /* exit umd pstate, restore level, enable gfx cg*/
361 if (!(*level & profile_mode_mask)) {
362 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
363 *level = hwmgr->saved_dpm_level;
364 hwmgr->en_umd_pstate = false;
365 cgs_set_clockgating_state(hwmgr->device,
366 AMD_IP_BLOCK_TYPE_GFX,
367 AMD_CG_STATE_GATE);
368 cgs_set_powergating_state(hwmgr->device,
369 AMD_IP_BLOCK_TYPE_GFX,
370 AMD_PG_STATE_GATE);
371 }
372 }
373}
374
Alex Deucher1f7371b2015-12-02 17:46:21 -0500375static int pp_dpm_force_performance_level(void *handle,
376 enum amd_dpm_forced_level level)
377{
Rex Zhu577bbe02015-08-28 12:56:43 +0800378 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800379 struct pp_instance *pp_handle = (struct pp_instance *)handle;
380 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800381
Rex Zhu1c863802016-12-28 19:43:23 +0800382 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800383
Rex Zhuae979882017-09-29 14:36:15 +0800384 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800385 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800386
387 hwmgr = pp_handle->hwmgr;
388
Rex Zhu9947f702017-08-29 16:08:56 +0800389 if (level == hwmgr->dpm_level)
390 return 0;
391
Rex Zhu7383bcb2016-03-30 11:35:50 +0800392 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800393 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800394 return 0;
395 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800396
Rex Zhu2a507102017-02-20 17:07:36 +0800397 mutex_lock(&pp_handle->pp_lock);
Rex Zhu9947f702017-08-29 16:08:56 +0800398 pp_dpm_en_umd_pstate(hwmgr, &level);
399 hwmgr->request_dpm_level = level;
Rex Zhudf1e6392017-09-01 13:46:20 +0800400 hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
Rex Zhu9947f702017-08-29 16:08:56 +0800401 ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
402 if (!ret)
403 hwmgr->dpm_level = hwmgr->request_dpm_level;
404
Rex Zhu2a507102017-02-20 17:07:36 +0800405 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500406 return 0;
407}
Rex Zhu577bbe02015-08-28 12:56:43 +0800408
Alex Deucher1f7371b2015-12-02 17:46:21 -0500409static enum amd_dpm_forced_level pp_dpm_get_performance_level(
410 void *handle)
411{
Rex Zhu577bbe02015-08-28 12:56:43 +0800412 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800413 struct pp_instance *pp_handle = (struct pp_instance *)handle;
414 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800415 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800416
Rex Zhu1c863802016-12-28 19:43:23 +0800417 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800418
Rex Zhuae979882017-09-29 14:36:15 +0800419 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800420 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800421
Rex Zhu1c863802016-12-28 19:43:23 +0800422 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800423 mutex_lock(&pp_handle->pp_lock);
424 level = hwmgr->dpm_level;
425 mutex_unlock(&pp_handle->pp_lock);
426 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500427}
Rex Zhu577bbe02015-08-28 12:56:43 +0800428
Rex Zhuf93f0c32017-09-06 16:08:03 +0800429static uint32_t pp_dpm_get_sclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500430{
Rex Zhu577bbe02015-08-28 12:56:43 +0800431 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800432 struct pp_instance *pp_handle = (struct pp_instance *)handle;
433 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800434 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800435
Rex Zhu1c863802016-12-28 19:43:23 +0800436 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800437
Rex Zhuae979882017-09-29 14:36:15 +0800438 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800439 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800440
Rex Zhu1c863802016-12-28 19:43:23 +0800441 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800442
443 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800444 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800445 return 0;
446 }
Rex Zhu2a507102017-02-20 17:07:36 +0800447 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800448 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800449 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800450 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500451}
Rex Zhu577bbe02015-08-28 12:56:43 +0800452
Rex Zhuf93f0c32017-09-06 16:08:03 +0800453static uint32_t pp_dpm_get_mclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500454{
Rex Zhu577bbe02015-08-28 12:56:43 +0800455 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800456 struct pp_instance *pp_handle = (struct pp_instance *)handle;
457 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800458 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800459
Rex Zhu1c863802016-12-28 19:43:23 +0800460 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800461
Rex Zhuae979882017-09-29 14:36:15 +0800462 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800463 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800464
Rex Zhu1c863802016-12-28 19:43:23 +0800465 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800466
467 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800468 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800469 return 0;
470 }
Rex Zhu2a507102017-02-20 17:07:36 +0800471 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800472 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800473 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800474 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500475}
Rex Zhu577bbe02015-08-28 12:56:43 +0800476
Rex Zhuf93f0c32017-09-06 16:08:03 +0800477static void pp_dpm_powergate_vce(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500478{
Rex Zhu577bbe02015-08-28 12:56:43 +0800479 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800480 struct pp_instance *pp_handle = (struct pp_instance *)handle;
481 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800482
Rex Zhu1c863802016-12-28 19:43:23 +0800483 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800484
Rex Zhuae979882017-09-29 14:36:15 +0800485 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800486 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800487
Rex Zhu1c863802016-12-28 19:43:23 +0800488 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800489
490 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800491 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800492 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800493 }
Rex Zhu2a507102017-02-20 17:07:36 +0800494 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800495 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800496 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500497}
Rex Zhu577bbe02015-08-28 12:56:43 +0800498
Rex Zhuf93f0c32017-09-06 16:08:03 +0800499static void pp_dpm_powergate_uvd(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500500{
Rex Zhu577bbe02015-08-28 12:56:43 +0800501 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800502 struct pp_instance *pp_handle = (struct pp_instance *)handle;
503 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800504
Rex Zhu1c863802016-12-28 19:43:23 +0800505 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800506
Rex Zhuae979882017-09-29 14:36:15 +0800507 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800508 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800509
Rex Zhu1c863802016-12-28 19:43:23 +0800510 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800511
512 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800513 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800514 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800515 }
Rex Zhu2a507102017-02-20 17:07:36 +0800516 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800517 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800518 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800519}
520
Rex Zhudf1e6392017-09-01 13:46:20 +0800521static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
Baoyou Xief8a4c112016-09-30 17:58:42 +0800522 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500523{
Rex Zhu577bbe02015-08-28 12:56:43 +0800524 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800525 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800526
Rex Zhu1c863802016-12-28 19:43:23 +0800527 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800528
Rex Zhuae979882017-09-29 14:36:15 +0800529 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800530 return ret;
Rex Zhudf1e6392017-09-01 13:46:20 +0800531
Rex Zhu2a507102017-02-20 17:07:36 +0800532 mutex_lock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800533 ret = hwmgr_handle_task(pp_handle, task_id, input, output);
Rex Zhu2a507102017-02-20 17:07:36 +0800534 mutex_unlock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800535
Rex Zhu577bbe02015-08-28 12:56:43 +0800536 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500537}
Rex Zhu577bbe02015-08-28 12:56:43 +0800538
Baoyou Xief8a4c112016-09-30 17:58:42 +0800539static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500540{
Rex Zhu577bbe02015-08-28 12:56:43 +0800541 struct pp_hwmgr *hwmgr;
542 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800543 struct pp_instance *pp_handle = (struct pp_instance *)handle;
544 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800545 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800546
Rex Zhu1c863802016-12-28 19:43:23 +0800547 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800548
Rex Zhuae979882017-09-29 14:36:15 +0800549 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800550 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800551
Rex Zhu1c863802016-12-28 19:43:23 +0800552 hwmgr = pp_handle->hwmgr;
553
554 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800555 return -EINVAL;
556
Rex Zhu2a507102017-02-20 17:07:36 +0800557 mutex_lock(&pp_handle->pp_lock);
558
Rex Zhu577bbe02015-08-28 12:56:43 +0800559 state = hwmgr->current_ps;
560
561 switch (state->classification.ui_label) {
562 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800563 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300564 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800565 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800566 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300567 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800568 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800569 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300570 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800571 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500572 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800573 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500574 else
Rex Zhu2a507102017-02-20 17:07:36 +0800575 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300576 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800577 }
Rex Zhu2a507102017-02-20 17:07:36 +0800578 mutex_unlock(&pp_handle->pp_lock);
579
580 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500581}
Rex Zhu577bbe02015-08-28 12:56:43 +0800582
Rex Zhuf93f0c32017-09-06 16:08:03 +0800583static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
Rex Zhucac9a192015-10-16 11:48:21 +0800584{
585 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800586 struct pp_instance *pp_handle = (struct pp_instance *)handle;
587 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800588
Rex Zhu1c863802016-12-28 19:43:23 +0800589 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800590
Rex Zhuae979882017-09-29 14:36:15 +0800591 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800592 return;
Rex Zhucac9a192015-10-16 11:48:21 +0800593
Rex Zhu1c863802016-12-28 19:43:23 +0800594 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800595
596 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800597 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800598 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800599 }
Rex Zhu2a507102017-02-20 17:07:36 +0800600 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800601 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
Rex Zhu2a507102017-02-20 17:07:36 +0800602 mutex_unlock(&pp_handle->pp_lock);
Rex Zhucac9a192015-10-16 11:48:21 +0800603}
604
Rex Zhuf93f0c32017-09-06 16:08:03 +0800605static uint32_t pp_dpm_get_fan_control_mode(void *handle)
Rex Zhucac9a192015-10-16 11:48:21 +0800606{
607 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800608 struct pp_instance *pp_handle = (struct pp_instance *)handle;
609 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800610 uint32_t mode = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800611
Rex Zhu1c863802016-12-28 19:43:23 +0800612 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800613
Rex Zhuae979882017-09-29 14:36:15 +0800614 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800615 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800616
Rex Zhu1c863802016-12-28 19:43:23 +0800617 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800618
619 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800620 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800621 return 0;
622 }
Rex Zhu2a507102017-02-20 17:07:36 +0800623 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800624 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
Rex Zhu2a507102017-02-20 17:07:36 +0800625 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800626 return mode;
Rex Zhucac9a192015-10-16 11:48:21 +0800627}
628
629static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
630{
631 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800632 struct pp_instance *pp_handle = (struct pp_instance *)handle;
633 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800634
Rex Zhu1c863802016-12-28 19:43:23 +0800635 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800636
Rex Zhuae979882017-09-29 14:36:15 +0800637 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800638 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800639
Rex Zhu1c863802016-12-28 19:43:23 +0800640 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800641
642 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800643 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800644 return 0;
645 }
Rex Zhu2a507102017-02-20 17:07:36 +0800646 mutex_lock(&pp_handle->pp_lock);
647 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
648 mutex_unlock(&pp_handle->pp_lock);
649 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800650}
651
652static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
653{
654 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800655 struct pp_instance *pp_handle = (struct pp_instance *)handle;
656 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800657
Rex Zhu1c863802016-12-28 19:43:23 +0800658 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800659
Rex Zhuae979882017-09-29 14:36:15 +0800660 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800661 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800662
Rex Zhu1c863802016-12-28 19:43:23 +0800663 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800664
665 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800666 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800667 return 0;
668 }
Rex Zhucac9a192015-10-16 11:48:21 +0800669
Rex Zhu2a507102017-02-20 17:07:36 +0800670 mutex_lock(&pp_handle->pp_lock);
671 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
672 mutex_unlock(&pp_handle->pp_lock);
673 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800674}
675
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300676static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
677{
678 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800679 struct pp_instance *pp_handle = (struct pp_instance *)handle;
680 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300681
Rex Zhu1c863802016-12-28 19:43:23 +0800682 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300683
Rex Zhuae979882017-09-29 14:36:15 +0800684 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800685 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300686
Rex Zhu1c863802016-12-28 19:43:23 +0800687 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300688
689 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
690 return -EINVAL;
691
Rex Zhu2a507102017-02-20 17:07:36 +0800692 mutex_lock(&pp_handle->pp_lock);
693 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
694 mutex_unlock(&pp_handle->pp_lock);
695 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300696}
697
Rex Zhucac9a192015-10-16 11:48:21 +0800698static int pp_dpm_get_temperature(void *handle)
699{
700 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800701 struct pp_instance *pp_handle = (struct pp_instance *)handle;
702 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800703
Rex Zhu1c863802016-12-28 19:43:23 +0800704 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800705
Rex Zhuae979882017-09-29 14:36:15 +0800706 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800707 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800708
Rex Zhu1c863802016-12-28 19:43:23 +0800709 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800710
711 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800712 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800713 return 0;
714 }
Rex Zhu2a507102017-02-20 17:07:36 +0800715 mutex_lock(&pp_handle->pp_lock);
716 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
717 mutex_unlock(&pp_handle->pp_lock);
718 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800719}
Rex Zhu577bbe02015-08-28 12:56:43 +0800720
Eric Huangf3898ea2015-12-11 16:24:34 -0500721static int pp_dpm_get_pp_num_states(void *handle,
722 struct pp_states_info *data)
723{
724 struct pp_hwmgr *hwmgr;
725 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800726 struct pp_instance *pp_handle = (struct pp_instance *)handle;
727 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500728
Rex Zhu1c863802016-12-28 19:43:23 +0800729 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500730
Rex Zhuae979882017-09-29 14:36:15 +0800731 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800732 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500733
Rex Zhu1c863802016-12-28 19:43:23 +0800734 hwmgr = pp_handle->hwmgr;
735
736 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500737 return -EINVAL;
738
Rex Zhu2a507102017-02-20 17:07:36 +0800739 mutex_lock(&pp_handle->pp_lock);
740
Eric Huangf3898ea2015-12-11 16:24:34 -0500741 data->nums = hwmgr->num_ps;
742
743 for (i = 0; i < hwmgr->num_ps; i++) {
744 struct pp_power_state *state = (struct pp_power_state *)
745 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
746 switch (state->classification.ui_label) {
747 case PP_StateUILabel_Battery:
748 data->states[i] = POWER_STATE_TYPE_BATTERY;
749 break;
750 case PP_StateUILabel_Balanced:
751 data->states[i] = POWER_STATE_TYPE_BALANCED;
752 break;
753 case PP_StateUILabel_Performance:
754 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
755 break;
756 default:
757 if (state->classification.flags & PP_StateClassificationFlag_Boot)
758 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
759 else
760 data->states[i] = POWER_STATE_TYPE_DEFAULT;
761 }
762 }
Rex Zhu2a507102017-02-20 17:07:36 +0800763 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500764 return 0;
765}
766
767static int pp_dpm_get_pp_table(void *handle, char **table)
768{
769 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800770 struct pp_instance *pp_handle = (struct pp_instance *)handle;
771 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800772 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500773
Rex Zhu1c863802016-12-28 19:43:23 +0800774 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500775
Rex Zhuae979882017-09-29 14:36:15 +0800776 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800777 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500778
Rex Zhu1c863802016-12-28 19:43:23 +0800779 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800780
Eric Huang4dcf9e62016-06-01 17:08:07 -0400781 if (!hwmgr->soft_pp_table)
782 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500783
Rex Zhu2a507102017-02-20 17:07:36 +0800784 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400785 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800786 size = hwmgr->soft_pp_table_size;
787 mutex_unlock(&pp_handle->pp_lock);
788 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500789}
790
791static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
792{
793 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800794 struct pp_instance *pp_handle = (struct pp_instance *)handle;
795 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500796
Rex Zhu1c863802016-12-28 19:43:23 +0800797 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500798
Rex Zhuae979882017-09-29 14:36:15 +0800799 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800800 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500801
Rex Zhu1c863802016-12-28 19:43:23 +0800802 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800803 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400804 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000805 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
806 hwmgr->soft_pp_table_size,
807 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800808 if (!hwmgr->hardcode_pp_table) {
809 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400810 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800811 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800812 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500813
Eric Huang4dcf9e62016-06-01 17:08:07 -0400814 memcpy(hwmgr->hardcode_pp_table, buf, size);
815
816 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800817 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400818
Eric Huangdd4bdf32017-03-01 15:49:31 -0500819 ret = amd_powerplay_reset(handle);
820 if (ret)
821 return ret;
822
823 if (hwmgr->hwmgr_func->avfs_control) {
824 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
825 if (ret)
826 return ret;
827 }
828
829 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500830}
831
832static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400833 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500834{
835 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800836 struct pp_instance *pp_handle = (struct pp_instance *)handle;
837 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500838
Rex Zhu1c863802016-12-28 19:43:23 +0800839 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500840
Rex Zhuae979882017-09-29 14:36:15 +0800841 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800842 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500843
Rex Zhu1c863802016-12-28 19:43:23 +0800844 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800845
846 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800847 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800848 return 0;
849 }
Rex Zhu2a507102017-02-20 17:07:36 +0800850 mutex_lock(&pp_handle->pp_lock);
851 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
852 mutex_unlock(&pp_handle->pp_lock);
853 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500854}
855
856static int pp_dpm_print_clock_levels(void *handle,
857 enum pp_clock_type type, char *buf)
858{
859 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800860 struct pp_instance *pp_handle = (struct pp_instance *)handle;
861 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500862
Rex Zhu1c863802016-12-28 19:43:23 +0800863 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500864
Rex Zhuae979882017-09-29 14:36:15 +0800865 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800866 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500867
Rex Zhu1c863802016-12-28 19:43:23 +0800868 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500869
Rex Zhu7383bcb2016-03-30 11:35:50 +0800870 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800871 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800872 return 0;
873 }
Rex Zhu2a507102017-02-20 17:07:36 +0800874 mutex_lock(&pp_handle->pp_lock);
875 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
876 mutex_unlock(&pp_handle->pp_lock);
877 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500878}
879
Eric Huang428bafa2016-05-12 14:51:21 -0400880static int pp_dpm_get_sclk_od(void *handle)
881{
882 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800883 struct pp_instance *pp_handle = (struct pp_instance *)handle;
884 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400885
Rex Zhu1c863802016-12-28 19:43:23 +0800886 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400887
Rex Zhuae979882017-09-29 14:36:15 +0800888 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800889 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400890
Rex Zhu1c863802016-12-28 19:43:23 +0800891 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400892
893 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800894 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400895 return 0;
896 }
Rex Zhu2a507102017-02-20 17:07:36 +0800897 mutex_lock(&pp_handle->pp_lock);
898 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
899 mutex_unlock(&pp_handle->pp_lock);
900 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400901}
902
903static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
904{
905 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800906 struct pp_instance *pp_handle = (struct pp_instance *)handle;
907 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400908
Rex Zhu1c863802016-12-28 19:43:23 +0800909 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400910
Rex Zhuae979882017-09-29 14:36:15 +0800911 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800912 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400913
Rex Zhu1c863802016-12-28 19:43:23 +0800914 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400915
916 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800917 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400918 return 0;
919 }
920
Rex Zhu2a507102017-02-20 17:07:36 +0800921 mutex_lock(&pp_handle->pp_lock);
922 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400923 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800924 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400925}
926
Eric Huangf2bdc052016-05-24 15:11:17 -0400927static int pp_dpm_get_mclk_od(void *handle)
928{
929 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800930 struct pp_instance *pp_handle = (struct pp_instance *)handle;
931 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400932
Rex Zhu1c863802016-12-28 19:43:23 +0800933 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400934
Rex Zhuae979882017-09-29 14:36:15 +0800935 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800936 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400937
Rex Zhu1c863802016-12-28 19:43:23 +0800938 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400939
940 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800941 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400942 return 0;
943 }
Rex Zhu2a507102017-02-20 17:07:36 +0800944 mutex_lock(&pp_handle->pp_lock);
945 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
946 mutex_unlock(&pp_handle->pp_lock);
947 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400948}
949
950static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
951{
952 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800953 struct pp_instance *pp_handle = (struct pp_instance *)handle;
954 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400955
Rex Zhu1c863802016-12-28 19:43:23 +0800956 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400957
Rex Zhuae979882017-09-29 14:36:15 +0800958 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800959 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400960
Rex Zhu1c863802016-12-28 19:43:23 +0800961 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400962
963 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800964 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400965 return 0;
966 }
Rex Zhu2a507102017-02-20 17:07:36 +0800967 mutex_lock(&pp_handle->pp_lock);
968 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
969 mutex_unlock(&pp_handle->pp_lock);
970 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400971}
972
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500973static int pp_dpm_read_sensor(void *handle, int idx,
974 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400975{
976 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800977 struct pp_instance *pp_handle = (struct pp_instance *)handle;
978 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400979
Rex Zhu1c863802016-12-28 19:43:23 +0800980 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400981
Rex Zhuae979882017-09-29 14:36:15 +0800982 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800983 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400984
Rex Zhu1c863802016-12-28 19:43:23 +0800985 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400986
987 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800988 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400989 return 0;
990 }
991
Rex Zhu2a507102017-02-20 17:07:36 +0800992 mutex_lock(&pp_handle->pp_lock);
993 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
994 mutex_unlock(&pp_handle->pp_lock);
995
996 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400997}
998
Alex Deucher597be302016-10-07 13:52:43 -0400999static struct amd_vce_state*
1000pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
1001{
1002 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001003 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1004 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -04001005
Rex Zhu1c863802016-12-28 19:43:23 +08001006 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -04001007
Rex Zhuae979882017-09-29 14:36:15 +08001008 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001009 return NULL;
1010
1011 hwmgr = pp_handle->hwmgr;
1012
1013 if (hwmgr && idx < hwmgr->num_vce_state_tables)
1014 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -04001015 return NULL;
1016}
1017
Eric Huang34bb2732016-09-12 16:17:44 -04001018static int pp_dpm_reset_power_profile_state(void *handle,
1019 struct amd_pp_profile *request)
1020{
1021 struct pp_hwmgr *hwmgr;
1022 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1023
1024 if (!request || pp_check(pp_handle))
1025 return -EINVAL;
1026
1027 hwmgr = pp_handle->hwmgr;
1028
1029 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1030 pr_info("%s was not implemented.\n", __func__);
1031 return 0;
1032 }
1033
1034 if (request->type == AMD_PP_GFX_PROFILE) {
1035 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1036 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1037 &hwmgr->gfx_power_profile);
1038 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1039 hwmgr->compute_power_profile =
1040 hwmgr->default_compute_power_profile;
1041 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1042 &hwmgr->compute_power_profile);
1043 } else
1044 return -EINVAL;
1045}
1046
1047static int pp_dpm_get_power_profile_state(void *handle,
1048 struct amd_pp_profile *query)
1049{
1050 struct pp_hwmgr *hwmgr;
1051 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1052
1053 if (!query || pp_check(pp_handle))
1054 return -EINVAL;
1055
1056 hwmgr = pp_handle->hwmgr;
1057
1058 if (query->type == AMD_PP_GFX_PROFILE)
1059 memcpy(query, &hwmgr->gfx_power_profile,
1060 sizeof(struct amd_pp_profile));
1061 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1062 memcpy(query, &hwmgr->compute_power_profile,
1063 sizeof(struct amd_pp_profile));
1064 else
1065 return -EINVAL;
1066
1067 return 0;
1068}
1069
1070static int pp_dpm_set_power_profile_state(void *handle,
1071 struct amd_pp_profile *request)
1072{
1073 struct pp_hwmgr *hwmgr;
1074 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1075 int ret = -1;
1076
1077 if (!request || pp_check(pp_handle))
1078 return -EINVAL;
1079
1080 hwmgr = pp_handle->hwmgr;
1081
1082 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1083 pr_info("%s was not implemented.\n", __func__);
1084 return 0;
1085 }
1086
1087 if (request->min_sclk ||
1088 request->min_mclk ||
1089 request->activity_threshold ||
1090 request->up_hyst ||
1091 request->down_hyst) {
1092 if (request->type == AMD_PP_GFX_PROFILE)
1093 memcpy(&hwmgr->gfx_power_profile, request,
1094 sizeof(struct amd_pp_profile));
1095 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1096 memcpy(&hwmgr->compute_power_profile, request,
1097 sizeof(struct amd_pp_profile));
1098 else
1099 return -EINVAL;
1100
1101 if (request->type == hwmgr->current_power_profile)
1102 ret = hwmgr->hwmgr_func->set_power_profile_state(
1103 hwmgr,
1104 request);
1105 } else {
1106 /* set power profile if it exists */
1107 switch (request->type) {
1108 case AMD_PP_GFX_PROFILE:
1109 ret = hwmgr->hwmgr_func->set_power_profile_state(
1110 hwmgr,
1111 &hwmgr->gfx_power_profile);
1112 break;
1113 case AMD_PP_COMPUTE_PROFILE:
1114 ret = hwmgr->hwmgr_func->set_power_profile_state(
1115 hwmgr,
1116 &hwmgr->compute_power_profile);
1117 break;
1118 default:
1119 return -EINVAL;
1120 }
1121 }
1122
1123 if (!ret)
1124 hwmgr->current_power_profile = request->type;
1125
1126 return 0;
1127}
1128
1129static int pp_dpm_switch_power_profile(void *handle,
1130 enum amd_pp_profile_type type)
1131{
1132 struct pp_hwmgr *hwmgr;
1133 struct amd_pp_profile request = {0};
1134 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1135
1136 if (pp_check(pp_handle))
1137 return -EINVAL;
1138
1139 hwmgr = pp_handle->hwmgr;
1140
1141 if (hwmgr->current_power_profile != type) {
1142 request.type = type;
1143 pp_dpm_set_power_profile_state(handle, &request);
1144 }
1145
1146 return 0;
1147}
1148
Rex Zhuf93f0c32017-09-06 16:08:03 +08001149const struct amd_pm_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001150 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001151 .load_firmware = pp_dpm_load_fw,
1152 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1153 .force_performance_level = pp_dpm_force_performance_level,
1154 .get_performance_level = pp_dpm_get_performance_level,
1155 .get_current_power_state = pp_dpm_get_current_power_state,
1156 .get_sclk = pp_dpm_get_sclk,
1157 .get_mclk = pp_dpm_get_mclk,
1158 .powergate_vce = pp_dpm_powergate_vce,
1159 .powergate_uvd = pp_dpm_powergate_uvd,
1160 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001161 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1162 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1163 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1164 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001165 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001166 .get_pp_num_states = pp_dpm_get_pp_num_states,
1167 .get_pp_table = pp_dpm_get_pp_table,
1168 .set_pp_table = pp_dpm_set_pp_table,
1169 .force_clock_level = pp_dpm_force_clock_level,
1170 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001171 .get_sclk_od = pp_dpm_get_sclk_od,
1172 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001173 .get_mclk_od = pp_dpm_get_mclk_od,
1174 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001175 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001176 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001177 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1178 .get_power_profile_state = pp_dpm_get_power_profile_state,
1179 .set_power_profile_state = pp_dpm_set_power_profile_state,
1180 .switch_power_profile = pp_dpm_switch_power_profile,
Rex Zhu3811f8f2017-09-26 13:39:38 +08001181 .set_clockgating_by_smu = pp_set_clockgating_by_smu,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001182};
1183
Eric Huang4dcf9e62016-06-01 17:08:07 -04001184int amd_powerplay_reset(void *handle)
1185{
1186 struct pp_instance *instance = (struct pp_instance *)handle;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001187 int ret;
1188
Rex Zhu1c863802016-12-28 19:43:23 +08001189 ret = pp_check(instance);
Dan Carpenter7265d502017-10-24 12:44:18 +03001190 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001191 return ret;
1192
Rex Zhudf1e6392017-09-01 13:46:20 +08001193 ret = pp_hw_fini(instance);
Rex Zhu1c863802016-12-28 19:43:23 +08001194 if (ret)
1195 return ret;
1196
1197 ret = hwmgr_hw_init(instance);
1198 if (ret)
Rex Zhue5f23732017-09-29 13:57:54 +08001199 return ret;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001200
Rex Zhudf1e6392017-09-01 13:46:20 +08001201 return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
Eric Huang4dcf9e62016-06-01 17:08:07 -04001202}
1203
Rex Zhu7fb72a12015-11-19 13:35:30 +08001204/* export this function to DAL */
1205
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001206int amd_powerplay_display_configuration_change(void *handle,
1207 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001208{
1209 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001210 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1211 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001212
Rex Zhu1c863802016-12-28 19:43:23 +08001213 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001214
Rex Zhuae979882017-09-29 14:36:15 +08001215 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001216 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001217
Rex Zhu1c863802016-12-28 19:43:23 +08001218 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +08001219 mutex_lock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001220 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhu2a507102017-02-20 17:07:36 +08001221 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001222 return 0;
1223}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001224
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001225int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001226 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001227{
1228 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001229 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1230 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001231
Rex Zhu1c863802016-12-28 19:43:23 +08001232 ret = pp_check(pp_handle);
1233
Rex Zhuae979882017-09-29 14:36:15 +08001234 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001235 return ret;
1236
1237 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001238
1239 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001240 return -EINVAL;
1241
Rex Zhu2a507102017-02-20 17:07:36 +08001242 mutex_lock(&pp_handle->pp_lock);
1243 ret = phm_get_dal_power_level(hwmgr, output);
1244 mutex_unlock(&pp_handle->pp_lock);
1245 return ret;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001246}
Rex Zhue273b042015-12-07 18:44:23 +08001247
1248int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001249 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001250{
Rex Zhue273b042015-12-07 18:44:23 +08001251 struct amd_pp_simple_clock_info simple_clocks;
1252 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001253 struct pp_hwmgr *hwmgr;
1254 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1255 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001256
Rex Zhu1c863802016-12-28 19:43:23 +08001257 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001258
Rex Zhuae979882017-09-29 14:36:15 +08001259 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001260 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001261
Rex Zhu1c863802016-12-28 19:43:23 +08001262 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001263
Rex Zhu2a507102017-02-20 17:07:36 +08001264 mutex_lock(&pp_handle->pp_lock);
1265
Rex Zhue273b042015-12-07 18:44:23 +08001266 phm_get_dal_power_level(hwmgr, &simple_clocks);
1267
Rex Zhu2a507102017-02-20 17:07:36 +08001268 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1269 PHM_PlatformCaps_PowerContainment))
1270 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1271 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1272 else
1273 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1274 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1275
Rex Zhuae979882017-09-29 14:36:15 +08001276 if (ret) {
Rex Zhu2a507102017-02-20 17:07:36 +08001277 pr_info("Error in phm_get_clock_info \n");
1278 mutex_unlock(&pp_handle->pp_lock);
1279 return -EINVAL;
Rex Zhue273b042015-12-07 18:44:23 +08001280 }
1281
1282 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1283 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1284 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1285 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1286 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1287 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1288
1289 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1290 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1291
1292 clocks->max_clocks_state = simple_clocks.level;
1293
1294 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1295 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1296 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1297 }
Rex Zhu2a507102017-02-20 17:07:36 +08001298 mutex_unlock(&pp_handle->pp_lock);
Rex Zhue273b042015-12-07 18:44:23 +08001299 return 0;
Rex Zhue273b042015-12-07 18:44:23 +08001300}
1301
1302int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1303{
Rex Zhu1c863802016-12-28 19:43:23 +08001304 struct pp_hwmgr *hwmgr;
1305 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1306 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001307
Rex Zhu1c863802016-12-28 19:43:23 +08001308 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001309
Rex Zhuae979882017-09-29 14:36:15 +08001310 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001311 return ret;
1312
1313 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001314
1315 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001316 return -EINVAL;
1317
Rex Zhu2a507102017-02-20 17:07:36 +08001318 mutex_lock(&pp_handle->pp_lock);
1319 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1320 mutex_unlock(&pp_handle->pp_lock);
1321 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001322}
1323
Eric Huangd0187722017-03-06 13:13:48 -05001324int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1325 enum amd_pp_clock_type type,
1326 struct pp_clock_levels_with_latency *clocks)
1327{
1328 struct pp_hwmgr *hwmgr;
1329 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1330 int ret = 0;
1331
1332 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001333 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001334 return ret;
1335
1336 if (!clocks)
1337 return -EINVAL;
1338
1339 mutex_lock(&pp_handle->pp_lock);
1340 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1341 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1342 mutex_unlock(&pp_handle->pp_lock);
1343 return ret;
1344}
1345
1346int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1347 enum amd_pp_clock_type type,
1348 struct pp_clock_levels_with_voltage *clocks)
1349{
1350 struct pp_hwmgr *hwmgr;
1351 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1352 int ret = 0;
1353
1354 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001355 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001356 return ret;
1357
1358 if (!clocks)
1359 return -EINVAL;
1360
1361 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1362
1363 mutex_lock(&pp_handle->pp_lock);
1364
1365 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1366
1367 mutex_unlock(&pp_handle->pp_lock);
1368 return ret;
1369}
1370
1371int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1372 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1373{
1374 struct pp_hwmgr *hwmgr;
1375 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1376 int ret = 0;
1377
1378 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001379 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001380 return ret;
1381
1382 if (!wm_with_clock_ranges)
1383 return -EINVAL;
1384
1385 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1386
1387 mutex_lock(&pp_handle->pp_lock);
1388 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1389 wm_with_clock_ranges);
1390 mutex_unlock(&pp_handle->pp_lock);
1391
1392 return ret;
1393}
1394
1395int amd_powerplay_display_clock_voltage_request(void *handle,
1396 struct pp_display_clock_request *clock)
1397{
1398 struct pp_hwmgr *hwmgr;
1399 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1400 int ret = 0;
1401
1402 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001403 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001404 return ret;
1405
1406 if (!clock)
1407 return -EINVAL;
1408
1409 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1410
1411 mutex_lock(&pp_handle->pp_lock);
1412 ret = phm_display_clock_voltage_request(hwmgr, clock);
1413 mutex_unlock(&pp_handle->pp_lock);
1414
1415 return ret;
1416}
1417
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001418int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1419 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001420{
Rex Zhue273b042015-12-07 18:44:23 +08001421 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001422 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1423 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001424
Rex Zhu1c863802016-12-28 19:43:23 +08001425 ret = pp_check(pp_handle);
1426
Rex Zhuae979882017-09-29 14:36:15 +08001427 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001428 return ret;
1429
1430 hwmgr = pp_handle->hwmgr;
1431
Rex Zhufa9e6992015-12-29 13:56:03 +08001432 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001433 return -EINVAL;
1434
Rex Zhu2a507102017-02-20 17:07:36 +08001435 mutex_lock(&pp_handle->pp_lock);
1436
Rex Zhue273b042015-12-07 18:44:23 +08001437 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001438 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001439
Rex Zhu2a507102017-02-20 17:07:36 +08001440 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001441 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001442}
1443