blob: 3c8ef4bfc205c6c479ae89baafbfb127e6c0a3b6 [file] [log] [blame]
Alex Deucher1f7371b2015-12-02 17:46:21 -05001/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
Huang Rui7bd55422016-12-26 14:05:30 +080023#include "pp_debug.h"
Alex Deucher1f7371b2015-12-02 17:46:21 -050024#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/gfp.h>
Jammy Zhouac885b32015-07-21 17:43:02 +080027#include <linux/slab.h>
Alex Deucher1f7371b2015-12-02 17:46:21 -050028#include "amd_shared.h"
29#include "amd_powerplay.h"
Jammy Zhouac885b32015-07-21 17:43:02 +080030#include "pp_instance.h"
Rex Zhu577bbe02015-08-28 12:56:43 +080031#include "power_state.h"
Alex Deucher1f7371b2015-12-02 17:46:21 -050032
Rex Zhue5f23732017-09-29 13:57:54 +080033#define PP_DPM_DISABLED 0xCCCC
34
Rex Zhu6d07fe72017-09-25 18:51:50 +080035static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
36 void *input, void *output);
37
Rex Zhu1c863802016-12-28 19:43:23 +080038static inline int pp_check(struct pp_instance *handle)
39{
Rex Zhue1827a32017-09-28 16:12:51 +080040 if (handle == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080041 return -EINVAL;
Rex Zhua969e162015-12-29 13:56:03 +080042
Rex Zhub3b03052017-09-26 13:28:27 -040043 if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080044 return -EINVAL;
45
46 if (handle->pm_en == 0)
47 return PP_DPM_DISABLED;
48
Rex Zhub3b03052017-09-26 13:28:27 -040049 if (handle->hwmgr->hwmgr_func == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080050 return PP_DPM_DISABLED;
51
52 return 0;
53}
Rex Zhu7383bcb2016-03-30 11:35:50 +080054
Rex Zhu139a2852017-09-25 20:46:37 +080055static int amd_powerplay_create(struct amd_pp_init *pp_init,
56 void **handle)
57{
58 struct pp_instance *instance;
59
60 if (pp_init == NULL || handle == NULL)
61 return -EINVAL;
62
63 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
64 if (instance == NULL)
65 return -ENOMEM;
66
Rex Zhu139a2852017-09-25 20:46:37 +080067 instance->chip_family = pp_init->chip_family;
68 instance->chip_id = pp_init->chip_id;
69 instance->pm_en = pp_init->pm_en;
70 instance->feature_mask = pp_init->feature_mask;
71 instance->device = pp_init->device;
72 mutex_init(&instance->pp_lock);
73 *handle = instance;
74 return 0;
75}
76
77static int amd_powerplay_destroy(void *handle)
78{
79 struct pp_instance *instance = (struct pp_instance *)handle;
80
81 kfree(instance->hwmgr);
82 instance->hwmgr = NULL;
83
84 kfree(instance);
85 instance = NULL;
86 return 0;
87}
88
Alex Deucher1f7371b2015-12-02 17:46:21 -050089static int pp_early_init(void *handle)
90{
Rex Zhu1c863802016-12-28 19:43:23 +080091 int ret;
Rex Zhu139a2852017-09-25 20:46:37 +080092 struct pp_instance *pp_handle = NULL;
93
94 pp_handle = cgs_register_pp_handle(handle, amd_powerplay_create);
95
96 if (!pp_handle)
97 return -EINVAL;
Rex Zhu1c863802016-12-28 19:43:23 +080098
Rex Zhub3b03052017-09-26 13:28:27 -040099 ret = hwmgr_early_init(pp_handle);
Rex Zhu1c863802016-12-28 19:43:23 +0800100 if (ret)
Rex Zhub3b03052017-09-26 13:28:27 -0400101 return -EINVAL;
Rex Zhu1c863802016-12-28 19:43:23 +0800102
Alex Deucher1f7371b2015-12-02 17:46:21 -0500103 return 0;
104}
105
106static int pp_sw_init(void *handle)
107{
Rex Zhub3b03052017-09-26 13:28:27 -0400108 struct pp_hwmgr *hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800109 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800110 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800111
Rex Zhu1c863802016-12-28 19:43:23 +0800112 ret = pp_check(pp_handle);
Jammy Zhou3bace352015-07-21 21:18:15 +0800113
Rex Zhue5f23732017-09-29 13:57:54 +0800114 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400115 hwmgr = pp_handle->hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800116
Rex Zhub3b03052017-09-26 13:28:27 -0400117 if (hwmgr->smumgr_funcs->smu_init == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800118 return -EINVAL;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800119
Rex Zhub3b03052017-09-26 13:28:27 -0400120 ret = hwmgr->smumgr_funcs->smu_init(hwmgr);
Jammy Zhou3bace352015-07-21 21:18:15 +0800121
Rex Zhu1c863802016-12-28 19:43:23 +0800122 pr_info("amdgpu: powerplay sw initialized\n");
Huang Rui167112b2016-12-14 16:26:54 +0800123 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800124 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500125}
126
127static int pp_sw_fini(void *handle)
128{
Rex Zhub3b03052017-09-26 13:28:27 -0400129 struct pp_hwmgr *hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800130 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800131 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800132
Rex Zhu1c863802016-12-28 19:43:23 +0800133 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800134 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400135 hwmgr = pp_handle->hwmgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800136
Rex Zhub3b03052017-09-26 13:28:27 -0400137 if (hwmgr->smumgr_funcs->smu_fini == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800138 return -EINVAL;
Jammy Zhou3bace352015-07-21 21:18:15 +0800139
Rex Zhub3b03052017-09-26 13:28:27 -0400140 ret = hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhu1c863802016-12-28 19:43:23 +0800141 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800142 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500143}
144
145static int pp_hw_init(void *handle)
146{
Jammy Zhouac885b32015-07-21 17:43:02 +0800147 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800148 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhub3b03052017-09-26 13:28:27 -0400149 struct pp_hwmgr *hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800150
Rex Zhu1c863802016-12-28 19:43:23 +0800151 ret = pp_check(pp_handle);
Jammy Zhouac885b32015-07-21 17:43:02 +0800152
Rex Zhue5f23732017-09-29 13:57:54 +0800153 if (ret >= 0) {
Rex Zhub3b03052017-09-26 13:28:27 -0400154 hwmgr = pp_handle->hwmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800155
Rex Zhub3b03052017-09-26 13:28:27 -0400156 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +0800157 return -EINVAL;
Jammy Zhouac885b32015-07-21 17:43:02 +0800158
Rex Zhub3b03052017-09-26 13:28:27 -0400159 if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Rex Zhu1c863802016-12-28 19:43:23 +0800160 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400161 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhu1c863802016-12-28 19:43:23 +0800162 return -EINVAL;;
163 }
164 if (ret == PP_DPM_DISABLED)
Rex Zhue5f23732017-09-29 13:57:54 +0800165 goto exit;
166 ret = hwmgr_hw_init(pp_handle);
167 if (ret)
168 goto exit;
Jammy Zhouac885b32015-07-21 17:43:02 +0800169 }
Rex Zhue5f23732017-09-29 13:57:54 +0800170 return ret;
171exit:
Rex Zhu1c863802016-12-28 19:43:23 +0800172 pp_handle->pm_en = 0;
Rex Zhue5f23732017-09-29 13:57:54 +0800173 cgs_notify_dpm_enabled(hwmgr->device, false);
174 return 0;
175
Alex Deucher1f7371b2015-12-02 17:46:21 -0500176}
177
178static int pp_hw_fini(void *handle)
179{
Rex Zhu1c863802016-12-28 19:43:23 +0800180 struct pp_instance *pp_handle = (struct pp_instance *)handle;
181 int ret = 0;
Jammy Zhouac885b32015-07-21 17:43:02 +0800182
Rex Zhu1c863802016-12-28 19:43:23 +0800183 ret = pp_check(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800184 if (ret == 0)
Rex Zhu1c863802016-12-28 19:43:23 +0800185 hwmgr_hw_fini(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800186
Alex Deucher1f7371b2015-12-02 17:46:21 -0500187 return 0;
188}
189
Rex Zhu6d07fe72017-09-25 18:51:50 +0800190static int pp_late_init(void *handle)
191{
192 struct pp_instance *pp_handle = (struct pp_instance *)handle;
193 int ret = 0;
194
195 ret = pp_check(pp_handle);
196 if (ret == 0)
197 pp_dpm_dispatch_tasks(pp_handle,
198 AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
199
200 return 0;
201}
202
Rex Zhu139a2852017-09-25 20:46:37 +0800203static void pp_late_fini(void *handle)
204{
205 amd_powerplay_destroy(handle);
206}
207
208
Alex Deucher1f7371b2015-12-02 17:46:21 -0500209static bool pp_is_idle(void *handle)
210{
Edward O'Callaghaned5121a2016-07-12 10:17:52 +1000211 return false;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500212}
213
214static int pp_wait_for_idle(void *handle)
215{
216 return 0;
217}
218
219static int pp_sw_reset(void *handle)
220{
221 return 0;
222}
223
Alex Deucher1f7371b2015-12-02 17:46:21 -0500224static int pp_set_powergating_state(void *handle,
225 enum amd_powergating_state state)
226{
Eric Huang65f85e72016-02-11 15:54:45 -0500227 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800228 struct pp_instance *pp_handle = (struct pp_instance *)handle;
229 int ret = 0;
Eric Huang65f85e72016-02-11 15:54:45 -0500230
Rex Zhu1c863802016-12-28 19:43:23 +0800231 ret = pp_check(pp_handle);
Eric Huang65f85e72016-02-11 15:54:45 -0500232
Rex Zhuae979882017-09-29 14:36:15 +0800233 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800234 return ret;
Eric Huang65f85e72016-02-11 15:54:45 -0500235
Rex Zhu1c863802016-12-28 19:43:23 +0800236 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800237
238 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800239 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800240 return 0;
241 }
Eric Huang65f85e72016-02-11 15:54:45 -0500242
243 /* Enable/disable GFX per cu powergating through SMU */
244 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
Andrew F. Davis93a4aec2017-03-15 11:20:24 -0500245 state == AMD_PG_STATE_GATE);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500246}
247
248static int pp_suspend(void *handle)
249{
Rex Zhu1c863802016-12-28 19:43:23 +0800250 struct pp_instance *pp_handle = (struct pp_instance *)handle;
251 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800252
Rex Zhu1c863802016-12-28 19:43:23 +0800253 ret = pp_check(pp_handle);
Rex Zhue5f23732017-09-29 13:57:54 +0800254 if (ret == 0)
255 hwmgr_hw_suspend(pp_handle);
256 return 0;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500257}
258
259static int pp_resume(void *handle)
260{
Rex Zhub3b03052017-09-26 13:28:27 -0400261 struct pp_hwmgr *hwmgr;
Rex Zhue5f23732017-09-29 13:57:54 +0800262 int ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800263 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800264
Rex Zhue5f23732017-09-29 13:57:54 +0800265 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800266
Rex Zhue5f23732017-09-29 13:57:54 +0800267 if (ret < 0)
268 return ret;
Rex Zhu1c863802016-12-28 19:43:23 +0800269
Rex Zhub3b03052017-09-26 13:28:27 -0400270 hwmgr = pp_handle->hwmgr;
Rex Zhue0b71a72015-12-29 10:25:19 +0800271
Rex Zhub3b03052017-09-26 13:28:27 -0400272 if (hwmgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800273 return -EINVAL;
274
Rex Zhue5f23732017-09-29 13:57:54 +0800275 if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800276 pr_err("smc start failed\n");
Rex Zhub3b03052017-09-26 13:28:27 -0400277 hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr);
Rex Zhue5f23732017-09-29 13:57:54 +0800278 return -EINVAL;
Rex Zhue0b71a72015-12-29 10:25:19 +0800279 }
280
Rex Zhue5f23732017-09-29 13:57:54 +0800281 if (ret == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800282 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800283
Rex Zhudf1e6392017-09-01 13:46:20 +0800284 return hwmgr_hw_resume(pp_handle);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500285}
286
287const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400288 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500289 .early_init = pp_early_init,
Rex Zhu6d07fe72017-09-25 18:51:50 +0800290 .late_init = pp_late_init,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500291 .sw_init = pp_sw_init,
292 .sw_fini = pp_sw_fini,
293 .hw_init = pp_hw_init,
294 .hw_fini = pp_hw_fini,
Rex Zhu139a2852017-09-25 20:46:37 +0800295 .late_fini = pp_late_fini,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500296 .suspend = pp_suspend,
297 .resume = pp_resume,
298 .is_idle = pp_is_idle,
299 .wait_for_idle = pp_wait_for_idle,
300 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800301 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500302 .set_powergating_state = pp_set_powergating_state,
303};
304
305static int pp_dpm_load_fw(void *handle)
306{
307 return 0;
308}
309
310static int pp_dpm_fw_loading_complete(void *handle)
311{
312 return 0;
313}
314
Rex Zhu3811f8f2017-09-26 13:39:38 +0800315static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id)
316{
317 struct pp_hwmgr *hwmgr;
318 struct pp_instance *pp_handle = (struct pp_instance *)handle;
319 int ret = 0;
320
321 ret = pp_check(pp_handle);
322
323 if (ret)
324 return ret;
325
326 hwmgr = pp_handle->hwmgr;
327
328 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
329 pr_info("%s was not implemented.\n", __func__);
330 return 0;
331 }
332
333 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
334}
335
Rex Zhu9947f702017-08-29 16:08:56 +0800336static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr,
337 enum amd_dpm_forced_level *level)
338{
339 uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
340 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
341 AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
342 AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
343
344 if (!(hwmgr->dpm_level & profile_mode_mask)) {
345 /* enter umd pstate, save current level, disable gfx cg*/
346 if (*level & profile_mode_mask) {
347 hwmgr->saved_dpm_level = hwmgr->dpm_level;
348 hwmgr->en_umd_pstate = true;
349 cgs_set_clockgating_state(hwmgr->device,
350 AMD_IP_BLOCK_TYPE_GFX,
351 AMD_CG_STATE_UNGATE);
352 cgs_set_powergating_state(hwmgr->device,
353 AMD_IP_BLOCK_TYPE_GFX,
354 AMD_PG_STATE_UNGATE);
355 }
356 } else {
357 /* exit umd pstate, restore level, enable gfx cg*/
358 if (!(*level & profile_mode_mask)) {
359 if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
360 *level = hwmgr->saved_dpm_level;
361 hwmgr->en_umd_pstate = false;
362 cgs_set_clockgating_state(hwmgr->device,
363 AMD_IP_BLOCK_TYPE_GFX,
364 AMD_CG_STATE_GATE);
365 cgs_set_powergating_state(hwmgr->device,
366 AMD_IP_BLOCK_TYPE_GFX,
367 AMD_PG_STATE_GATE);
368 }
369 }
370}
371
Alex Deucher1f7371b2015-12-02 17:46:21 -0500372static int pp_dpm_force_performance_level(void *handle,
373 enum amd_dpm_forced_level level)
374{
Rex Zhu577bbe02015-08-28 12:56:43 +0800375 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800376 struct pp_instance *pp_handle = (struct pp_instance *)handle;
377 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800378
Rex Zhu1c863802016-12-28 19:43:23 +0800379 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800380
Rex Zhuae979882017-09-29 14:36:15 +0800381 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800382 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800383
384 hwmgr = pp_handle->hwmgr;
385
Rex Zhu9947f702017-08-29 16:08:56 +0800386 if (level == hwmgr->dpm_level)
387 return 0;
388
Rex Zhu7383bcb2016-03-30 11:35:50 +0800389 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800390 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800391 return 0;
392 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800393
Rex Zhu2a507102017-02-20 17:07:36 +0800394 mutex_lock(&pp_handle->pp_lock);
Rex Zhu9947f702017-08-29 16:08:56 +0800395 pp_dpm_en_umd_pstate(hwmgr, &level);
396 hwmgr->request_dpm_level = level;
Rex Zhudf1e6392017-09-01 13:46:20 +0800397 hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
Rex Zhu9947f702017-08-29 16:08:56 +0800398 ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
399 if (!ret)
400 hwmgr->dpm_level = hwmgr->request_dpm_level;
401
Rex Zhu2a507102017-02-20 17:07:36 +0800402 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500403 return 0;
404}
Rex Zhu577bbe02015-08-28 12:56:43 +0800405
Alex Deucher1f7371b2015-12-02 17:46:21 -0500406static enum amd_dpm_forced_level pp_dpm_get_performance_level(
407 void *handle)
408{
Rex Zhu577bbe02015-08-28 12:56:43 +0800409 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800410 struct pp_instance *pp_handle = (struct pp_instance *)handle;
411 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800412 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800413
Rex Zhu1c863802016-12-28 19:43:23 +0800414 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800415
Rex Zhuae979882017-09-29 14:36:15 +0800416 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800417 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800418
Rex Zhu1c863802016-12-28 19:43:23 +0800419 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800420 mutex_lock(&pp_handle->pp_lock);
421 level = hwmgr->dpm_level;
422 mutex_unlock(&pp_handle->pp_lock);
423 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500424}
Rex Zhu577bbe02015-08-28 12:56:43 +0800425
Rex Zhuf93f0c32017-09-06 16:08:03 +0800426static uint32_t pp_dpm_get_sclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500427{
Rex Zhu577bbe02015-08-28 12:56:43 +0800428 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800429 struct pp_instance *pp_handle = (struct pp_instance *)handle;
430 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800431 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800432
Rex Zhu1c863802016-12-28 19:43:23 +0800433 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800434
Rex Zhuae979882017-09-29 14:36:15 +0800435 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800436 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800437
Rex Zhu1c863802016-12-28 19:43:23 +0800438 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800439
440 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800441 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800442 return 0;
443 }
Rex Zhu2a507102017-02-20 17:07:36 +0800444 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800445 clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800446 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800447 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500448}
Rex Zhu577bbe02015-08-28 12:56:43 +0800449
Rex Zhuf93f0c32017-09-06 16:08:03 +0800450static uint32_t pp_dpm_get_mclk(void *handle, bool low)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500451{
Rex Zhu577bbe02015-08-28 12:56:43 +0800452 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800453 struct pp_instance *pp_handle = (struct pp_instance *)handle;
454 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800455 uint32_t clk = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800456
Rex Zhu1c863802016-12-28 19:43:23 +0800457 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800458
Rex Zhuae979882017-09-29 14:36:15 +0800459 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800460 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800461
Rex Zhu1c863802016-12-28 19:43:23 +0800462 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800463
464 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800465 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800466 return 0;
467 }
Rex Zhu2a507102017-02-20 17:07:36 +0800468 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800469 clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
Rex Zhu2a507102017-02-20 17:07:36 +0800470 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800471 return clk;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500472}
Rex Zhu577bbe02015-08-28 12:56:43 +0800473
Rex Zhuf93f0c32017-09-06 16:08:03 +0800474static void pp_dpm_powergate_vce(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500475{
Rex Zhu577bbe02015-08-28 12:56:43 +0800476 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800477 struct pp_instance *pp_handle = (struct pp_instance *)handle;
478 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800479
Rex Zhu1c863802016-12-28 19:43:23 +0800480 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800481
Rex Zhuae979882017-09-29 14:36:15 +0800482 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800483 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800484
Rex Zhu1c863802016-12-28 19:43:23 +0800485 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800486
487 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800488 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800489 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800490 }
Rex Zhu2a507102017-02-20 17:07:36 +0800491 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800492 hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800493 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500494}
Rex Zhu577bbe02015-08-28 12:56:43 +0800495
Rex Zhuf93f0c32017-09-06 16:08:03 +0800496static void pp_dpm_powergate_uvd(void *handle, bool gate)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500497{
Rex Zhu577bbe02015-08-28 12:56:43 +0800498 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800499 struct pp_instance *pp_handle = (struct pp_instance *)handle;
500 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800501
Rex Zhu1c863802016-12-28 19:43:23 +0800502 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800503
Rex Zhuae979882017-09-29 14:36:15 +0800504 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800505 return;
Rex Zhu577bbe02015-08-28 12:56:43 +0800506
Rex Zhu1c863802016-12-28 19:43:23 +0800507 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800508
509 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800510 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800511 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800512 }
Rex Zhu2a507102017-02-20 17:07:36 +0800513 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800514 hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
Rex Zhu2a507102017-02-20 17:07:36 +0800515 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800516}
517
Rex Zhudf1e6392017-09-01 13:46:20 +0800518static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
Baoyou Xief8a4c112016-09-30 17:58:42 +0800519 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500520{
Rex Zhu577bbe02015-08-28 12:56:43 +0800521 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800522 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800523
Rex Zhu1c863802016-12-28 19:43:23 +0800524 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800525
Rex Zhuae979882017-09-29 14:36:15 +0800526 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800527 return ret;
Rex Zhudf1e6392017-09-01 13:46:20 +0800528
Rex Zhu2a507102017-02-20 17:07:36 +0800529 mutex_lock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800530 ret = hwmgr_handle_task(pp_handle, task_id, input, output);
Rex Zhu2a507102017-02-20 17:07:36 +0800531 mutex_unlock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800532
Rex Zhu577bbe02015-08-28 12:56:43 +0800533 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500534}
Rex Zhu577bbe02015-08-28 12:56:43 +0800535
Baoyou Xief8a4c112016-09-30 17:58:42 +0800536static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500537{
Rex Zhu577bbe02015-08-28 12:56:43 +0800538 struct pp_hwmgr *hwmgr;
539 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800540 struct pp_instance *pp_handle = (struct pp_instance *)handle;
541 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800542 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800543
Rex Zhu1c863802016-12-28 19:43:23 +0800544 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800545
Rex Zhuae979882017-09-29 14:36:15 +0800546 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800547 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800548
Rex Zhu1c863802016-12-28 19:43:23 +0800549 hwmgr = pp_handle->hwmgr;
550
551 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800552 return -EINVAL;
553
Rex Zhu2a507102017-02-20 17:07:36 +0800554 mutex_lock(&pp_handle->pp_lock);
555
Rex Zhu577bbe02015-08-28 12:56:43 +0800556 state = hwmgr->current_ps;
557
558 switch (state->classification.ui_label) {
559 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800560 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300561 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800562 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800563 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300564 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800565 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800566 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300567 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800568 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500569 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800570 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500571 else
Rex Zhu2a507102017-02-20 17:07:36 +0800572 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300573 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800574 }
Rex Zhu2a507102017-02-20 17:07:36 +0800575 mutex_unlock(&pp_handle->pp_lock);
576
577 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500578}
Rex Zhu577bbe02015-08-28 12:56:43 +0800579
Rex Zhuf93f0c32017-09-06 16:08:03 +0800580static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
Rex Zhucac9a192015-10-16 11:48:21 +0800581{
582 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800583 struct pp_instance *pp_handle = (struct pp_instance *)handle;
584 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800585
Rex Zhu1c863802016-12-28 19:43:23 +0800586 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800587
Rex Zhuae979882017-09-29 14:36:15 +0800588 if (ret)
Rex Zhuf93f0c32017-09-06 16:08:03 +0800589 return;
Rex Zhucac9a192015-10-16 11:48:21 +0800590
Rex Zhu1c863802016-12-28 19:43:23 +0800591 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800592
593 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800594 pr_info("%s was not implemented.\n", __func__);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800595 return;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800596 }
Rex Zhu2a507102017-02-20 17:07:36 +0800597 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800598 hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
Rex Zhu2a507102017-02-20 17:07:36 +0800599 mutex_unlock(&pp_handle->pp_lock);
Rex Zhucac9a192015-10-16 11:48:21 +0800600}
601
Rex Zhuf93f0c32017-09-06 16:08:03 +0800602static uint32_t pp_dpm_get_fan_control_mode(void *handle)
Rex Zhucac9a192015-10-16 11:48:21 +0800603{
604 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800605 struct pp_instance *pp_handle = (struct pp_instance *)handle;
606 int ret = 0;
Rex Zhuf93f0c32017-09-06 16:08:03 +0800607 uint32_t mode = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800608
Rex Zhu1c863802016-12-28 19:43:23 +0800609 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800610
Rex Zhuae979882017-09-29 14:36:15 +0800611 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800612 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800613
Rex Zhu1c863802016-12-28 19:43:23 +0800614 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800615
616 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800617 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800618 return 0;
619 }
Rex Zhu2a507102017-02-20 17:07:36 +0800620 mutex_lock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800621 mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
Rex Zhu2a507102017-02-20 17:07:36 +0800622 mutex_unlock(&pp_handle->pp_lock);
Rex Zhuf93f0c32017-09-06 16:08:03 +0800623 return mode;
Rex Zhucac9a192015-10-16 11:48:21 +0800624}
625
626static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
627{
628 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800629 struct pp_instance *pp_handle = (struct pp_instance *)handle;
630 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800631
Rex Zhu1c863802016-12-28 19:43:23 +0800632 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800633
Rex Zhuae979882017-09-29 14:36:15 +0800634 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800635 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800636
Rex Zhu1c863802016-12-28 19:43:23 +0800637 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800638
639 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800640 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800641 return 0;
642 }
Rex Zhu2a507102017-02-20 17:07:36 +0800643 mutex_lock(&pp_handle->pp_lock);
644 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
645 mutex_unlock(&pp_handle->pp_lock);
646 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800647}
648
649static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
650{
651 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800652 struct pp_instance *pp_handle = (struct pp_instance *)handle;
653 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800654
Rex Zhu1c863802016-12-28 19:43:23 +0800655 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800656
Rex Zhuae979882017-09-29 14:36:15 +0800657 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800658 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800659
Rex Zhu1c863802016-12-28 19:43:23 +0800660 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800661
662 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800663 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800664 return 0;
665 }
Rex Zhucac9a192015-10-16 11:48:21 +0800666
Rex Zhu2a507102017-02-20 17:07:36 +0800667 mutex_lock(&pp_handle->pp_lock);
668 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
669 mutex_unlock(&pp_handle->pp_lock);
670 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800671}
672
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300673static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
674{
675 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800676 struct pp_instance *pp_handle = (struct pp_instance *)handle;
677 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300678
Rex Zhu1c863802016-12-28 19:43:23 +0800679 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300680
Rex Zhuae979882017-09-29 14:36:15 +0800681 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800682 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300683
Rex Zhu1c863802016-12-28 19:43:23 +0800684 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300685
686 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
687 return -EINVAL;
688
Rex Zhu2a507102017-02-20 17:07:36 +0800689 mutex_lock(&pp_handle->pp_lock);
690 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
691 mutex_unlock(&pp_handle->pp_lock);
692 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300693}
694
Rex Zhucac9a192015-10-16 11:48:21 +0800695static int pp_dpm_get_temperature(void *handle)
696{
697 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800698 struct pp_instance *pp_handle = (struct pp_instance *)handle;
699 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800700
Rex Zhu1c863802016-12-28 19:43:23 +0800701 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800702
Rex Zhuae979882017-09-29 14:36:15 +0800703 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800704 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800705
Rex Zhu1c863802016-12-28 19:43:23 +0800706 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800707
708 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800709 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800710 return 0;
711 }
Rex Zhu2a507102017-02-20 17:07:36 +0800712 mutex_lock(&pp_handle->pp_lock);
713 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
714 mutex_unlock(&pp_handle->pp_lock);
715 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800716}
Rex Zhu577bbe02015-08-28 12:56:43 +0800717
Eric Huangf3898ea2015-12-11 16:24:34 -0500718static int pp_dpm_get_pp_num_states(void *handle,
719 struct pp_states_info *data)
720{
721 struct pp_hwmgr *hwmgr;
722 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800723 struct pp_instance *pp_handle = (struct pp_instance *)handle;
724 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500725
Rex Zhu1c863802016-12-28 19:43:23 +0800726 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500727
Rex Zhuae979882017-09-29 14:36:15 +0800728 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800729 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500730
Rex Zhu1c863802016-12-28 19:43:23 +0800731 hwmgr = pp_handle->hwmgr;
732
733 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500734 return -EINVAL;
735
Rex Zhu2a507102017-02-20 17:07:36 +0800736 mutex_lock(&pp_handle->pp_lock);
737
Eric Huangf3898ea2015-12-11 16:24:34 -0500738 data->nums = hwmgr->num_ps;
739
740 for (i = 0; i < hwmgr->num_ps; i++) {
741 struct pp_power_state *state = (struct pp_power_state *)
742 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
743 switch (state->classification.ui_label) {
744 case PP_StateUILabel_Battery:
745 data->states[i] = POWER_STATE_TYPE_BATTERY;
746 break;
747 case PP_StateUILabel_Balanced:
748 data->states[i] = POWER_STATE_TYPE_BALANCED;
749 break;
750 case PP_StateUILabel_Performance:
751 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
752 break;
753 default:
754 if (state->classification.flags & PP_StateClassificationFlag_Boot)
755 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
756 else
757 data->states[i] = POWER_STATE_TYPE_DEFAULT;
758 }
759 }
Rex Zhu2a507102017-02-20 17:07:36 +0800760 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500761 return 0;
762}
763
764static int pp_dpm_get_pp_table(void *handle, char **table)
765{
766 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800767 struct pp_instance *pp_handle = (struct pp_instance *)handle;
768 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800769 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500770
Rex Zhu1c863802016-12-28 19:43:23 +0800771 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500772
Rex Zhuae979882017-09-29 14:36:15 +0800773 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800774 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500775
Rex Zhu1c863802016-12-28 19:43:23 +0800776 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800777
Eric Huang4dcf9e62016-06-01 17:08:07 -0400778 if (!hwmgr->soft_pp_table)
779 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500780
Rex Zhu2a507102017-02-20 17:07:36 +0800781 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400782 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800783 size = hwmgr->soft_pp_table_size;
784 mutex_unlock(&pp_handle->pp_lock);
785 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500786}
787
788static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
789{
790 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800791 struct pp_instance *pp_handle = (struct pp_instance *)handle;
792 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500793
Rex Zhu1c863802016-12-28 19:43:23 +0800794 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500795
Rex Zhuae979882017-09-29 14:36:15 +0800796 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800797 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500798
Rex Zhu1c863802016-12-28 19:43:23 +0800799 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800800 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400801 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000802 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
803 hwmgr->soft_pp_table_size,
804 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800805 if (!hwmgr->hardcode_pp_table) {
806 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400807 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800808 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800809 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500810
Eric Huang4dcf9e62016-06-01 17:08:07 -0400811 memcpy(hwmgr->hardcode_pp_table, buf, size);
812
813 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800814 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400815
Eric Huangdd4bdf32017-03-01 15:49:31 -0500816 ret = amd_powerplay_reset(handle);
817 if (ret)
818 return ret;
819
820 if (hwmgr->hwmgr_func->avfs_control) {
821 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
822 if (ret)
823 return ret;
824 }
825
826 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500827}
828
829static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400830 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500831{
832 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800833 struct pp_instance *pp_handle = (struct pp_instance *)handle;
834 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500835
Rex Zhu1c863802016-12-28 19:43:23 +0800836 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500837
Rex Zhuae979882017-09-29 14:36:15 +0800838 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800839 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500840
Rex Zhu1c863802016-12-28 19:43:23 +0800841 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800842
843 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800844 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800845 return 0;
846 }
Rex Zhu2a507102017-02-20 17:07:36 +0800847 mutex_lock(&pp_handle->pp_lock);
848 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
849 mutex_unlock(&pp_handle->pp_lock);
850 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500851}
852
853static int pp_dpm_print_clock_levels(void *handle,
854 enum pp_clock_type type, char *buf)
855{
856 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800857 struct pp_instance *pp_handle = (struct pp_instance *)handle;
858 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500859
Rex Zhu1c863802016-12-28 19:43:23 +0800860 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500861
Rex Zhuae979882017-09-29 14:36:15 +0800862 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800863 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500864
Rex Zhu1c863802016-12-28 19:43:23 +0800865 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500866
Rex Zhu7383bcb2016-03-30 11:35:50 +0800867 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800868 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800869 return 0;
870 }
Rex Zhu2a507102017-02-20 17:07:36 +0800871 mutex_lock(&pp_handle->pp_lock);
872 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
873 mutex_unlock(&pp_handle->pp_lock);
874 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500875}
876
Eric Huang428bafa2016-05-12 14:51:21 -0400877static int pp_dpm_get_sclk_od(void *handle)
878{
879 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800880 struct pp_instance *pp_handle = (struct pp_instance *)handle;
881 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400882
Rex Zhu1c863802016-12-28 19:43:23 +0800883 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400884
Rex Zhuae979882017-09-29 14:36:15 +0800885 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800886 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400887
Rex Zhu1c863802016-12-28 19:43:23 +0800888 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400889
890 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800891 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400892 return 0;
893 }
Rex Zhu2a507102017-02-20 17:07:36 +0800894 mutex_lock(&pp_handle->pp_lock);
895 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
896 mutex_unlock(&pp_handle->pp_lock);
897 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400898}
899
900static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
901{
902 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800903 struct pp_instance *pp_handle = (struct pp_instance *)handle;
904 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400905
Rex Zhu1c863802016-12-28 19:43:23 +0800906 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400907
Rex Zhuae979882017-09-29 14:36:15 +0800908 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800909 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400910
Rex Zhu1c863802016-12-28 19:43:23 +0800911 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400912
913 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800914 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400915 return 0;
916 }
917
Rex Zhu2a507102017-02-20 17:07:36 +0800918 mutex_lock(&pp_handle->pp_lock);
919 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400920 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800921 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400922}
923
Eric Huangf2bdc052016-05-24 15:11:17 -0400924static int pp_dpm_get_mclk_od(void *handle)
925{
926 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800927 struct pp_instance *pp_handle = (struct pp_instance *)handle;
928 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400929
Rex Zhu1c863802016-12-28 19:43:23 +0800930 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400931
Rex Zhuae979882017-09-29 14:36:15 +0800932 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800933 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400934
Rex Zhu1c863802016-12-28 19:43:23 +0800935 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400936
937 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800938 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400939 return 0;
940 }
Rex Zhu2a507102017-02-20 17:07:36 +0800941 mutex_lock(&pp_handle->pp_lock);
942 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
943 mutex_unlock(&pp_handle->pp_lock);
944 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400945}
946
947static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
948{
949 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800950 struct pp_instance *pp_handle = (struct pp_instance *)handle;
951 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400952
Rex Zhu1c863802016-12-28 19:43:23 +0800953 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400954
Rex Zhuae979882017-09-29 14:36:15 +0800955 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800956 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400957
Rex Zhu1c863802016-12-28 19:43:23 +0800958 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400959
960 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800961 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400962 return 0;
963 }
Rex Zhu2a507102017-02-20 17:07:36 +0800964 mutex_lock(&pp_handle->pp_lock);
965 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
966 mutex_unlock(&pp_handle->pp_lock);
967 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400968}
969
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500970static int pp_dpm_read_sensor(void *handle, int idx,
971 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400972{
973 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800974 struct pp_instance *pp_handle = (struct pp_instance *)handle;
975 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400976
Rex Zhu1c863802016-12-28 19:43:23 +0800977 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400978
Rex Zhuae979882017-09-29 14:36:15 +0800979 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +0800980 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400981
Rex Zhu1c863802016-12-28 19:43:23 +0800982 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400983
984 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800985 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400986 return 0;
987 }
988
Rex Zhu2a507102017-02-20 17:07:36 +0800989 mutex_lock(&pp_handle->pp_lock);
990 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
991 mutex_unlock(&pp_handle->pp_lock);
992
993 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400994}
995
Alex Deucher597be302016-10-07 13:52:43 -0400996static struct amd_vce_state*
997pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
998{
999 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001000 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1001 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -04001002
Rex Zhu1c863802016-12-28 19:43:23 +08001003 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -04001004
Rex Zhuae979882017-09-29 14:36:15 +08001005 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001006 return NULL;
1007
1008 hwmgr = pp_handle->hwmgr;
1009
1010 if (hwmgr && idx < hwmgr->num_vce_state_tables)
1011 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -04001012 return NULL;
1013}
1014
Eric Huang34bb2732016-09-12 16:17:44 -04001015static int pp_dpm_reset_power_profile_state(void *handle,
1016 struct amd_pp_profile *request)
1017{
1018 struct pp_hwmgr *hwmgr;
1019 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1020
1021 if (!request || pp_check(pp_handle))
1022 return -EINVAL;
1023
1024 hwmgr = pp_handle->hwmgr;
1025
1026 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1027 pr_info("%s was not implemented.\n", __func__);
1028 return 0;
1029 }
1030
1031 if (request->type == AMD_PP_GFX_PROFILE) {
1032 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1033 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1034 &hwmgr->gfx_power_profile);
1035 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1036 hwmgr->compute_power_profile =
1037 hwmgr->default_compute_power_profile;
1038 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1039 &hwmgr->compute_power_profile);
1040 } else
1041 return -EINVAL;
1042}
1043
1044static int pp_dpm_get_power_profile_state(void *handle,
1045 struct amd_pp_profile *query)
1046{
1047 struct pp_hwmgr *hwmgr;
1048 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1049
1050 if (!query || pp_check(pp_handle))
1051 return -EINVAL;
1052
1053 hwmgr = pp_handle->hwmgr;
1054
1055 if (query->type == AMD_PP_GFX_PROFILE)
1056 memcpy(query, &hwmgr->gfx_power_profile,
1057 sizeof(struct amd_pp_profile));
1058 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1059 memcpy(query, &hwmgr->compute_power_profile,
1060 sizeof(struct amd_pp_profile));
1061 else
1062 return -EINVAL;
1063
1064 return 0;
1065}
1066
1067static int pp_dpm_set_power_profile_state(void *handle,
1068 struct amd_pp_profile *request)
1069{
1070 struct pp_hwmgr *hwmgr;
1071 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1072 int ret = -1;
1073
1074 if (!request || pp_check(pp_handle))
1075 return -EINVAL;
1076
1077 hwmgr = pp_handle->hwmgr;
1078
1079 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1080 pr_info("%s was not implemented.\n", __func__);
1081 return 0;
1082 }
1083
1084 if (request->min_sclk ||
1085 request->min_mclk ||
1086 request->activity_threshold ||
1087 request->up_hyst ||
1088 request->down_hyst) {
1089 if (request->type == AMD_PP_GFX_PROFILE)
1090 memcpy(&hwmgr->gfx_power_profile, request,
1091 sizeof(struct amd_pp_profile));
1092 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1093 memcpy(&hwmgr->compute_power_profile, request,
1094 sizeof(struct amd_pp_profile));
1095 else
1096 return -EINVAL;
1097
1098 if (request->type == hwmgr->current_power_profile)
1099 ret = hwmgr->hwmgr_func->set_power_profile_state(
1100 hwmgr,
1101 request);
1102 } else {
1103 /* set power profile if it exists */
1104 switch (request->type) {
1105 case AMD_PP_GFX_PROFILE:
1106 ret = hwmgr->hwmgr_func->set_power_profile_state(
1107 hwmgr,
1108 &hwmgr->gfx_power_profile);
1109 break;
1110 case AMD_PP_COMPUTE_PROFILE:
1111 ret = hwmgr->hwmgr_func->set_power_profile_state(
1112 hwmgr,
1113 &hwmgr->compute_power_profile);
1114 break;
1115 default:
1116 return -EINVAL;
1117 }
1118 }
1119
1120 if (!ret)
1121 hwmgr->current_power_profile = request->type;
1122
1123 return 0;
1124}
1125
1126static int pp_dpm_switch_power_profile(void *handle,
1127 enum amd_pp_profile_type type)
1128{
1129 struct pp_hwmgr *hwmgr;
1130 struct amd_pp_profile request = {0};
1131 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1132
1133 if (pp_check(pp_handle))
1134 return -EINVAL;
1135
1136 hwmgr = pp_handle->hwmgr;
1137
1138 if (hwmgr->current_power_profile != type) {
1139 request.type = type;
1140 pp_dpm_set_power_profile_state(handle, &request);
1141 }
1142
1143 return 0;
1144}
1145
Rex Zhuf93f0c32017-09-06 16:08:03 +08001146const struct amd_pm_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001147 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001148 .load_firmware = pp_dpm_load_fw,
1149 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1150 .force_performance_level = pp_dpm_force_performance_level,
1151 .get_performance_level = pp_dpm_get_performance_level,
1152 .get_current_power_state = pp_dpm_get_current_power_state,
1153 .get_sclk = pp_dpm_get_sclk,
1154 .get_mclk = pp_dpm_get_mclk,
1155 .powergate_vce = pp_dpm_powergate_vce,
1156 .powergate_uvd = pp_dpm_powergate_uvd,
1157 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001158 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1159 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1160 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1161 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001162 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001163 .get_pp_num_states = pp_dpm_get_pp_num_states,
1164 .get_pp_table = pp_dpm_get_pp_table,
1165 .set_pp_table = pp_dpm_set_pp_table,
1166 .force_clock_level = pp_dpm_force_clock_level,
1167 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001168 .get_sclk_od = pp_dpm_get_sclk_od,
1169 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001170 .get_mclk_od = pp_dpm_get_mclk_od,
1171 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001172 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001173 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001174 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1175 .get_power_profile_state = pp_dpm_get_power_profile_state,
1176 .set_power_profile_state = pp_dpm_set_power_profile_state,
1177 .switch_power_profile = pp_dpm_switch_power_profile,
Rex Zhu3811f8f2017-09-26 13:39:38 +08001178 .set_clockgating_by_smu = pp_set_clockgating_by_smu,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001179};
1180
Eric Huang4dcf9e62016-06-01 17:08:07 -04001181int amd_powerplay_reset(void *handle)
1182{
1183 struct pp_instance *instance = (struct pp_instance *)handle;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001184 int ret;
1185
Rex Zhu1c863802016-12-28 19:43:23 +08001186 ret = pp_check(instance);
Rex Zhuae979882017-09-29 14:36:15 +08001187 if (!ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001188 return ret;
1189
Rex Zhudf1e6392017-09-01 13:46:20 +08001190 ret = pp_hw_fini(instance);
Rex Zhu1c863802016-12-28 19:43:23 +08001191 if (ret)
1192 return ret;
1193
1194 ret = hwmgr_hw_init(instance);
1195 if (ret)
Rex Zhue5f23732017-09-29 13:57:54 +08001196 return ret;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001197
Rex Zhudf1e6392017-09-01 13:46:20 +08001198 return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
Eric Huang4dcf9e62016-06-01 17:08:07 -04001199}
1200
Rex Zhu7fb72a12015-11-19 13:35:30 +08001201/* export this function to DAL */
1202
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001203int amd_powerplay_display_configuration_change(void *handle,
1204 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001205{
1206 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001207 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1208 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001209
Rex Zhu1c863802016-12-28 19:43:23 +08001210 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001211
Rex Zhuae979882017-09-29 14:36:15 +08001212 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001213 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001214
Rex Zhu1c863802016-12-28 19:43:23 +08001215 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +08001216 mutex_lock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001217 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhu2a507102017-02-20 17:07:36 +08001218 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001219 return 0;
1220}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001221
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001222int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001223 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001224{
1225 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001226 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1227 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001228
Rex Zhu1c863802016-12-28 19:43:23 +08001229 ret = pp_check(pp_handle);
1230
Rex Zhuae979882017-09-29 14:36:15 +08001231 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001232 return ret;
1233
1234 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001235
1236 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001237 return -EINVAL;
1238
Rex Zhu2a507102017-02-20 17:07:36 +08001239 mutex_lock(&pp_handle->pp_lock);
1240 ret = phm_get_dal_power_level(hwmgr, output);
1241 mutex_unlock(&pp_handle->pp_lock);
1242 return ret;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001243}
Rex Zhue273b042015-12-07 18:44:23 +08001244
1245int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001246 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001247{
Rex Zhue273b042015-12-07 18:44:23 +08001248 struct amd_pp_simple_clock_info simple_clocks;
1249 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001250 struct pp_hwmgr *hwmgr;
1251 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1252 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001253
Rex Zhu1c863802016-12-28 19:43:23 +08001254 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001255
Rex Zhuae979882017-09-29 14:36:15 +08001256 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001257 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001258
Rex Zhu1c863802016-12-28 19:43:23 +08001259 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001260
Rex Zhu2a507102017-02-20 17:07:36 +08001261 mutex_lock(&pp_handle->pp_lock);
1262
Rex Zhue273b042015-12-07 18:44:23 +08001263 phm_get_dal_power_level(hwmgr, &simple_clocks);
1264
Rex Zhu2a507102017-02-20 17:07:36 +08001265 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1266 PHM_PlatformCaps_PowerContainment))
1267 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1268 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1269 else
1270 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1271 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1272
Rex Zhuae979882017-09-29 14:36:15 +08001273 if (ret) {
Rex Zhu2a507102017-02-20 17:07:36 +08001274 pr_info("Error in phm_get_clock_info \n");
1275 mutex_unlock(&pp_handle->pp_lock);
1276 return -EINVAL;
Rex Zhue273b042015-12-07 18:44:23 +08001277 }
1278
1279 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1280 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1281 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1282 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1283 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1284 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1285
1286 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1287 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1288
1289 clocks->max_clocks_state = simple_clocks.level;
1290
1291 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1292 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1293 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1294 }
Rex Zhu2a507102017-02-20 17:07:36 +08001295 mutex_unlock(&pp_handle->pp_lock);
Rex Zhue273b042015-12-07 18:44:23 +08001296 return 0;
Rex Zhue273b042015-12-07 18:44:23 +08001297}
1298
1299int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1300{
Rex Zhu1c863802016-12-28 19:43:23 +08001301 struct pp_hwmgr *hwmgr;
1302 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1303 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001304
Rex Zhu1c863802016-12-28 19:43:23 +08001305 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001306
Rex Zhuae979882017-09-29 14:36:15 +08001307 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001308 return ret;
1309
1310 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001311
1312 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001313 return -EINVAL;
1314
Rex Zhu2a507102017-02-20 17:07:36 +08001315 mutex_lock(&pp_handle->pp_lock);
1316 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1317 mutex_unlock(&pp_handle->pp_lock);
1318 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001319}
1320
Eric Huangd0187722017-03-06 13:13:48 -05001321int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1322 enum amd_pp_clock_type type,
1323 struct pp_clock_levels_with_latency *clocks)
1324{
1325 struct pp_hwmgr *hwmgr;
1326 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1327 int ret = 0;
1328
1329 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001330 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001331 return ret;
1332
1333 if (!clocks)
1334 return -EINVAL;
1335
1336 mutex_lock(&pp_handle->pp_lock);
1337 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1338 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1339 mutex_unlock(&pp_handle->pp_lock);
1340 return ret;
1341}
1342
1343int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1344 enum amd_pp_clock_type type,
1345 struct pp_clock_levels_with_voltage *clocks)
1346{
1347 struct pp_hwmgr *hwmgr;
1348 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1349 int ret = 0;
1350
1351 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001352 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001353 return ret;
1354
1355 if (!clocks)
1356 return -EINVAL;
1357
1358 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1359
1360 mutex_lock(&pp_handle->pp_lock);
1361
1362 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1363
1364 mutex_unlock(&pp_handle->pp_lock);
1365 return ret;
1366}
1367
1368int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1369 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1370{
1371 struct pp_hwmgr *hwmgr;
1372 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1373 int ret = 0;
1374
1375 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001376 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001377 return ret;
1378
1379 if (!wm_with_clock_ranges)
1380 return -EINVAL;
1381
1382 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1383
1384 mutex_lock(&pp_handle->pp_lock);
1385 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1386 wm_with_clock_ranges);
1387 mutex_unlock(&pp_handle->pp_lock);
1388
1389 return ret;
1390}
1391
1392int amd_powerplay_display_clock_voltage_request(void *handle,
1393 struct pp_display_clock_request *clock)
1394{
1395 struct pp_hwmgr *hwmgr;
1396 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1397 int ret = 0;
1398
1399 ret = pp_check(pp_handle);
Rex Zhuae979882017-09-29 14:36:15 +08001400 if (ret)
Eric Huangd0187722017-03-06 13:13:48 -05001401 return ret;
1402
1403 if (!clock)
1404 return -EINVAL;
1405
1406 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1407
1408 mutex_lock(&pp_handle->pp_lock);
1409 ret = phm_display_clock_voltage_request(hwmgr, clock);
1410 mutex_unlock(&pp_handle->pp_lock);
1411
1412 return ret;
1413}
1414
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001415int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1416 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001417{
Rex Zhue273b042015-12-07 18:44:23 +08001418 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001419 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1420 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001421
Rex Zhu1c863802016-12-28 19:43:23 +08001422 ret = pp_check(pp_handle);
1423
Rex Zhuae979882017-09-29 14:36:15 +08001424 if (ret)
Rex Zhu1c863802016-12-28 19:43:23 +08001425 return ret;
1426
1427 hwmgr = pp_handle->hwmgr;
1428
Rex Zhufa9e6992015-12-29 13:56:03 +08001429 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001430 return -EINVAL;
1431
Rex Zhu2a507102017-02-20 17:07:36 +08001432 mutex_lock(&pp_handle->pp_lock);
1433
Rex Zhue273b042015-12-07 18:44:23 +08001434 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001435 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001436
Rex Zhu2a507102017-02-20 17:07:36 +08001437 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001438 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001439}
1440