blob: 6e0b35245555e92c0bd7c61380bdfbc60b8d99f3 [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 -0500225
Rex Zhu465f96e2016-09-18 16:52:03 +0800226int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500227{
Eric Huang03e39052016-02-09 16:26:00 -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 Huang03e39052016-02-09 16:26:00 -0500231
Rex Zhu1c863802016-12-28 19:43:23 +0800232 ret = pp_check(pp_handle);
Eric Huang03e39052016-02-09 16:26:00 -0500233
Rex Zhuae979882017-09-29 14:36:15 +0800234 if (!ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800235 return ret;
Eric Huang03e39052016-02-09 16:26:00 -0500236
Rex Zhu1c863802016-12-28 19:43:23 +0800237 hwmgr = pp_handle->hwmgr;
Eric Huang03e39052016-02-09 16:26:00 -0500238
Rex Zhu7383bcb2016-03-30 11:35:50 +0800239 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800240 pr_info("%s was not implemented.\n", __func__);
Flora Cui538333f2016-02-15 15:45:59 +0800241 return 0;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800242 }
Flora Cui538333f2016-02-15 15:45:59 +0800243
Rex Zhu465f96e2016-09-18 16:52:03 +0800244 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500245}
246
247static int pp_set_powergating_state(void *handle,
248 enum amd_powergating_state state)
249{
Eric Huang65f85e72016-02-11 15:54:45 -0500250 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800251 struct pp_instance *pp_handle = (struct pp_instance *)handle;
252 int ret = 0;
Eric Huang65f85e72016-02-11 15:54:45 -0500253
Rex Zhu1c863802016-12-28 19:43:23 +0800254 ret = pp_check(pp_handle);
Eric Huang65f85e72016-02-11 15:54:45 -0500255
Rex Zhuae979882017-09-29 14:36:15 +0800256 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800257 return ret;
Eric Huang65f85e72016-02-11 15:54:45 -0500258
Rex Zhu1c863802016-12-28 19:43:23 +0800259 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800260
261 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800262 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800263 return 0;
264 }
Eric Huang65f85e72016-02-11 15:54:45 -0500265
266 /* Enable/disable GFX per cu powergating through SMU */
267 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
Andrew F. Davis93a4aec2017-03-15 11:20:24 -0500268 state == AMD_PG_STATE_GATE);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500269}
270
271static int pp_suspend(void *handle)
272{
Rex Zhu1c863802016-12-28 19:43:23 +0800273 struct pp_instance *pp_handle = (struct pp_instance *)handle;
274 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800275
Rex Zhu1c863802016-12-28 19:43:23 +0800276 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800277 if (ret == 0)
278 hwmgr_hw_suspend(pp_handle);
279 return 0;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500280}
281
282static int pp_resume(void *handle)
283{
Rex Zhub3b03052017-09-26 13:28:27 -0400284 struct pp_hwmgr *hwmgr;
Rex Zhue5f23732017-09-29 13:57:54 +0800285 int ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800286 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800287
Rex Zhue5f23732017-09-29 13:57:54 +0800288 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800289
Rex Zhue5f23732017-09-29 13:57:54 +0800290 if (ret < 0)
291 return ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800292
Rex Zhub3b03052017-09-26 13:28:27 -0400293 hwmgr = pp_handle->hwmgr;
Rex Zhue0b71a72015-12-29 10:25:19 +0800294
Rex Zhub3b03052017-09-26 13:28:27 -0400295 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800296 return -EINVAL;
297
Rex Zhue5f23732017-09-29 13:57:54 +0800298 if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800299 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400300 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhue5f23732017-09-29 13:57:54 +0800301 return -EINVAL;
Rex Zhue0b71a72015-12-29 10:25:19 +0800302 }
303
Rex Zhue5f23732017-09-29 13:57:54 +0800304 if (ret == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800305 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800306
Rex Zhudf1e6392017-09-01 13:46:20 +0800307 return hwmgr_hw_resume(pp_handle);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500308}
309
310const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400311 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500312 .early_init = pp_early_init,
Rex Zhu6d07fe72017-09-25 18:51:50 +0800313 .late_init = pp_late_init,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500314 .sw_init = pp_sw_init,
315 .sw_fini = pp_sw_fini,
316 .hw_init = pp_hw_init,
317 .hw_fini = pp_hw_fini,
Rex Zhu139a2852017-09-25 20:46:37 +0800318 .late_fini = pp_late_fini,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500319 .suspend = pp_suspend,
320 .resume = pp_resume,
321 .is_idle = pp_is_idle,
322 .wait_for_idle = pp_wait_for_idle,
323 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800324 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500325 .set_powergating_state = pp_set_powergating_state,
326};
327
328static int pp_dpm_load_fw(void *handle)
329{
330 return 0;
331}
332
333static int pp_dpm_fw_loading_complete(void *handle)
334{
335 return 0;
336}
337
Rex Zhu9947f702017-08-29 16:08:56 +0800338static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
339 enum amd_dpm_forced_level *level)
340{
341 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
342 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
343 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
344 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
345
346 if (!(hwmgr->dpm_level & profile_mode_mask)) {
347 /* enter umd pstate, save current level, disable gfx cg*/
348 if (*level & profile_mode_mask) {
349 hwmgr->saved_dpm_level = hwmgr->dpm_level;
350 hwmgr->en_umd_pstate = true;
351 cgs_set_clockgating_state(hwmgr->device,
352 AMD_IP_BLOCK_TYPE_GFX,
353 AMD_CG_STATE_UNGATE);
354 cgs_set_powergating_state(hwmgr->device,
355 AMD_IP_BLOCK_TYPE_GFX,
356 AMD_PG_STATE_UNGATE);
357 }
358 } else {
359 /* exit umd pstate, restore level, enable gfx cg*/
360 if (!(*level & profile_mode_mask)) {
361 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
362 *level = hwmgr->saved_dpm_level;
363 hwmgr->en_umd_pstate = false;
364 cgs_set_clockgating_state(hwmgr->device,
365 AMD_IP_BLOCK_TYPE_GFX,
366 AMD_CG_STATE_GATE);
367 cgs_set_powergating_state(hwmgr->device,
368 AMD_IP_BLOCK_TYPE_GFX,
369 AMD_PG_STATE_GATE);
370 }
371 }
372}
373
Alex Deucher1f7371b2015-12-02 17:46:21 -0500374static int pp_dpm_force_performance_level(void *handle,
375 enum amd_dpm_forced_level level)
376{
Rex Zhu577bbe02015-08-28 12:56:43 +0800377 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800378 struct pp_instance *pp_handle = (struct pp_instance *)handle;
379 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800380
Rex Zhu1c863802016-12-28 19:43:23 +0800381 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800382
Rex Zhuae979882017-09-29 14:36:15 +0800383 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800384 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800385
386 hwmgr = pp_handle->hwmgr;
387
Rex Zhu9947f702017-08-29 16:08:56 +0800388 if (level == hwmgr->dpm_level)
389 return 0;
390
Rex Zhu7383bcb2016-03-30 11:35:50 +0800391 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800392 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800393 return 0;
394 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800395
Rex Zhu2a507102017-02-20 17:07:36 +0800396 mutex_lock(&pp_handle->pp_lock);
Rex Zhu9947f702017-08-29 16:08:56 +0800397 pp_dpm_en_umd_pstate(hwmgr, &level);
398 hwmgr->request_dpm_level = level;
Rex Zhudf1e6392017-09-01 13:46:20 +0800399 hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
Rex Zhu9947f702017-08-29 16:08:56 +0800400 ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
401 if (!ret)
402 hwmgr->dpm_level = hwmgr->request_dpm_level;
403
Rex Zhu2a507102017-02-20 17:07:36 +0800404 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500405 return 0;
406}
Rex Zhu577bbe02015-08-28 12:56:43 +0800407
Alex Deucher1f7371b2015-12-02 17:46:21 -0500408static enum amd_dpm_forced_level pp_dpm_get_performance_level(
409 void *handle)
410{
Rex Zhu577bbe02015-08-28 12:56:43 +0800411 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800412 struct pp_instance *pp_handle = (struct pp_instance *)handle;
413 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800414 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800415
Rex Zhu1c863802016-12-28 19:43:23 +0800416 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800417
Rex Zhuae979882017-09-29 14:36:15 +0800418 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800419 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800420
Rex Zhu1c863802016-12-28 19:43:23 +0800421 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800422 mutex_lock(&pp_handle->pp_lock);
423 level = hwmgr->dpm_level;
424 mutex_unlock(&pp_handle->pp_lock);
425 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500426}
Rex Zhu577bbe02015-08-28 12:56:43 +0800427
Rex Zhuf93f0c32017-09-06 16:08:03 +0800428static uint32_t pp_dpm_get_sclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500429{
Rex Zhu577bbe02015-08-28 12:56:43 +0800430 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800431 struct pp_instance *pp_handle = (struct pp_instance *)handle;
432 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800433 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800434
Rex Zhu1c863802016-12-28 19:43:23 +0800435 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800436
Rex Zhuae979882017-09-29 14:36:15 +0800437 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800438 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800439
Rex Zhu1c863802016-12-28 19:43:23 +0800440 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800441
442 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800443 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800444 return 0;
445 }
Rex Zhu2a507102017-02-20 17:07:36 +0800446 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800447 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800448 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800449 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500450}
Rex Zhu577bbe02015-08-28 12:56:43 +0800451
Rex Zhuf93f0c32017-09-06 16:08:03 +0800452static uint32_t pp_dpm_get_mclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500453{
Rex Zhu577bbe02015-08-28 12:56:43 +0800454 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800455 struct pp_instance *pp_handle = (struct pp_instance *)handle;
456 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800457 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800458
Rex Zhu1c863802016-12-28 19:43:23 +0800459 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800460
Rex Zhuae979882017-09-29 14:36:15 +0800461 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800462 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800463
Rex Zhu1c863802016-12-28 19:43:23 +0800464 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800465
466 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800467 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800468 return 0;
469 }
Rex Zhu2a507102017-02-20 17:07:36 +0800470 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800471 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800472 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800473 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500474}
Rex Zhu577bbe02015-08-28 12:56:43 +0800475
Rex Zhuf93f0c32017-09-06 16:08:03 +0800476static void pp_dpm_powergate_vce(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500477{
Rex Zhu577bbe02015-08-28 12:56:43 +0800478 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800479 struct pp_instance *pp_handle = (struct pp_instance *)handle;
480 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800481
Rex Zhu1c863802016-12-28 19:43:23 +0800482 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800483
Rex Zhuae979882017-09-29 14:36:15 +0800484 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800485 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800486
Rex Zhu1c863802016-12-28 19:43:23 +0800487 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800488
489 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800490 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800491 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800492 }
Rex Zhu2a507102017-02-20 17:07:36 +0800493 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800494 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800495 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500496}
Rex Zhu577bbe02015-08-28 12:56:43 +0800497
Rex Zhuf93f0c32017-09-06 16:08:03 +0800498static void pp_dpm_powergate_uvd(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500499{
Rex Zhu577bbe02015-08-28 12:56:43 +0800500 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800501 struct pp_instance *pp_handle = (struct pp_instance *)handle;
502 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800503
Rex Zhu1c863802016-12-28 19:43:23 +0800504 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800505
Rex Zhuae979882017-09-29 14:36:15 +0800506 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800507 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800508
Rex Zhu1c863802016-12-28 19:43:23 +0800509 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800510
511 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800512 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800513 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800514 }
Rex Zhu2a507102017-02-20 17:07:36 +0800515 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800516 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800517 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800518}
519
Rex Zhudf1e6392017-09-01 13:46:20 +0800520static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
Baoyou Xief8a4c112016-09-30 17:58:42 +0800521 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500522{
Rex Zhu577bbe02015-08-28 12:56:43 +0800523 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800524 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800525
Rex Zhu1c863802016-12-28 19:43:23 +0800526 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800527
Rex Zhuae979882017-09-29 14:36:15 +0800528 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800529 return ret;
Rex Zhudf1e6392017-09-01 13:46:20 +0800530
Rex Zhu2a507102017-02-20 17:07:36 +0800531 mutex_lock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800532 ret = hwmgr_handle_task(pp_handle, task_id, input, output);
Rex Zhu2a507102017-02-20 17:07:36 +0800533 mutex_unlock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800534
Rex Zhu577bbe02015-08-28 12:56:43 +0800535 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500536}
Rex Zhu577bbe02015-08-28 12:56:43 +0800537
Baoyou Xief8a4c112016-09-30 17:58:42 +0800538static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500539{
Rex Zhu577bbe02015-08-28 12:56:43 +0800540 struct pp_hwmgr *hwmgr;
541 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800542 struct pp_instance *pp_handle = (struct pp_instance *)handle;
543 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800544 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800545
Rex Zhu1c863802016-12-28 19:43:23 +0800546 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800547
Rex Zhuae979882017-09-29 14:36:15 +0800548 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800549 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800550
Rex Zhu1c863802016-12-28 19:43:23 +0800551 hwmgr = pp_handle->hwmgr;
552
553 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800554 return -EINVAL;
555
Rex Zhu2a507102017-02-20 17:07:36 +0800556 mutex_lock(&pp_handle->pp_lock);
557
Rex Zhu577bbe02015-08-28 12:56:43 +0800558 state = hwmgr->current_ps;
559
560 switch (state->classification.ui_label) {
561 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800562 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300563 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800564 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800565 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300566 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800567 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800568 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300569 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800570 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500571 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800572 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500573 else
Rex Zhu2a507102017-02-20 17:07:36 +0800574 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300575 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800576 }
Rex Zhu2a507102017-02-20 17:07:36 +0800577 mutex_unlock(&pp_handle->pp_lock);
578
579 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500580}
Rex Zhu577bbe02015-08-28 12:56:43 +0800581
Rex Zhuf93f0c32017-09-06 16:08:03 +0800582static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
Rex Zhucac9a192015-10-16 11:48:21 +0800583{
584 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800585 struct pp_instance *pp_handle = (struct pp_instance *)handle;
586 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800587
Rex Zhu1c863802016-12-28 19:43:23 +0800588 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800589
Rex Zhuae979882017-09-29 14:36:15 +0800590 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800591 return;
Rex Zhucac9a192015-10-16 11:48:21 +0800592
Rex Zhu1c863802016-12-28 19:43:23 +0800593 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800594
595 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800596 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800597 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800598 }
Rex Zhu2a507102017-02-20 17:07:36 +0800599 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800600 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
Rex Zhu2a507102017-02-20 17:07:36 +0800601 mutex_unlock(&pp_handle->pp_lock);
Rex Zhucac9a192015-10-16 11:48:21 +0800602}
603
Rex Zhuf93f0c32017-09-06 16:08:03 +0800604static uint32_t pp_dpm_get_fan_control_mode(void *handle)
Rex Zhucac9a192015-10-16 11:48:21 +0800605{
606 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800607 struct pp_instance *pp_handle = (struct pp_instance *)handle;
608 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800609 uint32_t mode = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800610
Rex Zhu1c863802016-12-28 19:43:23 +0800611 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800612
Rex Zhuae979882017-09-29 14:36:15 +0800613 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800614 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800615
Rex Zhu1c863802016-12-28 19:43:23 +0800616 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800617
618 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800619 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800620 return 0;
621 }
Rex Zhu2a507102017-02-20 17:07:36 +0800622 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800623 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
Rex Zhu2a507102017-02-20 17:07:36 +0800624 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800625 return mode;
Rex Zhucac9a192015-10-16 11:48:21 +0800626}
627
628static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
629{
630 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800631 struct pp_instance *pp_handle = (struct pp_instance *)handle;
632 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800633
Rex Zhu1c863802016-12-28 19:43:23 +0800634 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800635
Rex Zhuae979882017-09-29 14:36:15 +0800636 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800637 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800638
Rex Zhu1c863802016-12-28 19:43:23 +0800639 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800640
641 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800642 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800643 return 0;
644 }
Rex Zhu2a507102017-02-20 17:07:36 +0800645 mutex_lock(&pp_handle->pp_lock);
646 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
647 mutex_unlock(&pp_handle->pp_lock);
648 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800649}
650
651static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
652{
653 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800654 struct pp_instance *pp_handle = (struct pp_instance *)handle;
655 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800656
Rex Zhu1c863802016-12-28 19:43:23 +0800657 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800658
Rex Zhuae979882017-09-29 14:36:15 +0800659 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800660 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800661
Rex Zhu1c863802016-12-28 19:43:23 +0800662 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800663
664 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800665 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800666 return 0;
667 }
Rex Zhucac9a192015-10-16 11:48:21 +0800668
Rex Zhu2a507102017-02-20 17:07:36 +0800669 mutex_lock(&pp_handle->pp_lock);
670 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
671 mutex_unlock(&pp_handle->pp_lock);
672 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800673}
674
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300675static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
676{
677 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800678 struct pp_instance *pp_handle = (struct pp_instance *)handle;
679 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300680
Rex Zhu1c863802016-12-28 19:43:23 +0800681 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300682
Rex Zhuae979882017-09-29 14:36:15 +0800683 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800684 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300685
Rex Zhu1c863802016-12-28 19:43:23 +0800686 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300687
688 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
689 return -EINVAL;
690
Rex Zhu2a507102017-02-20 17:07:36 +0800691 mutex_lock(&pp_handle->pp_lock);
692 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
693 mutex_unlock(&pp_handle->pp_lock);
694 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300695}
696
Rex Zhucac9a192015-10-16 11:48:21 +0800697static int pp_dpm_get_temperature(void *handle)
698{
699 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800700 struct pp_instance *pp_handle = (struct pp_instance *)handle;
701 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800702
Rex Zhu1c863802016-12-28 19:43:23 +0800703 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800704
Rex Zhuae979882017-09-29 14:36:15 +0800705 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800706 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800707
Rex Zhu1c863802016-12-28 19:43:23 +0800708 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800709
710 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800711 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800712 return 0;
713 }
Rex Zhu2a507102017-02-20 17:07:36 +0800714 mutex_lock(&pp_handle->pp_lock);
715 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
716 mutex_unlock(&pp_handle->pp_lock);
717 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800718}
Rex Zhu577bbe02015-08-28 12:56:43 +0800719
Eric Huangf3898ea2015-12-11 16:24:34 -0500720static int pp_dpm_get_pp_num_states(void *handle,
721 struct pp_states_info *data)
722{
723 struct pp_hwmgr *hwmgr;
724 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800725 struct pp_instance *pp_handle = (struct pp_instance *)handle;
726 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500727
Rex Zhu1c863802016-12-28 19:43:23 +0800728 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500729
Rex Zhuae979882017-09-29 14:36:15 +0800730 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800731 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500732
Rex Zhu1c863802016-12-28 19:43:23 +0800733 hwmgr = pp_handle->hwmgr;
734
735 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500736 return -EINVAL;
737
Rex Zhu2a507102017-02-20 17:07:36 +0800738 mutex_lock(&pp_handle->pp_lock);
739
Eric Huangf3898ea2015-12-11 16:24:34 -0500740 data->nums = hwmgr->num_ps;
741
742 for (i = 0; i < hwmgr->num_ps; i++) {
743 struct pp_power_state *state = (struct pp_power_state *)
744 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
745 switch (state->classification.ui_label) {
746 case PP_StateUILabel_Battery:
747 data->states[i] = POWER_STATE_TYPE_BATTERY;
748 break;
749 case PP_StateUILabel_Balanced:
750 data->states[i] = POWER_STATE_TYPE_BALANCED;
751 break;
752 case PP_StateUILabel_Performance:
753 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
754 break;
755 default:
756 if (state->classification.flags & PP_StateClassificationFlag_Boot)
757 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
758 else
759 data->states[i] = POWER_STATE_TYPE_DEFAULT;
760 }
761 }
Rex Zhu2a507102017-02-20 17:07:36 +0800762 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500763 return 0;
764}
765
766static int pp_dpm_get_pp_table(void *handle, char **table)
767{
768 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800769 struct pp_instance *pp_handle = (struct pp_instance *)handle;
770 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800771 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500772
Rex Zhu1c863802016-12-28 19:43:23 +0800773 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500774
Rex Zhuae979882017-09-29 14:36:15 +0800775 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800776 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500777
Rex Zhu1c863802016-12-28 19:43:23 +0800778 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800779
Eric Huang4dcf9e62016-06-01 17:08:07 -0400780 if (!hwmgr->soft_pp_table)
781 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500782
Rex Zhu2a507102017-02-20 17:07:36 +0800783 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400784 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800785 size = hwmgr->soft_pp_table_size;
786 mutex_unlock(&pp_handle->pp_lock);
787 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500788}
789
790static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
791{
792 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800793 struct pp_instance *pp_handle = (struct pp_instance *)handle;
794 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500795
Rex Zhu1c863802016-12-28 19:43:23 +0800796 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500797
Rex Zhuae979882017-09-29 14:36:15 +0800798 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800799 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500800
Rex Zhu1c863802016-12-28 19:43:23 +0800801 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800802 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400803 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000804 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
805 hwmgr->soft_pp_table_size,
806 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800807 if (!hwmgr->hardcode_pp_table) {
808 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400809 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800810 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800811 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500812
Eric Huang4dcf9e62016-06-01 17:08:07 -0400813 memcpy(hwmgr->hardcode_pp_table, buf, size);
814
815 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800816 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400817
Eric Huangdd4bdf32017-03-01 15:49:31 -0500818 ret = amd_powerplay_reset(handle);
819 if (ret)
820 return ret;
821
822 if (hwmgr->hwmgr_func->avfs_control) {
823 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
824 if (ret)
825 return ret;
826 }
827
828 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500829}
830
831static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400832 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500833{
834 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800835 struct pp_instance *pp_handle = (struct pp_instance *)handle;
836 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500837
Rex Zhu1c863802016-12-28 19:43:23 +0800838 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500839
Rex Zhuae979882017-09-29 14:36:15 +0800840 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800841 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500842
Rex Zhu1c863802016-12-28 19:43:23 +0800843 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800844
845 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800846 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800847 return 0;
848 }
Rex Zhu2a507102017-02-20 17:07:36 +0800849 mutex_lock(&pp_handle->pp_lock);
850 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
851 mutex_unlock(&pp_handle->pp_lock);
852 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500853}
854
855static int pp_dpm_print_clock_levels(void *handle,
856 enum pp_clock_type type, char *buf)
857{
858 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800859 struct pp_instance *pp_handle = (struct pp_instance *)handle;
860 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500861
Rex Zhu1c863802016-12-28 19:43:23 +0800862 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500863
Rex Zhuae979882017-09-29 14:36:15 +0800864 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800865 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500866
Rex Zhu1c863802016-12-28 19:43:23 +0800867 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500868
Rex Zhu7383bcb2016-03-30 11:35:50 +0800869 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800870 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800871 return 0;
872 }
Rex Zhu2a507102017-02-20 17:07:36 +0800873 mutex_lock(&pp_handle->pp_lock);
874 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
875 mutex_unlock(&pp_handle->pp_lock);
876 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500877}
878
Eric Huang428bafa2016-05-12 14:51:21 -0400879static int pp_dpm_get_sclk_od(void *handle)
880{
881 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800882 struct pp_instance *pp_handle = (struct pp_instance *)handle;
883 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400884
Rex Zhu1c863802016-12-28 19:43:23 +0800885 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400886
Rex Zhuae979882017-09-29 14:36:15 +0800887 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800888 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400889
Rex Zhu1c863802016-12-28 19:43:23 +0800890 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400891
892 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800893 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400894 return 0;
895 }
Rex Zhu2a507102017-02-20 17:07:36 +0800896 mutex_lock(&pp_handle->pp_lock);
897 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
898 mutex_unlock(&pp_handle->pp_lock);
899 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400900}
901
902static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
903{
904 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800905 struct pp_instance *pp_handle = (struct pp_instance *)handle;
906 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400907
Rex Zhu1c863802016-12-28 19:43:23 +0800908 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400909
Rex Zhuae979882017-09-29 14:36:15 +0800910 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800911 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400912
Rex Zhu1c863802016-12-28 19:43:23 +0800913 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400914
915 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800916 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400917 return 0;
918 }
919
Rex Zhu2a507102017-02-20 17:07:36 +0800920 mutex_lock(&pp_handle->pp_lock);
921 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400922 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800923 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400924}
925
Eric Huangf2bdc052016-05-24 15:11:17 -0400926static int pp_dpm_get_mclk_od(void *handle)
927{
928 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800929 struct pp_instance *pp_handle = (struct pp_instance *)handle;
930 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400931
Rex Zhu1c863802016-12-28 19:43:23 +0800932 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400933
Rex Zhuae979882017-09-29 14:36:15 +0800934 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800935 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400936
Rex Zhu1c863802016-12-28 19:43:23 +0800937 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400938
939 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800940 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400941 return 0;
942 }
Rex Zhu2a507102017-02-20 17:07:36 +0800943 mutex_lock(&pp_handle->pp_lock);
944 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
945 mutex_unlock(&pp_handle->pp_lock);
946 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400947}
948
949static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
950{
951 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800952 struct pp_instance *pp_handle = (struct pp_instance *)handle;
953 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400954
Rex Zhu1c863802016-12-28 19:43:23 +0800955 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400956
Rex Zhuae979882017-09-29 14:36:15 +0800957 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800958 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400959
Rex Zhu1c863802016-12-28 19:43:23 +0800960 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400961
962 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800963 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400964 return 0;
965 }
Rex Zhu2a507102017-02-20 17:07:36 +0800966 mutex_lock(&pp_handle->pp_lock);
967 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
968 mutex_unlock(&pp_handle->pp_lock);
969 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400970}
971
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500972static int pp_dpm_read_sensor(void *handle, int idx,
973 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400974{
975 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800976 struct pp_instance *pp_handle = (struct pp_instance *)handle;
977 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400978
Rex Zhu1c863802016-12-28 19:43:23 +0800979 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400980
Rex Zhuae979882017-09-29 14:36:15 +0800981 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800982 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400983
Rex Zhu1c863802016-12-28 19:43:23 +0800984 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400985
986 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800987 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400988 return 0;
989 }
990
Rex Zhu2a507102017-02-20 17:07:36 +0800991 mutex_lock(&pp_handle->pp_lock);
992 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
993 mutex_unlock(&pp_handle->pp_lock);
994
995 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400996}
997
Alex Deucher597be302016-10-07 13:52:43 -0400998static struct amd_vce_state*
999pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
1000{
1001 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001002 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1003 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -04001004
Rex Zhu1c863802016-12-28 19:43:23 +08001005 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -04001006
Rex Zhuae979882017-09-29 14:36:15 +08001007 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001008 return NULL;
1009
1010 hwmgr = pp_handle->hwmgr;
1011
1012 if (hwmgr && idx < hwmgr->num_vce_state_tables)
1013 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -04001014 return NULL;
1015}
1016
Eric Huang34bb2732016-09-12 16:17:44 -04001017static int pp_dpm_reset_power_profile_state(void *handle,
1018 struct amd_pp_profile *request)
1019{
1020 struct pp_hwmgr *hwmgr;
1021 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1022
1023 if (!request || pp_check(pp_handle))
1024 return -EINVAL;
1025
1026 hwmgr = pp_handle->hwmgr;
1027
1028 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1029 pr_info("%s was not implemented.\n", __func__);
1030 return 0;
1031 }
1032
1033 if (request->type == AMD_PP_GFX_PROFILE) {
1034 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1035 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1036 &hwmgr->gfx_power_profile);
1037 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1038 hwmgr->compute_power_profile =
1039 hwmgr->default_compute_power_profile;
1040 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1041 &hwmgr->compute_power_profile);
1042 } else
1043 return -EINVAL;
1044}
1045
1046static int pp_dpm_get_power_profile_state(void *handle,
1047 struct amd_pp_profile *query)
1048{
1049 struct pp_hwmgr *hwmgr;
1050 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1051
1052 if (!query || pp_check(pp_handle))
1053 return -EINVAL;
1054
1055 hwmgr = pp_handle->hwmgr;
1056
1057 if (query->type == AMD_PP_GFX_PROFILE)
1058 memcpy(query, &hwmgr->gfx_power_profile,
1059 sizeof(struct amd_pp_profile));
1060 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1061 memcpy(query, &hwmgr->compute_power_profile,
1062 sizeof(struct amd_pp_profile));
1063 else
1064 return -EINVAL;
1065
1066 return 0;
1067}
1068
1069static int pp_dpm_set_power_profile_state(void *handle,
1070 struct amd_pp_profile *request)
1071{
1072 struct pp_hwmgr *hwmgr;
1073 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1074 int ret = -1;
1075
1076 if (!request || pp_check(pp_handle))
1077 return -EINVAL;
1078
1079 hwmgr = pp_handle->hwmgr;
1080
1081 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1082 pr_info("%s was not implemented.\n", __func__);
1083 return 0;
1084 }
1085
1086 if (request->min_sclk ||
1087 request->min_mclk ||
1088 request->activity_threshold ||
1089 request->up_hyst ||
1090 request->down_hyst) {
1091 if (request->type == AMD_PP_GFX_PROFILE)
1092 memcpy(&hwmgr->gfx_power_profile, request,
1093 sizeof(struct amd_pp_profile));
1094 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1095 memcpy(&hwmgr->compute_power_profile, request,
1096 sizeof(struct amd_pp_profile));
1097 else
1098 return -EINVAL;
1099
1100 if (request->type == hwmgr->current_power_profile)
1101 ret = hwmgr->hwmgr_func->set_power_profile_state(
1102 hwmgr,
1103 request);
1104 } else {
1105 /* set power profile if it exists */
1106 switch (request->type) {
1107 case AMD_PP_GFX_PROFILE:
1108 ret = hwmgr->hwmgr_func->set_power_profile_state(
1109 hwmgr,
1110 &hwmgr->gfx_power_profile);
1111 break;
1112 case AMD_PP_COMPUTE_PROFILE:
1113 ret = hwmgr->hwmgr_func->set_power_profile_state(
1114 hwmgr,
1115 &hwmgr->compute_power_profile);
1116 break;
1117 default:
1118 return -EINVAL;
1119 }
1120 }
1121
1122 if (!ret)
1123 hwmgr->current_power_profile = request->type;
1124
1125 return 0;
1126}
1127
1128static int pp_dpm_switch_power_profile(void *handle,
1129 enum amd_pp_profile_type type)
1130{
1131 struct pp_hwmgr *hwmgr;
1132 struct amd_pp_profile request = {0};
1133 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1134
1135 if (pp_check(pp_handle))
1136 return -EINVAL;
1137
1138 hwmgr = pp_handle->hwmgr;
1139
1140 if (hwmgr->current_power_profile != type) {
1141 request.type = type;
1142 pp_dpm_set_power_profile_state(handle, &request);
1143 }
1144
1145 return 0;
1146}
1147
Rex Zhuf93f0c32017-09-06 16:08:03 +08001148const struct amd_pm_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001149 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001150 .load_firmware = pp_dpm_load_fw,
1151 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1152 .force_performance_level = pp_dpm_force_performance_level,
1153 .get_performance_level = pp_dpm_get_performance_level,
1154 .get_current_power_state = pp_dpm_get_current_power_state,
1155 .get_sclk = pp_dpm_get_sclk,
1156 .get_mclk = pp_dpm_get_mclk,
1157 .powergate_vce = pp_dpm_powergate_vce,
1158 .powergate_uvd = pp_dpm_powergate_uvd,
1159 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001160 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1161 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1162 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1163 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001164 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001165 .get_pp_num_states = pp_dpm_get_pp_num_states,
1166 .get_pp_table = pp_dpm_get_pp_table,
1167 .set_pp_table = pp_dpm_set_pp_table,
1168 .force_clock_level = pp_dpm_force_clock_level,
1169 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001170 .get_sclk_od = pp_dpm_get_sclk_od,
1171 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001172 .get_mclk_od = pp_dpm_get_mclk_od,
1173 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001174 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001175 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001176 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1177 .get_power_profile_state = pp_dpm_get_power_profile_state,
1178 .set_power_profile_state = pp_dpm_set_power_profile_state,
1179 .switch_power_profile = pp_dpm_switch_power_profile,
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