blob: 71bb7d932c86bb57aa547549b5e588e9452086da [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{
40 if (handle == NULL || handle->pp_valid != PP_VALID)
41 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
67 instance->pp_valid = PP_VALID;
68 instance->chip_family = pp_init->chip_family;
69 instance->chip_id = pp_init->chip_id;
70 instance->pm_en = pp_init->pm_en;
71 instance->feature_mask = pp_init->feature_mask;
72 instance->device = pp_init->device;
73 mutex_init(&instance->pp_lock);
74 *handle = instance;
75 return 0;
76}
77
78static int amd_powerplay_destroy(void *handle)
79{
80 struct pp_instance *instance = (struct pp_instance *)handle;
81
82 kfree(instance->hwmgr);
83 instance->hwmgr = NULL;
84
85 kfree(instance);
86 instance = NULL;
87 return 0;
88}
89
Alex Deucher1f7371b2015-12-02 17:46:21 -050090static int pp_early_init(void *handle)
91{
Rex Zhu1c863802016-12-28 19:43:23 +080092 int ret;
Rex Zhu139a2852017-09-25 20:46:37 +080093 struct pp_instance *pp_handle = NULL;
94
95 pp_handle = cgs_register_pp_handle(handle, amd_powerplay_create);
96
97 if (!pp_handle)
98 return -EINVAL;
Rex Zhu1c863802016-12-28 19:43:23 +080099
Rex Zhub3b03052017-09-26 13:28:27 -0400100 ret = hwmgr_early_init(pp_handle);
Rex Zhu1c863802016-12-28 19:43:23 +0800101 if (ret)
Rex Zhub3b03052017-09-26 13:28:27 -0400102 return -EINVAL;
Rex Zhu1c863802016-12-28 19:43:23 +0800103
Alex Deucher1f7371b2015-12-02 17:46:21 -0500104 return 0;
105}
106
107static int pp_sw_init(void *handle)
108{
Rex Zhub3b03052017-09-26 13:28:27 -0400109 struct pp_hwmgr *hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800110 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800111 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800112
Rex Zhu1c863802016-12-28 19:43:23 +0800113 ret = pp_check(pp_handle);
Jammy Zhou3bace352015-07-21 21:18:15 +0800114
Rex Zhue5f23732017-09-29 13:57:54 +0800115 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400116 hwmgr = pp_handle->hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800117
Rex Zhub3b03052017-09-26 13:28:27 -0400118 if (hwmgr->smumgr_funcs->smu_init == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800119 return -EINVAL;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800120
Rex Zhub3b03052017-09-26 13:28:27 -0400121 ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
Jammy Zhou3bace352015-07-21 21:18:15 +0800122
Rex Zhu1c863802016-12-28 19:43:23 +0800123 pr_info("amdgpu: powerplay sw initialized\n");
Huang Rui167112b2016-12-14 16:26:54 +0800124 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800125 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500126}
127
128static int pp_sw_fini(void *handle)
129{
Rex Zhub3b03052017-09-26 13:28:27 -0400130 struct pp_hwmgr *hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800131 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800132 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800133
Rex Zhu1c863802016-12-28 19:43:23 +0800134 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800135 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400136 hwmgr = pp_handle->hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800137
Rex Zhub3b03052017-09-26 13:28:27 -0400138 if (hwmgr->smumgr_funcs->smu_fini == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800139 return -EINVAL;
Jammy Zhou3bace352015-07-21 21:18:15 +0800140
Rex Zhub3b03052017-09-26 13:28:27 -0400141 ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhu1c863802016-12-28 19:43:23 +0800142 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800143 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500144}
145
146static int pp_hw_init(void *handle)
147{
Jammy Zhouac885b32015-07-21 17:43:02 +0800148 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800149 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhub3b03052017-09-26 13:28:27 -0400150 struct pp_hwmgr *hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800151
Rex Zhu1c863802016-12-28 19:43:23 +0800152 ret = pp_check(pp_handle);
Jammy Zhouac885b32015-07-21 17:43:02 +0800153
Rex Zhue5f23732017-09-29 13:57:54 +0800154 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400155 hwmgr = pp_handle->hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800156
Rex Zhub3b03052017-09-26 13:28:27 -0400157 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800158 return -EINVAL;
Jammy Zhouac885b32015-07-21 17:43:02 +0800159
Rex Zhub3b03052017-09-26 13:28:27 -0400160 if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Rex Zhu1c863802016-12-28 19:43:23 +0800161 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400162 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhu1c863802016-12-28 19:43:23 +0800163 return -EINVAL;;
164 }
165 if (ret == PP_DPM_DISABLED)
Rex Zhue5f23732017-09-29 13:57:54 +0800166 goto exit;
167 ret = hwmgr_hw_init(pp_handle);
168 if (ret)
169 goto exit;
Jammy Zhouac885b32015-07-21 17:43:02 +0800170 }
Rex Zhue5f23732017-09-29 13:57:54 +0800171 return ret;
172exit:
Rex Zhu1c863802016-12-28 19:43:23 +0800173 pp_handle->pm_en = 0;
Rex Zhue5f23732017-09-29 13:57:54 +0800174 cgs_notify_dpm_enabled(hwmgr->device, false);
175 return 0;
176
Alex Deucher1f7371b2015-12-02 17:46:21 -0500177}
178
179static int pp_hw_fini(void *handle)
180{
Rex Zhu1c863802016-12-28 19:43:23 +0800181 struct pp_instance *pp_handle = (struct pp_instance *)handle;
182 int ret = 0;
Jammy Zhouac885b32015-07-21 17:43:02 +0800183
Rex Zhu1c863802016-12-28 19:43:23 +0800184 ret = pp_check(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800185 if (ret == 0)
Rex Zhu1c863802016-12-28 19:43:23 +0800186 hwmgr_hw_fini(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800187
Alex Deucher1f7371b2015-12-02 17:46:21 -0500188 return 0;
189}
190
Rex Zhu6d07fe72017-09-25 18:51:50 +0800191static int pp_late_init(void *handle)
192{
193 struct pp_instance *pp_handle = (struct pp_instance *)handle;
194 int ret = 0;
195
196 ret = pp_check(pp_handle);
197 if (ret == 0)
198 pp_dpm_dispatch_tasks(pp_handle,
199 AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
200
201 return 0;
202}
203
Rex Zhu139a2852017-09-25 20:46:37 +0800204static void pp_late_fini(void *handle)
205{
206 amd_powerplay_destroy(handle);
207}
208
209
Alex Deucher1f7371b2015-12-02 17:46:21 -0500210static bool pp_is_idle(void *handle)
211{
Edward O'Callaghaned5121a2016-07-12 10:17:52 +1000212 return false;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500213}
214
215static int pp_wait_for_idle(void *handle)
216{
217 return 0;
218}
219
220static int pp_sw_reset(void *handle)
221{
222 return 0;
223}
224
Alex Deucher1f7371b2015-12-02 17:46:21 -0500225static int pp_set_powergating_state(void *handle,
226 enum amd_powergating_state state)
227{
Eric Huang65f85e72016-02-11 15:54:45 -0500228 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800229 struct pp_instance *pp_handle = (struct pp_instance *)handle;
230 int ret = 0;
Eric Huang65f85e72016-02-11 15:54:45 -0500231
Rex Zhu1c863802016-12-28 19:43:23 +0800232 ret = pp_check(pp_handle);
Eric Huang65f85e72016-02-11 15:54:45 -0500233
Rex Zhuae979882017-09-29 14:36:15 +0800234 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800235 return ret;
Eric Huang65f85e72016-02-11 15:54:45 -0500236
Rex Zhu1c863802016-12-28 19:43:23 +0800237 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800238
239 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800240 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800241 return 0;
242 }
Eric Huang65f85e72016-02-11 15:54:45 -0500243
244 /* Enable/disable GFX per cu powergating through SMU */
245 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
Andrew F. Davis93a4aec2017-03-15 11:20:24 -0500246 state == AMD_PG_STATE_GATE);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500247}
248
249static int pp_suspend(void *handle)
250{
Rex Zhu1c863802016-12-28 19:43:23 +0800251 struct pp_instance *pp_handle = (struct pp_instance *)handle;
252 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800253
Rex Zhu1c863802016-12-28 19:43:23 +0800254 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800255 if (ret == 0)
256 hwmgr_hw_suspend(pp_handle);
257 return 0;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500258}
259
260static int pp_resume(void *handle)
261{
Rex Zhub3b03052017-09-26 13:28:27 -0400262 struct pp_hwmgr *hwmgr;
Rex Zhue5f23732017-09-29 13:57:54 +0800263 int ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800264 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800265
Rex Zhue5f23732017-09-29 13:57:54 +0800266 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800267
Rex Zhue5f23732017-09-29 13:57:54 +0800268 if (ret < 0)
269 return ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800270
Rex Zhub3b03052017-09-26 13:28:27 -0400271 hwmgr = pp_handle->hwmgr;
Rex Zhue0b71a72015-12-29 10:25:19 +0800272
Rex Zhub3b03052017-09-26 13:28:27 -0400273 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800274 return -EINVAL;
275
Rex Zhue5f23732017-09-29 13:57:54 +0800276 if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800277 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400278 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhue5f23732017-09-29 13:57:54 +0800279 return -EINVAL;
Rex Zhue0b71a72015-12-29 10:25:19 +0800280 }
281
Rex Zhue5f23732017-09-29 13:57:54 +0800282 if (ret == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800283 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800284
Rex Zhudf1e6392017-09-01 13:46:20 +0800285 return hwmgr_hw_resume(pp_handle);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500286}
287
288const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400289 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500290 .early_init = pp_early_init,
Rex Zhu6d07fe72017-09-25 18:51:50 +0800291 .late_init = pp_late_init,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500292 .sw_init = pp_sw_init,
293 .sw_fini = pp_sw_fini,
294 .hw_init = pp_hw_init,
295 .hw_fini = pp_hw_fini,
Rex Zhu139a2852017-09-25 20:46:37 +0800296 .late_fini = pp_late_fini,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500297 .suspend = pp_suspend,
298 .resume = pp_resume,
299 .is_idle = pp_is_idle,
300 .wait_for_idle = pp_wait_for_idle,
301 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800302 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500303 .set_powergating_state = pp_set_powergating_state,
304};
305
306static int pp_dpm_load_fw(void *handle)
307{
308 return 0;
309}
310
311static int pp_dpm_fw_loading_complete(void *handle)
312{
313 return 0;
314}
315
Rex Zhu3811f8f2017-09-26 13:39:38 +0800316static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
317{
318 struct pp_hwmgr *hwmgr;
319 struct pp_instance *pp_handle = (struct pp_instance *)handle;
320 int ret = 0;
321
322 ret = pp_check(pp_handle);
323
324 if (ret)
325 return ret;
326
327 hwmgr = pp_handle->hwmgr;
328
329 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
330 pr_info("%s was not implemented.\n", __func__);
331 return 0;
332 }
333
334 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
335}
336
Rex Zhu9947f702017-08-29 16:08:56 +0800337static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
338 enum amd_dpm_forced_level *level)
339{
340 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
341 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
342 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
343 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
344
345 if (!(hwmgr->dpm_level & profile_mode_mask)) {
346 /* enter umd pstate, save current level, disable gfx cg*/
347 if (*level & profile_mode_mask) {
348 hwmgr->saved_dpm_level = hwmgr->dpm_level;
349 hwmgr->en_umd_pstate = true;
350 cgs_set_clockgating_state(hwmgr->device,
351 AMD_IP_BLOCK_TYPE_GFX,
352 AMD_CG_STATE_UNGATE);
353 cgs_set_powergating_state(hwmgr->device,
354 AMD_IP_BLOCK_TYPE_GFX,
355 AMD_PG_STATE_UNGATE);
356 }
357 } else {
358 /* exit umd pstate, restore level, enable gfx cg*/
359 if (!(*level & profile_mode_mask)) {
360 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
361 *level = hwmgr->saved_dpm_level;
362 hwmgr->en_umd_pstate = false;
363 cgs_set_clockgating_state(hwmgr->device,
364 AMD_IP_BLOCK_TYPE_GFX,
365 AMD_CG_STATE_GATE);
366 cgs_set_powergating_state(hwmgr->device,
367 AMD_IP_BLOCK_TYPE_GFX,
368 AMD_PG_STATE_GATE);
369 }
370 }
371}
372
Alex Deucher1f7371b2015-12-02 17:46:21 -0500373static int pp_dpm_force_performance_level(void *handle,
374 enum amd_dpm_forced_level level)
375{
Rex Zhu577bbe02015-08-28 12:56:43 +0800376 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800377 struct pp_instance *pp_handle = (struct pp_instance *)handle;
378 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800379
Rex Zhu1c863802016-12-28 19:43:23 +0800380 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800381
Rex Zhuae979882017-09-29 14:36:15 +0800382 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800383 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800384
385 hwmgr = pp_handle->hwmgr;
386
Rex Zhu9947f702017-08-29 16:08:56 +0800387 if (level == hwmgr->dpm_level)
388 return 0;
389
Rex Zhu7383bcb2016-03-30 11:35:50 +0800390 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800391 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800392 return 0;
393 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800394
Rex Zhu2a507102017-02-20 17:07:36 +0800395 mutex_lock(&pp_handle->pp_lock);
Rex Zhu9947f702017-08-29 16:08:56 +0800396 pp_dpm_en_umd_pstate(hwmgr, &level);
397 hwmgr->request_dpm_level = level;
Rex Zhudf1e6392017-09-01 13:46:20 +0800398 hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
Rex Zhu9947f702017-08-29 16:08:56 +0800399 ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
400 if (!ret)
401 hwmgr->dpm_level = hwmgr->request_dpm_level;
402
Rex Zhu2a507102017-02-20 17:07:36 +0800403 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500404 return 0;
405}
Rex Zhu577bbe02015-08-28 12:56:43 +0800406
Alex Deucher1f7371b2015-12-02 17:46:21 -0500407static enum amd_dpm_forced_level pp_dpm_get_performance_level(
408 void *handle)
409{
Rex Zhu577bbe02015-08-28 12:56:43 +0800410 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800411 struct pp_instance *pp_handle = (struct pp_instance *)handle;
412 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800413 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800414
Rex Zhu1c863802016-12-28 19:43:23 +0800415 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800416
Rex Zhuae979882017-09-29 14:36:15 +0800417 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800418 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800419
Rex Zhu1c863802016-12-28 19:43:23 +0800420 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800421 mutex_lock(&pp_handle->pp_lock);
422 level = hwmgr->dpm_level;
423 mutex_unlock(&pp_handle->pp_lock);
424 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500425}
Rex Zhu577bbe02015-08-28 12:56:43 +0800426
Rex Zhuf93f0c32017-09-06 16:08:03 +0800427static uint32_t pp_dpm_get_sclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500428{
Rex Zhu577bbe02015-08-28 12:56:43 +0800429 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800430 struct pp_instance *pp_handle = (struct pp_instance *)handle;
431 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800432 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800433
Rex Zhu1c863802016-12-28 19:43:23 +0800434 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800435
Rex Zhuae979882017-09-29 14:36:15 +0800436 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800437 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800438
Rex Zhu1c863802016-12-28 19:43:23 +0800439 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800440
441 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800442 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800443 return 0;
444 }
Rex Zhu2a507102017-02-20 17:07:36 +0800445 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800446 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800447 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800448 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500449}
Rex Zhu577bbe02015-08-28 12:56:43 +0800450
Rex Zhuf93f0c32017-09-06 16:08:03 +0800451static uint32_t pp_dpm_get_mclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500452{
Rex Zhu577bbe02015-08-28 12:56:43 +0800453 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800454 struct pp_instance *pp_handle = (struct pp_instance *)handle;
455 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800456 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800457
Rex Zhu1c863802016-12-28 19:43:23 +0800458 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800459
Rex Zhuae979882017-09-29 14:36:15 +0800460 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800461 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800462
Rex Zhu1c863802016-12-28 19:43:23 +0800463 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800464
465 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800466 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800467 return 0;
468 }
Rex Zhu2a507102017-02-20 17:07:36 +0800469 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800470 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800471 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800472 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500473}
Rex Zhu577bbe02015-08-28 12:56:43 +0800474
Rex Zhuf93f0c32017-09-06 16:08:03 +0800475static void pp_dpm_powergate_vce(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500476{
Rex Zhu577bbe02015-08-28 12:56:43 +0800477 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800478 struct pp_instance *pp_handle = (struct pp_instance *)handle;
479 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800480
Rex Zhu1c863802016-12-28 19:43:23 +0800481 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800482
Rex Zhuae979882017-09-29 14:36:15 +0800483 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800484 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800485
Rex Zhu1c863802016-12-28 19:43:23 +0800486 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800487
488 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800489 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800490 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800491 }
Rex Zhu2a507102017-02-20 17:07:36 +0800492 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800493 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800494 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500495}
Rex Zhu577bbe02015-08-28 12:56:43 +0800496
Rex Zhuf93f0c32017-09-06 16:08:03 +0800497static void pp_dpm_powergate_uvd(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500498{
Rex Zhu577bbe02015-08-28 12:56:43 +0800499 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800500 struct pp_instance *pp_handle = (struct pp_instance *)handle;
501 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800502
Rex Zhu1c863802016-12-28 19:43:23 +0800503 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800504
Rex Zhuae979882017-09-29 14:36:15 +0800505 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800506 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800507
Rex Zhu1c863802016-12-28 19:43:23 +0800508 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800509
510 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800511 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800512 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800513 }
Rex Zhu2a507102017-02-20 17:07:36 +0800514 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800515 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800516 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800517}
518
Rex Zhudf1e6392017-09-01 13:46:20 +0800519static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
Baoyou Xief8a4c112016-09-30 17:58:42 +0800520 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500521{
Rex Zhu577bbe02015-08-28 12:56:43 +0800522 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800523 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800524
Rex Zhu1c863802016-12-28 19:43:23 +0800525 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800526
Rex Zhuae979882017-09-29 14:36:15 +0800527 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800528 return ret;
Rex Zhudf1e6392017-09-01 13:46:20 +0800529
Rex Zhu2a507102017-02-20 17:07:36 +0800530 mutex_lock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800531 ret = hwmgr_handle_task(pp_handle, task_id, input, output);
Rex Zhu2a507102017-02-20 17:07:36 +0800532 mutex_unlock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800533
Rex Zhu577bbe02015-08-28 12:56:43 +0800534 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500535}
Rex Zhu577bbe02015-08-28 12:56:43 +0800536
Baoyou Xief8a4c112016-09-30 17:58:42 +0800537static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500538{
Rex Zhu577bbe02015-08-28 12:56:43 +0800539 struct pp_hwmgr *hwmgr;
540 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800541 struct pp_instance *pp_handle = (struct pp_instance *)handle;
542 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800543 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800544
Rex Zhu1c863802016-12-28 19:43:23 +0800545 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800546
Rex Zhuae979882017-09-29 14:36:15 +0800547 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800548 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800549
Rex Zhu1c863802016-12-28 19:43:23 +0800550 hwmgr = pp_handle->hwmgr;
551
552 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800553 return -EINVAL;
554
Rex Zhu2a507102017-02-20 17:07:36 +0800555 mutex_lock(&pp_handle->pp_lock);
556
Rex Zhu577bbe02015-08-28 12:56:43 +0800557 state = hwmgr->current_ps;
558
559 switch (state->classification.ui_label) {
560 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800561 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300562 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800563 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800564 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300565 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800566 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800567 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300568 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800569 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500570 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800571 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500572 else
Rex Zhu2a507102017-02-20 17:07:36 +0800573 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300574 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800575 }
Rex Zhu2a507102017-02-20 17:07:36 +0800576 mutex_unlock(&pp_handle->pp_lock);
577
578 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500579}
Rex Zhu577bbe02015-08-28 12:56:43 +0800580
Rex Zhuf93f0c32017-09-06 16:08:03 +0800581static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
Rex Zhucac9a192015-10-16 11:48:21 +0800582{
583 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800584 struct pp_instance *pp_handle = (struct pp_instance *)handle;
585 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800586
Rex Zhu1c863802016-12-28 19:43:23 +0800587 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800588
Rex Zhuae979882017-09-29 14:36:15 +0800589 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800590 return;
Rex Zhucac9a192015-10-16 11:48:21 +0800591
Rex Zhu1c863802016-12-28 19:43:23 +0800592 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800593
594 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800595 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800596 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800597 }
Rex Zhu2a507102017-02-20 17:07:36 +0800598 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800599 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
Rex Zhu2a507102017-02-20 17:07:36 +0800600 mutex_unlock(&pp_handle->pp_lock);
Rex Zhucac9a192015-10-16 11:48:21 +0800601}
602
Rex Zhuf93f0c32017-09-06 16:08:03 +0800603static uint32_t pp_dpm_get_fan_control_mode(void *handle)
Rex Zhucac9a192015-10-16 11:48:21 +0800604{
605 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800606 struct pp_instance *pp_handle = (struct pp_instance *)handle;
607 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800608 uint32_t mode = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800609
Rex Zhu1c863802016-12-28 19:43:23 +0800610 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800611
Rex Zhuae979882017-09-29 14:36:15 +0800612 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800613 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800614
Rex Zhu1c863802016-12-28 19:43:23 +0800615 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800616
617 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800618 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800619 return 0;
620 }
Rex Zhu2a507102017-02-20 17:07:36 +0800621 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800622 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
Rex Zhu2a507102017-02-20 17:07:36 +0800623 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800624 return mode;
Rex Zhucac9a192015-10-16 11:48:21 +0800625}
626
627static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
628{
629 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800630 struct pp_instance *pp_handle = (struct pp_instance *)handle;
631 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800632
Rex Zhu1c863802016-12-28 19:43:23 +0800633 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800634
Rex Zhuae979882017-09-29 14:36:15 +0800635 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800636 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800637
Rex Zhu1c863802016-12-28 19:43:23 +0800638 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800639
640 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800641 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800642 return 0;
643 }
Rex Zhu2a507102017-02-20 17:07:36 +0800644 mutex_lock(&pp_handle->pp_lock);
645 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
646 mutex_unlock(&pp_handle->pp_lock);
647 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800648}
649
650static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
651{
652 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800653 struct pp_instance *pp_handle = (struct pp_instance *)handle;
654 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800655
Rex Zhu1c863802016-12-28 19:43:23 +0800656 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800657
Rex Zhuae979882017-09-29 14:36:15 +0800658 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800659 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800660
Rex Zhu1c863802016-12-28 19:43:23 +0800661 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800662
663 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800664 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800665 return 0;
666 }
Rex Zhucac9a192015-10-16 11:48:21 +0800667
Rex Zhu2a507102017-02-20 17:07:36 +0800668 mutex_lock(&pp_handle->pp_lock);
669 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
670 mutex_unlock(&pp_handle->pp_lock);
671 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800672}
673
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300674static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
675{
676 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800677 struct pp_instance *pp_handle = (struct pp_instance *)handle;
678 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300679
Rex Zhu1c863802016-12-28 19:43:23 +0800680 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300681
Rex Zhuae979882017-09-29 14:36:15 +0800682 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800683 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300684
Rex Zhu1c863802016-12-28 19:43:23 +0800685 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300686
687 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
688 return -EINVAL;
689
Rex Zhu2a507102017-02-20 17:07:36 +0800690 mutex_lock(&pp_handle->pp_lock);
691 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
692 mutex_unlock(&pp_handle->pp_lock);
693 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300694}
695
Rex Zhucac9a192015-10-16 11:48:21 +0800696static int pp_dpm_get_temperature(void *handle)
697{
698 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800699 struct pp_instance *pp_handle = (struct pp_instance *)handle;
700 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800701
Rex Zhu1c863802016-12-28 19:43:23 +0800702 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800703
Rex Zhuae979882017-09-29 14:36:15 +0800704 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800705 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800706
Rex Zhu1c863802016-12-28 19:43:23 +0800707 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800708
709 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800710 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800711 return 0;
712 }
Rex Zhu2a507102017-02-20 17:07:36 +0800713 mutex_lock(&pp_handle->pp_lock);
714 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
715 mutex_unlock(&pp_handle->pp_lock);
716 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800717}
Rex Zhu577bbe02015-08-28 12:56:43 +0800718
Eric Huangf3898ea2015-12-11 16:24:34 -0500719static int pp_dpm_get_pp_num_states(void *handle,
720 struct pp_states_info *data)
721{
722 struct pp_hwmgr *hwmgr;
723 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800724 struct pp_instance *pp_handle = (struct pp_instance *)handle;
725 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500726
Rex Zhu1c863802016-12-28 19:43:23 +0800727 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500728
Rex Zhuae979882017-09-29 14:36:15 +0800729 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800730 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500731
Rex Zhu1c863802016-12-28 19:43:23 +0800732 hwmgr = pp_handle->hwmgr;
733
734 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500735 return -EINVAL;
736
Rex Zhu2a507102017-02-20 17:07:36 +0800737 mutex_lock(&pp_handle->pp_lock);
738
Eric Huangf3898ea2015-12-11 16:24:34 -0500739 data->nums = hwmgr->num_ps;
740
741 for (i = 0; i < hwmgr->num_ps; i++) {
742 struct pp_power_state *state = (struct pp_power_state *)
743 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
744 switch (state->classification.ui_label) {
745 case PP_StateUILabel_Battery:
746 data->states[i] = POWER_STATE_TYPE_BATTERY;
747 break;
748 case PP_StateUILabel_Balanced:
749 data->states[i] = POWER_STATE_TYPE_BALANCED;
750 break;
751 case PP_StateUILabel_Performance:
752 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
753 break;
754 default:
755 if (state->classification.flags & PP_StateClassificationFlag_Boot)
756 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
757 else
758 data->states[i] = POWER_STATE_TYPE_DEFAULT;
759 }
760 }
Rex Zhu2a507102017-02-20 17:07:36 +0800761 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500762 return 0;
763}
764
765static int pp_dpm_get_pp_table(void *handle, char **table)
766{
767 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800768 struct pp_instance *pp_handle = (struct pp_instance *)handle;
769 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800770 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500771
Rex Zhu1c863802016-12-28 19:43:23 +0800772 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500773
Rex Zhuae979882017-09-29 14:36:15 +0800774 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800775 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500776
Rex Zhu1c863802016-12-28 19:43:23 +0800777 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800778
Eric Huang4dcf9e62016-06-01 17:08:07 -0400779 if (!hwmgr->soft_pp_table)
780 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500781
Rex Zhu2a507102017-02-20 17:07:36 +0800782 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400783 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800784 size = hwmgr->soft_pp_table_size;
785 mutex_unlock(&pp_handle->pp_lock);
786 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500787}
788
789static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
790{
791 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800792 struct pp_instance *pp_handle = (struct pp_instance *)handle;
793 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500794
Rex Zhu1c863802016-12-28 19:43:23 +0800795 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500796
Rex Zhuae979882017-09-29 14:36:15 +0800797 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800798 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500799
Rex Zhu1c863802016-12-28 19:43:23 +0800800 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800801 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400802 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000803 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
804 hwmgr->soft_pp_table_size,
805 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800806 if (!hwmgr->hardcode_pp_table) {
807 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400808 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800809 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800810 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500811
Eric Huang4dcf9e62016-06-01 17:08:07 -0400812 memcpy(hwmgr->hardcode_pp_table, buf, size);
813
814 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800815 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400816
Eric Huangdd4bdf32017-03-01 15:49:31 -0500817 ret = amd_powerplay_reset(handle);
818 if (ret)
819 return ret;
820
821 if (hwmgr->hwmgr_func->avfs_control) {
822 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
823 if (ret)
824 return ret;
825 }
826
827 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500828}
829
830static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400831 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500832{
833 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800834 struct pp_instance *pp_handle = (struct pp_instance *)handle;
835 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500836
Rex Zhu1c863802016-12-28 19:43:23 +0800837 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500838
Rex Zhuae979882017-09-29 14:36:15 +0800839 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800840 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500841
Rex Zhu1c863802016-12-28 19:43:23 +0800842 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800843
844 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800845 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800846 return 0;
847 }
Rex Zhu2a507102017-02-20 17:07:36 +0800848 mutex_lock(&pp_handle->pp_lock);
849 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
850 mutex_unlock(&pp_handle->pp_lock);
851 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500852}
853
854static int pp_dpm_print_clock_levels(void *handle,
855 enum pp_clock_type type, char *buf)
856{
857 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800858 struct pp_instance *pp_handle = (struct pp_instance *)handle;
859 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500860
Rex Zhu1c863802016-12-28 19:43:23 +0800861 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500862
Rex Zhuae979882017-09-29 14:36:15 +0800863 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800864 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500865
Rex Zhu1c863802016-12-28 19:43:23 +0800866 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500867
Rex Zhu7383bcb2016-03-30 11:35:50 +0800868 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800869 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800870 return 0;
871 }
Rex Zhu2a507102017-02-20 17:07:36 +0800872 mutex_lock(&pp_handle->pp_lock);
873 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
874 mutex_unlock(&pp_handle->pp_lock);
875 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500876}
877
Eric Huang428bafa2016-05-12 14:51:21 -0400878static int pp_dpm_get_sclk_od(void *handle)
879{
880 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800881 struct pp_instance *pp_handle = (struct pp_instance *)handle;
882 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400883
Rex Zhu1c863802016-12-28 19:43:23 +0800884 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400885
Rex Zhuae979882017-09-29 14:36:15 +0800886 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800887 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400888
Rex Zhu1c863802016-12-28 19:43:23 +0800889 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400890
891 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800892 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400893 return 0;
894 }
Rex Zhu2a507102017-02-20 17:07:36 +0800895 mutex_lock(&pp_handle->pp_lock);
896 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
897 mutex_unlock(&pp_handle->pp_lock);
898 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400899}
900
901static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
902{
903 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800904 struct pp_instance *pp_handle = (struct pp_instance *)handle;
905 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400906
Rex Zhu1c863802016-12-28 19:43:23 +0800907 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400908
Rex Zhuae979882017-09-29 14:36:15 +0800909 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800910 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400911
Rex Zhu1c863802016-12-28 19:43:23 +0800912 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400913
914 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800915 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400916 return 0;
917 }
918
Rex Zhu2a507102017-02-20 17:07:36 +0800919 mutex_lock(&pp_handle->pp_lock);
920 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400921 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800922 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400923}
924
Eric Huangf2bdc052016-05-24 15:11:17 -0400925static int pp_dpm_get_mclk_od(void *handle)
926{
927 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800928 struct pp_instance *pp_handle = (struct pp_instance *)handle;
929 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400930
Rex Zhu1c863802016-12-28 19:43:23 +0800931 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400932
Rex Zhuae979882017-09-29 14:36:15 +0800933 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800934 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400935
Rex Zhu1c863802016-12-28 19:43:23 +0800936 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400937
938 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800939 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400940 return 0;
941 }
Rex Zhu2a507102017-02-20 17:07:36 +0800942 mutex_lock(&pp_handle->pp_lock);
943 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
944 mutex_unlock(&pp_handle->pp_lock);
945 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400946}
947
948static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
949{
950 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800951 struct pp_instance *pp_handle = (struct pp_instance *)handle;
952 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400953
Rex Zhu1c863802016-12-28 19:43:23 +0800954 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400955
Rex Zhuae979882017-09-29 14:36:15 +0800956 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800957 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400958
Rex Zhu1c863802016-12-28 19:43:23 +0800959 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400960
961 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800962 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400963 return 0;
964 }
Rex Zhu2a507102017-02-20 17:07:36 +0800965 mutex_lock(&pp_handle->pp_lock);
966 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
967 mutex_unlock(&pp_handle->pp_lock);
968 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400969}
970
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500971static int pp_dpm_read_sensor(void *handle, int idx,
972 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400973{
974 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800975 struct pp_instance *pp_handle = (struct pp_instance *)handle;
976 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400977
Rex Zhu1c863802016-12-28 19:43:23 +0800978 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400979
Rex Zhuae979882017-09-29 14:36:15 +0800980 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800981 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400982
Rex Zhu1c863802016-12-28 19:43:23 +0800983 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400984
985 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800986 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400987 return 0;
988 }
989
Rex Zhu2a507102017-02-20 17:07:36 +0800990 mutex_lock(&pp_handle->pp_lock);
991 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
992 mutex_unlock(&pp_handle->pp_lock);
993
994 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400995}
996
Alex Deucher597be302016-10-07 13:52:43 -0400997static struct amd_vce_state*
998pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
999{
1000 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001001 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1002 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -04001003
Rex Zhu1c863802016-12-28 19:43:23 +08001004 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -04001005
Rex Zhuae979882017-09-29 14:36:15 +08001006 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001007 return NULL;
1008
1009 hwmgr = pp_handle->hwmgr;
1010
1011 if (hwmgr && idx < hwmgr->num_vce_state_tables)
1012 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -04001013 return NULL;
1014}
1015
Eric Huang34bb2732016-09-12 16:17:44 -04001016static int pp_dpm_reset_power_profile_state(void *handle,
1017 struct amd_pp_profile *request)
1018{
1019 struct pp_hwmgr *hwmgr;
1020 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1021
1022 if (!request || pp_check(pp_handle))
1023 return -EINVAL;
1024
1025 hwmgr = pp_handle->hwmgr;
1026
1027 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1028 pr_info("%s was not implemented.\n", __func__);
1029 return 0;
1030 }
1031
1032 if (request->type == AMD_PP_GFX_PROFILE) {
1033 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1034 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1035 &hwmgr->gfx_power_profile);
1036 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1037 hwmgr->compute_power_profile =
1038 hwmgr->default_compute_power_profile;
1039 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1040 &hwmgr->compute_power_profile);
1041 } else
1042 return -EINVAL;
1043}
1044
1045static int pp_dpm_get_power_profile_state(void *handle,
1046 struct amd_pp_profile *query)
1047{
1048 struct pp_hwmgr *hwmgr;
1049 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1050
1051 if (!query || pp_check(pp_handle))
1052 return -EINVAL;
1053
1054 hwmgr = pp_handle->hwmgr;
1055
1056 if (query->type == AMD_PP_GFX_PROFILE)
1057 memcpy(query, &hwmgr->gfx_power_profile,
1058 sizeof(struct amd_pp_profile));
1059 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1060 memcpy(query, &hwmgr->compute_power_profile,
1061 sizeof(struct amd_pp_profile));
1062 else
1063 return -EINVAL;
1064
1065 return 0;
1066}
1067
1068static int pp_dpm_set_power_profile_state(void *handle,
1069 struct amd_pp_profile *request)
1070{
1071 struct pp_hwmgr *hwmgr;
1072 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1073 int ret = -1;
1074
1075 if (!request || pp_check(pp_handle))
1076 return -EINVAL;
1077
1078 hwmgr = pp_handle->hwmgr;
1079
1080 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1081 pr_info("%s was not implemented.\n", __func__);
1082 return 0;
1083 }
1084
1085 if (request->min_sclk ||
1086 request->min_mclk ||
1087 request->activity_threshold ||
1088 request->up_hyst ||
1089 request->down_hyst) {
1090 if (request->type == AMD_PP_GFX_PROFILE)
1091 memcpy(&hwmgr->gfx_power_profile, request,
1092 sizeof(struct amd_pp_profile));
1093 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1094 memcpy(&hwmgr->compute_power_profile, request,
1095 sizeof(struct amd_pp_profile));
1096 else
1097 return -EINVAL;
1098
1099 if (request->type == hwmgr->current_power_profile)
1100 ret = hwmgr->hwmgr_func->set_power_profile_state(
1101 hwmgr,
1102 request);
1103 } else {
1104 /* set power profile if it exists */
1105 switch (request->type) {
1106 case AMD_PP_GFX_PROFILE:
1107 ret = hwmgr->hwmgr_func->set_power_profile_state(
1108 hwmgr,
1109 &hwmgr->gfx_power_profile);
1110 break;
1111 case AMD_PP_COMPUTE_PROFILE:
1112 ret = hwmgr->hwmgr_func->set_power_profile_state(
1113 hwmgr,
1114 &hwmgr->compute_power_profile);
1115 break;
1116 default:
1117 return -EINVAL;
1118 }
1119 }
1120
1121 if (!ret)
1122 hwmgr->current_power_profile = request->type;
1123
1124 return 0;
1125}
1126
1127static int pp_dpm_switch_power_profile(void *handle,
1128 enum amd_pp_profile_type type)
1129{
1130 struct pp_hwmgr *hwmgr;
1131 struct amd_pp_profile request = {0};
1132 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1133
1134 if (pp_check(pp_handle))
1135 return -EINVAL;
1136
1137 hwmgr = pp_handle->hwmgr;
1138
1139 if (hwmgr->current_power_profile != type) {
1140 request.type = type;
1141 pp_dpm_set_power_profile_state(handle, &request);
1142 }
1143
1144 return 0;
1145}
1146
Rex Zhuf93f0c32017-09-06 16:08:03 +08001147const struct amd_pm_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001148 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001149 .load_firmware = pp_dpm_load_fw,
1150 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1151 .force_performance_level = pp_dpm_force_performance_level,
1152 .get_performance_level = pp_dpm_get_performance_level,
1153 .get_current_power_state = pp_dpm_get_current_power_state,
1154 .get_sclk = pp_dpm_get_sclk,
1155 .get_mclk = pp_dpm_get_mclk,
1156 .powergate_vce = pp_dpm_powergate_vce,
1157 .powergate_uvd = pp_dpm_powergate_uvd,
1158 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001159 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1160 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1161 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1162 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001163 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001164 .get_pp_num_states = pp_dpm_get_pp_num_states,
1165 .get_pp_table = pp_dpm_get_pp_table,
1166 .set_pp_table = pp_dpm_set_pp_table,
1167 .force_clock_level = pp_dpm_force_clock_level,
1168 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001169 .get_sclk_od = pp_dpm_get_sclk_od,
1170 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001171 .get_mclk_od = pp_dpm_get_mclk_od,
1172 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001173 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001174 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001175 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1176 .get_power_profile_state = pp_dpm_get_power_profile_state,
1177 .set_power_profile_state = pp_dpm_set_power_profile_state,
1178 .switch_power_profile = pp_dpm_switch_power_profile,
Rex Zhu3811f8f2017-09-26 13:39:38 +08001179 .set_clockgating_by_smu = pp_set_clockgating_by_smu,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001180};
1181
Eric Huang4dcf9e62016-06-01 17:08:07 -04001182int amd_powerplay_reset(void *handle)
1183{
1184 struct pp_instance *instance = (struct pp_instance *)handle;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001185 int ret;
1186
Rex Zhu1c863802016-12-28 19:43:23 +08001187 ret = pp_check(instance);
Rex Zhuae979882017-09-29 14:36:15 +08001188 if (!ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001189 return ret;
1190
Rex Zhudf1e6392017-09-01 13:46:20 +08001191 ret = pp_hw_fini(instance);
Rex Zhu1c863802016-12-28 19:43:23 +08001192 if (ret)
1193 return ret;
1194
1195 ret = hwmgr_hw_init(instance);
1196 if (ret)
Rex Zhue5f23732017-09-29 13:57:54 +08001197 return ret;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001198
Rex Zhudf1e6392017-09-01 13:46:20 +08001199 return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
Eric Huang4dcf9e62016-06-01 17:08:07 -04001200}
1201
Rex Zhu7fb72a12015-11-19 13:35:30 +08001202/* export this function to DAL */
1203
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001204int amd_powerplay_display_configuration_change(void *handle,
1205 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001206{
1207 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001208 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1209 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001210
Rex Zhu1c863802016-12-28 19:43:23 +08001211 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001212
Rex Zhuae979882017-09-29 14:36:15 +08001213 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001214 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001215
Rex Zhu1c863802016-12-28 19:43:23 +08001216 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +08001217 mutex_lock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001218 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhu2a507102017-02-20 17:07:36 +08001219 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001220 return 0;
1221}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001222
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001223int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001224 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001225{
1226 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001227 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1228 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001229
Rex Zhu1c863802016-12-28 19:43:23 +08001230 ret = pp_check(pp_handle);
1231
Rex Zhuae979882017-09-29 14:36:15 +08001232 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001233 return ret;
1234
1235 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001236
1237 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001238 return -EINVAL;
1239
Rex Zhu2a507102017-02-20 17:07:36 +08001240 mutex_lock(&pp_handle->pp_lock);
1241 ret = phm_get_dal_power_level(hwmgr, output);
1242 mutex_unlock(&pp_handle->pp_lock);
1243 return ret;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001244}
Rex Zhue273b042015-12-07 18:44:23 +08001245
1246int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001247 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001248{
Rex Zhue273b042015-12-07 18:44:23 +08001249 struct amd_pp_simple_clock_info simple_clocks;
1250 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001251 struct pp_hwmgr *hwmgr;
1252 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1253 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001254
Rex Zhu1c863802016-12-28 19:43:23 +08001255 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001256
Rex Zhuae979882017-09-29 14:36:15 +08001257 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001258 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001259
Rex Zhu1c863802016-12-28 19:43:23 +08001260 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001261
Rex Zhu2a507102017-02-20 17:07:36 +08001262 mutex_lock(&pp_handle->pp_lock);
1263
Rex Zhue273b042015-12-07 18:44:23 +08001264 phm_get_dal_power_level(hwmgr, &simple_clocks);
1265
Rex Zhu2a507102017-02-20 17:07:36 +08001266 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1267 PHM_PlatformCaps_PowerContainment))
1268 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1269 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1270 else
1271 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1272 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1273
Rex Zhuae979882017-09-29 14:36:15 +08001274 if (ret) {
Rex Zhu2a507102017-02-20 17:07:36 +08001275 pr_info("Error in phm_get_clock_info \n");
1276 mutex_unlock(&pp_handle->pp_lock);
1277 return -EINVAL;
Rex Zhue273b042015-12-07 18:44:23 +08001278 }
1279
1280 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1281 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1282 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1283 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1284 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1285 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1286
1287 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1288 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1289
1290 clocks->max_clocks_state = simple_clocks.level;
1291
1292 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1293 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1294 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1295 }
Rex Zhu2a507102017-02-20 17:07:36 +08001296 mutex_unlock(&pp_handle->pp_lock);
Rex Zhue273b042015-12-07 18:44:23 +08001297 return 0;
Rex Zhue273b042015-12-07 18:44:23 +08001298}
1299
1300int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1301{
Rex Zhu1c863802016-12-28 19:43:23 +08001302 struct pp_hwmgr *hwmgr;
1303 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1304 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001305
Rex Zhu1c863802016-12-28 19:43:23 +08001306 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001307
Rex Zhuae979882017-09-29 14:36:15 +08001308 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001309 return ret;
1310
1311 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001312
1313 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001314 return -EINVAL;
1315
Rex Zhu2a507102017-02-20 17:07:36 +08001316 mutex_lock(&pp_handle->pp_lock);
1317 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1318 mutex_unlock(&pp_handle->pp_lock);
1319 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001320}
1321
Eric Huangd0187722017-03-06 13:13:48 -05001322int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1323 enum amd_pp_clock_type type,
1324 struct pp_clock_levels_with_latency *clocks)
1325{
1326 struct pp_hwmgr *hwmgr;
1327 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1328 int ret = 0;
1329
1330 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001331 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001332 return ret;
1333
1334 if (!clocks)
1335 return -EINVAL;
1336
1337 mutex_lock(&pp_handle->pp_lock);
1338 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1339 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1340 mutex_unlock(&pp_handle->pp_lock);
1341 return ret;
1342}
1343
1344int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1345 enum amd_pp_clock_type type,
1346 struct pp_clock_levels_with_voltage *clocks)
1347{
1348 struct pp_hwmgr *hwmgr;
1349 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1350 int ret = 0;
1351
1352 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001353 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001354 return ret;
1355
1356 if (!clocks)
1357 return -EINVAL;
1358
1359 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1360
1361 mutex_lock(&pp_handle->pp_lock);
1362
1363 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1364
1365 mutex_unlock(&pp_handle->pp_lock);
1366 return ret;
1367}
1368
1369int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1370 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1371{
1372 struct pp_hwmgr *hwmgr;
1373 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1374 int ret = 0;
1375
1376 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001377 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001378 return ret;
1379
1380 if (!wm_with_clock_ranges)
1381 return -EINVAL;
1382
1383 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1384
1385 mutex_lock(&pp_handle->pp_lock);
1386 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1387 wm_with_clock_ranges);
1388 mutex_unlock(&pp_handle->pp_lock);
1389
1390 return ret;
1391}
1392
1393int amd_powerplay_display_clock_voltage_request(void *handle,
1394 struct pp_display_clock_request *clock)
1395{
1396 struct pp_hwmgr *hwmgr;
1397 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1398 int ret = 0;
1399
1400 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001401 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001402 return ret;
1403
1404 if (!clock)
1405 return -EINVAL;
1406
1407 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1408
1409 mutex_lock(&pp_handle->pp_lock);
1410 ret = phm_display_clock_voltage_request(hwmgr, clock);
1411 mutex_unlock(&pp_handle->pp_lock);
1412
1413 return ret;
1414}
1415
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001416int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1417 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001418{
Rex Zhue273b042015-12-07 18:44:23 +08001419 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001420 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1421 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001422
Rex Zhu1c863802016-12-28 19:43:23 +08001423 ret = pp_check(pp_handle);
1424
Rex Zhuae979882017-09-29 14:36:15 +08001425 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001426 return ret;
1427
1428 hwmgr = pp_handle->hwmgr;
1429
Rex Zhufa9e6992015-12-29 13:56:03 +08001430 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001431 return -EINVAL;
1432
Rex Zhu2a507102017-02-20 17:07:36 +08001433 mutex_lock(&pp_handle->pp_lock);
1434
Rex Zhue273b042015-12-07 18:44:23 +08001435 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001436 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001437
Rex Zhu2a507102017-02-20 17:07:36 +08001438 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001439 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001440}
1441