blob: 94bed3c08161b2b0d4081559d3183ca5c07959ca [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 Zhuaf223df2016-07-28 16:51:47 +080033
Rex Zhu1c863802016-12-28 19:43:23 +080034static inline int pp_check(struct pp_instance *handle)
35{
36 if (handle == NULL || handle->pp_valid != PP_VALID)
37 return -EINVAL;
Rex Zhua969e162015-12-29 13:56:03 +080038
Rex Zhu1c863802016-12-28 19:43:23 +080039 if (handle->smu_mgr == NULL || handle->smu_mgr->smumgr_funcs == NULL)
40 return -EINVAL;
41
42 if (handle->pm_en == 0)
43 return PP_DPM_DISABLED;
44
Rex Zhudf1e6392017-09-01 13:46:20 +080045 if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL)
Rex Zhu1c863802016-12-28 19:43:23 +080046 return PP_DPM_DISABLED;
47
48 return 0;
49}
Rex Zhu7383bcb2016-03-30 11:35:50 +080050
Alex Deucher1f7371b2015-12-02 17:46:21 -050051static int pp_early_init(void *handle)
52{
Rex Zhu1c863802016-12-28 19:43:23 +080053 int ret;
54 struct pp_instance *pp_handle = (struct pp_instance *)handle;
55
56 ret = smum_early_init(pp_handle);
57 if (ret)
58 return ret;
59
60 if ((pp_handle->pm_en == 0)
61 || cgs_is_virtualization_enabled(pp_handle->device))
62 return PP_DPM_DISABLED;
63
64 ret = hwmgr_early_init(pp_handle);
65 if (ret) {
66 pp_handle->pm_en = 0;
67 return PP_DPM_DISABLED;
68 }
69
Alex Deucher1f7371b2015-12-02 17:46:21 -050070 return 0;
71}
72
73static int pp_sw_init(void *handle)
74{
Rex Zhu1c863802016-12-28 19:43:23 +080075 struct pp_smumgr *smumgr;
Jammy Zhou3bace352015-07-21 21:18:15 +080076 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +080077 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +080078
Rex Zhu1c863802016-12-28 19:43:23 +080079 ret = pp_check(pp_handle);
Jammy Zhou3bace352015-07-21 21:18:15 +080080
Rex Zhu1c863802016-12-28 19:43:23 +080081 if (ret == 0 || ret == PP_DPM_DISABLED) {
82 smumgr = pp_handle->smu_mgr;
Jammy Zhou3bace352015-07-21 21:18:15 +080083
Rex Zhu1c863802016-12-28 19:43:23 +080084 if (smumgr->smumgr_funcs->smu_init == NULL)
85 return -EINVAL;
Rex Zhu7383bcb2016-03-30 11:35:50 +080086
Rex Zhu1c863802016-12-28 19:43:23 +080087 ret = smumgr->smumgr_funcs->smu_init(smumgr);
Jammy Zhou3bace352015-07-21 21:18:15 +080088
Rex Zhu1c863802016-12-28 19:43:23 +080089 pr_info("amdgpu: powerplay sw initialized\n");
Huang Rui167112b2016-12-14 16:26:54 +080090 }
Jammy Zhou3bace352015-07-21 21:18:15 +080091 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -050092}
93
94static int pp_sw_fini(void *handle)
95{
Rex Zhu1c863802016-12-28 19:43:23 +080096 struct pp_smumgr *smumgr;
Jammy Zhou3bace352015-07-21 21:18:15 +080097 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +080098 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +080099
Rex Zhu1c863802016-12-28 19:43:23 +0800100 ret = pp_check(pp_handle);
101 if (ret == 0 || ret == PP_DPM_DISABLED) {
102 smumgr = pp_handle->smu_mgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800103
Rex Zhu1c863802016-12-28 19:43:23 +0800104 if (smumgr->smumgr_funcs->smu_fini == NULL)
105 return -EINVAL;
Jammy Zhou3bace352015-07-21 21:18:15 +0800106
Rex Zhu1c863802016-12-28 19:43:23 +0800107 ret = smumgr->smumgr_funcs->smu_fini(smumgr);
108 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800109 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500110}
111
112static int pp_hw_init(void *handle)
113{
Jammy Zhouac885b32015-07-21 17:43:02 +0800114 struct pp_smumgr *smumgr;
115 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800116 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhouac885b32015-07-21 17:43:02 +0800117
Rex Zhu1c863802016-12-28 19:43:23 +0800118 ret = pp_check(pp_handle);
Jammy Zhouac885b32015-07-21 17:43:02 +0800119
Rex Zhu1c863802016-12-28 19:43:23 +0800120 if (ret == 0 || ret == PP_DPM_DISABLED) {
121 smumgr = pp_handle->smu_mgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800122
Rex Zhu1c863802016-12-28 19:43:23 +0800123 if (smumgr->smumgr_funcs->start_smu == NULL)
124 return -EINVAL;
Jammy Zhouac885b32015-07-21 17:43:02 +0800125
Rex Zhu1c863802016-12-28 19:43:23 +0800126 if(smumgr->smumgr_funcs->start_smu(smumgr)) {
127 pr_err("smc start failed\n");
128 smumgr->smumgr_funcs->smu_fini(smumgr);
129 return -EINVAL;;
130 }
131 if (ret == PP_DPM_DISABLED)
132 return PP_DPM_DISABLED;
Jammy Zhouac885b32015-07-21 17:43:02 +0800133 }
134
Rex Zhu1c863802016-12-28 19:43:23 +0800135 ret = hwmgr_hw_init(pp_handle);
136 if (ret)
137 goto err;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500138 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800139err:
140 pp_handle->pm_en = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800141 kfree(pp_handle->hwmgr);
142 pp_handle->hwmgr = NULL;
Rex Zhu1c863802016-12-28 19:43:23 +0800143 return PP_DPM_DISABLED;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500144}
145
146static int pp_hw_fini(void *handle)
147{
Rex Zhu1c863802016-12-28 19:43:23 +0800148 struct pp_instance *pp_handle = (struct pp_instance *)handle;
149 int ret = 0;
Jammy Zhouac885b32015-07-21 17:43:02 +0800150
Rex Zhu1c863802016-12-28 19:43:23 +0800151 ret = pp_check(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800152 if (ret == 0)
Rex Zhu1c863802016-12-28 19:43:23 +0800153 hwmgr_hw_fini(pp_handle);
Rex Zhudf1e6392017-09-01 13:46:20 +0800154
Alex Deucher1f7371b2015-12-02 17:46:21 -0500155 return 0;
156}
157
158static bool pp_is_idle(void *handle)
159{
Edward O'Callaghaned5121a2016-07-12 10:17:52 +1000160 return false;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500161}
162
163static int pp_wait_for_idle(void *handle)
164{
165 return 0;
166}
167
168static int pp_sw_reset(void *handle)
169{
170 return 0;
171}
172
Alex Deucher1f7371b2015-12-02 17:46:21 -0500173
Rex Zhu465f96e2016-09-18 16:52:03 +0800174int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500175{
Eric Huang03e39052016-02-09 16:26:00 -0500176 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800177 struct pp_instance *pp_handle = (struct pp_instance *)handle;
178 int ret = 0;
Eric Huang03e39052016-02-09 16:26:00 -0500179
Rex Zhu1c863802016-12-28 19:43:23 +0800180 ret = pp_check(pp_handle);
Eric Huang03e39052016-02-09 16:26:00 -0500181
Rex Zhu1c863802016-12-28 19:43:23 +0800182 if (ret != 0)
183 return ret;
Eric Huang03e39052016-02-09 16:26:00 -0500184
Rex Zhu1c863802016-12-28 19:43:23 +0800185 hwmgr = pp_handle->hwmgr;
Eric Huang03e39052016-02-09 16:26:00 -0500186
Rex Zhu7383bcb2016-03-30 11:35:50 +0800187 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800188 pr_info("%s was not implemented.\n", __func__);
Flora Cui538333f2016-02-15 15:45:59 +0800189 return 0;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800190 }
Flora Cui538333f2016-02-15 15:45:59 +0800191
Rex Zhu465f96e2016-09-18 16:52:03 +0800192 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500193}
194
195static int pp_set_powergating_state(void *handle,
196 enum amd_powergating_state state)
197{
Eric Huang65f85e72016-02-11 15:54:45 -0500198 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800199 struct pp_instance *pp_handle = (struct pp_instance *)handle;
200 int ret = 0;
Eric Huang65f85e72016-02-11 15:54:45 -0500201
Rex Zhu1c863802016-12-28 19:43:23 +0800202 ret = pp_check(pp_handle);
Eric Huang65f85e72016-02-11 15:54:45 -0500203
Rex Zhu1c863802016-12-28 19:43:23 +0800204 if (ret != 0)
205 return ret;
Eric Huang65f85e72016-02-11 15:54:45 -0500206
Rex Zhu1c863802016-12-28 19:43:23 +0800207 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800208
209 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800210 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800211 return 0;
212 }
Eric Huang65f85e72016-02-11 15:54:45 -0500213
214 /* Enable/disable GFX per cu powergating through SMU */
215 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
Andrew F. Davis93a4aec2017-03-15 11:20:24 -0500216 state == AMD_PG_STATE_GATE);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500217}
218
219static int pp_suspend(void *handle)
220{
Rex Zhu1c863802016-12-28 19:43:23 +0800221 struct pp_instance *pp_handle = (struct pp_instance *)handle;
222 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800223
Rex Zhu1c863802016-12-28 19:43:23 +0800224 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800225
Huang Rui4573f0f2017-04-10 14:40:51 +0800226 if (ret == PP_DPM_DISABLED)
227 return 0;
228 else if (ret != 0)
Rex Zhu1c863802016-12-28 19:43:23 +0800229 return ret;
230
Rex Zhudf1e6392017-09-01 13:46:20 +0800231 return hwmgr_hw_suspend(pp_handle);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500232}
233
234static int pp_resume(void *handle)
235{
Rex Zhue0b71a72015-12-29 10:25:19 +0800236 struct pp_smumgr *smumgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800237 int ret, ret1;
238 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800239
Rex Zhu1c863802016-12-28 19:43:23 +0800240 ret1 = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800241
Rex Zhu1c863802016-12-28 19:43:23 +0800242 if (ret1 != 0 && ret1 != PP_DPM_DISABLED)
243 return ret1;
244
Rex Zhue0b71a72015-12-29 10:25:19 +0800245 smumgr = pp_handle->smu_mgr;
246
Rex Zhu1c863802016-12-28 19:43:23 +0800247 if (smumgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800248 return -EINVAL;
249
250 ret = smumgr->smumgr_funcs->start_smu(smumgr);
251 if (ret) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800252 pr_err("smc start failed\n");
Rex Zhue0b71a72015-12-29 10:25:19 +0800253 smumgr->smumgr_funcs->smu_fini(smumgr);
254 return ret;
255 }
256
Rex Zhu1c863802016-12-28 19:43:23 +0800257 if (ret1 == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800258 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800259
Rex Zhudf1e6392017-09-01 13:46:20 +0800260 return hwmgr_hw_resume(pp_handle);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500261}
262
263const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400264 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500265 .early_init = pp_early_init,
266 .late_init = NULL,
267 .sw_init = pp_sw_init,
268 .sw_fini = pp_sw_fini,
269 .hw_init = pp_hw_init,
270 .hw_fini = pp_hw_fini,
271 .suspend = pp_suspend,
272 .resume = pp_resume,
273 .is_idle = pp_is_idle,
274 .wait_for_idle = pp_wait_for_idle,
275 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800276 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500277 .set_powergating_state = pp_set_powergating_state,
278};
279
280static int pp_dpm_load_fw(void *handle)
281{
282 return 0;
283}
284
285static int pp_dpm_fw_loading_complete(void *handle)
286{
287 return 0;
288}
289
290static int pp_dpm_force_performance_level(void *handle,
291 enum amd_dpm_forced_level level)
292{
Rex Zhu577bbe02015-08-28 12:56:43 +0800293 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800294 struct pp_instance *pp_handle = (struct pp_instance *)handle;
295 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800296
Rex Zhu1c863802016-12-28 19:43:23 +0800297 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800298
Rex Zhu1c863802016-12-28 19:43:23 +0800299 if (ret != 0)
300 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800301
302 hwmgr = pp_handle->hwmgr;
303
Rex Zhu7383bcb2016-03-30 11:35:50 +0800304 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800305 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800306 return 0;
307 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800308
Rex Zhu2a507102017-02-20 17:07:36 +0800309 mutex_lock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800310 hwmgr_handle_task(pp_handle, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL);
Rex Zhu577bbe02015-08-28 12:56:43 +0800311 hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
Rex Zhu2a507102017-02-20 17:07:36 +0800312 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500313 return 0;
314}
Rex Zhu577bbe02015-08-28 12:56:43 +0800315
Alex Deucher1f7371b2015-12-02 17:46:21 -0500316static enum amd_dpm_forced_level pp_dpm_get_performance_level(
317 void *handle)
318{
Rex Zhu577bbe02015-08-28 12:56:43 +0800319 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800320 struct pp_instance *pp_handle = (struct pp_instance *)handle;
321 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800322 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800323
Rex Zhu1c863802016-12-28 19:43:23 +0800324 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800325
Rex Zhu1c863802016-12-28 19:43:23 +0800326 if (ret != 0)
327 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800328
Rex Zhu1c863802016-12-28 19:43:23 +0800329 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800330 mutex_lock(&pp_handle->pp_lock);
331 level = hwmgr->dpm_level;
332 mutex_unlock(&pp_handle->pp_lock);
333 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500334}
Rex Zhu577bbe02015-08-28 12:56:43 +0800335
Alex Deucher1f7371b2015-12-02 17:46:21 -0500336static int pp_dpm_get_sclk(void *handle, bool low)
337{
Rex Zhu577bbe02015-08-28 12:56:43 +0800338 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800339 struct pp_instance *pp_handle = (struct pp_instance *)handle;
340 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800341
Rex Zhu1c863802016-12-28 19:43:23 +0800342 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800343
Rex Zhu1c863802016-12-28 19:43:23 +0800344 if (ret != 0)
345 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800346
Rex Zhu1c863802016-12-28 19:43:23 +0800347 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800348
349 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800350 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800351 return 0;
352 }
Rex Zhu2a507102017-02-20 17:07:36 +0800353 mutex_lock(&pp_handle->pp_lock);
354 ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
355 mutex_unlock(&pp_handle->pp_lock);
356 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500357}
Rex Zhu577bbe02015-08-28 12:56:43 +0800358
Alex Deucher1f7371b2015-12-02 17:46:21 -0500359static int pp_dpm_get_mclk(void *handle, bool low)
360{
Rex Zhu577bbe02015-08-28 12:56:43 +0800361 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800362 struct pp_instance *pp_handle = (struct pp_instance *)handle;
363 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800364
Rex Zhu1c863802016-12-28 19:43:23 +0800365 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800366
Rex Zhu1c863802016-12-28 19:43:23 +0800367 if (ret != 0)
368 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800369
Rex Zhu1c863802016-12-28 19:43:23 +0800370 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800371
372 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800373 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800374 return 0;
375 }
Rex Zhu2a507102017-02-20 17:07:36 +0800376 mutex_lock(&pp_handle->pp_lock);
377 ret = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
378 mutex_unlock(&pp_handle->pp_lock);
379 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500380}
Rex Zhu577bbe02015-08-28 12:56:43 +0800381
Alex Deucher1f7371b2015-12-02 17:46:21 -0500382static int pp_dpm_powergate_vce(void *handle, bool gate)
383{
Rex Zhu577bbe02015-08-28 12:56:43 +0800384 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800385 struct pp_instance *pp_handle = (struct pp_instance *)handle;
386 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800387
Rex Zhu1c863802016-12-28 19:43:23 +0800388 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800389
Rex Zhu1c863802016-12-28 19:43:23 +0800390 if (ret != 0)
391 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800392
Rex Zhu1c863802016-12-28 19:43:23 +0800393 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800394
395 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800396 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800397 return 0;
398 }
Rex Zhu2a507102017-02-20 17:07:36 +0800399 mutex_lock(&pp_handle->pp_lock);
400 ret = hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
401 mutex_unlock(&pp_handle->pp_lock);
402 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500403}
Rex Zhu577bbe02015-08-28 12:56:43 +0800404
Alex Deucher1f7371b2015-12-02 17:46:21 -0500405static int pp_dpm_powergate_uvd(void *handle, bool gate)
406{
Rex Zhu577bbe02015-08-28 12:56:43 +0800407 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800408 struct pp_instance *pp_handle = (struct pp_instance *)handle;
409 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800410
Rex Zhu1c863802016-12-28 19:43:23 +0800411 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800412
Rex Zhu1c863802016-12-28 19:43:23 +0800413 if (ret != 0)
414 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800415
Rex Zhu1c863802016-12-28 19:43:23 +0800416 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800417
418 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800419 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800420 return 0;
421 }
Rex Zhu2a507102017-02-20 17:07:36 +0800422 mutex_lock(&pp_handle->pp_lock);
423 ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
424 mutex_unlock(&pp_handle->pp_lock);
425 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800426}
427
Rex Zhudf1e6392017-09-01 13:46:20 +0800428static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id,
Baoyou Xief8a4c112016-09-30 17:58:42 +0800429 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500430{
Rex Zhu577bbe02015-08-28 12:56:43 +0800431 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800432 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800433
Rex Zhu1c863802016-12-28 19:43:23 +0800434 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800435
Rex Zhu1c863802016-12-28 19:43:23 +0800436 if (ret != 0)
437 return ret;
Rex Zhudf1e6392017-09-01 13:46:20 +0800438
Rex Zhu2a507102017-02-20 17:07:36 +0800439 mutex_lock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800440 ret = hwmgr_handle_task(pp_handle, task_id, input, output);
Rex Zhu2a507102017-02-20 17:07:36 +0800441 mutex_unlock(&pp_handle->pp_lock);
Rex Zhudf1e6392017-09-01 13:46:20 +0800442
Rex Zhu577bbe02015-08-28 12:56:43 +0800443 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500444}
Rex Zhu577bbe02015-08-28 12:56:43 +0800445
Baoyou Xief8a4c112016-09-30 17:58:42 +0800446static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500447{
Rex Zhu577bbe02015-08-28 12:56:43 +0800448 struct pp_hwmgr *hwmgr;
449 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800450 struct pp_instance *pp_handle = (struct pp_instance *)handle;
451 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800452 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800453
Rex Zhu1c863802016-12-28 19:43:23 +0800454 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800455
Rex Zhu1c863802016-12-28 19:43:23 +0800456 if (ret != 0)
457 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800458
Rex Zhu1c863802016-12-28 19:43:23 +0800459 hwmgr = pp_handle->hwmgr;
460
461 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800462 return -EINVAL;
463
Rex Zhu2a507102017-02-20 17:07:36 +0800464 mutex_lock(&pp_handle->pp_lock);
465
Rex Zhu577bbe02015-08-28 12:56:43 +0800466 state = hwmgr->current_ps;
467
468 switch (state->classification.ui_label) {
469 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800470 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300471 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800472 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800473 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300474 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800475 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800476 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300477 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800478 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500479 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800480 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500481 else
Rex Zhu2a507102017-02-20 17:07:36 +0800482 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300483 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800484 }
Rex Zhu2a507102017-02-20 17:07:36 +0800485 mutex_unlock(&pp_handle->pp_lock);
486
487 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500488}
Rex Zhu577bbe02015-08-28 12:56:43 +0800489
Rex Zhucac9a192015-10-16 11:48:21 +0800490static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
491{
492 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800493 struct pp_instance *pp_handle = (struct pp_instance *)handle;
494 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800495
Rex Zhu1c863802016-12-28 19:43:23 +0800496 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800497
Rex Zhu1c863802016-12-28 19:43:23 +0800498 if (ret != 0)
499 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800500
Rex Zhu1c863802016-12-28 19:43:23 +0800501 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800502
503 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800504 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800505 return 0;
506 }
Rex Zhu2a507102017-02-20 17:07:36 +0800507 mutex_lock(&pp_handle->pp_lock);
508 ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
509 mutex_unlock(&pp_handle->pp_lock);
510 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800511}
512
513static int pp_dpm_get_fan_control_mode(void *handle)
514{
515 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800516 struct pp_instance *pp_handle = (struct pp_instance *)handle;
517 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800518
Rex Zhu1c863802016-12-28 19:43:23 +0800519 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800520
Rex Zhu1c863802016-12-28 19:43:23 +0800521 if (ret != 0)
522 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800523
Rex Zhu1c863802016-12-28 19:43:23 +0800524 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800525
526 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800527 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800528 return 0;
529 }
Rex Zhu2a507102017-02-20 17:07:36 +0800530 mutex_lock(&pp_handle->pp_lock);
531 ret = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
532 mutex_unlock(&pp_handle->pp_lock);
533 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800534}
535
536static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
537{
538 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800539 struct pp_instance *pp_handle = (struct pp_instance *)handle;
540 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800541
Rex Zhu1c863802016-12-28 19:43:23 +0800542 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800543
Rex Zhu1c863802016-12-28 19:43:23 +0800544 if (ret != 0)
545 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800546
Rex Zhu1c863802016-12-28 19:43:23 +0800547 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800548
549 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800550 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800551 return 0;
552 }
Rex Zhu2a507102017-02-20 17:07:36 +0800553 mutex_lock(&pp_handle->pp_lock);
554 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
555 mutex_unlock(&pp_handle->pp_lock);
556 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800557}
558
559static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
560{
561 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800562 struct pp_instance *pp_handle = (struct pp_instance *)handle;
563 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800564
Rex Zhu1c863802016-12-28 19:43:23 +0800565 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800566
Rex Zhu1c863802016-12-28 19:43:23 +0800567 if (ret != 0)
568 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800569
Rex Zhu1c863802016-12-28 19:43:23 +0800570 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800571
572 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800573 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800574 return 0;
575 }
Rex Zhucac9a192015-10-16 11:48:21 +0800576
Rex Zhu2a507102017-02-20 17:07:36 +0800577 mutex_lock(&pp_handle->pp_lock);
578 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
579 mutex_unlock(&pp_handle->pp_lock);
580 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800581}
582
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300583static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
584{
585 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800586 struct pp_instance *pp_handle = (struct pp_instance *)handle;
587 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300588
Rex Zhu1c863802016-12-28 19:43:23 +0800589 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300590
Rex Zhu1c863802016-12-28 19:43:23 +0800591 if (ret != 0)
592 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300593
Rex Zhu1c863802016-12-28 19:43:23 +0800594 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300595
596 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
597 return -EINVAL;
598
Rex Zhu2a507102017-02-20 17:07:36 +0800599 mutex_lock(&pp_handle->pp_lock);
600 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
601 mutex_unlock(&pp_handle->pp_lock);
602 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300603}
604
Rex Zhucac9a192015-10-16 11:48:21 +0800605static int pp_dpm_get_temperature(void *handle)
606{
607 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800608 struct pp_instance *pp_handle = (struct pp_instance *)handle;
609 int ret = 0;
Rex 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 Zhu1c863802016-12-28 19:43:23 +0800613 if (ret != 0)
614 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_temperature == 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);
623 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
624 mutex_unlock(&pp_handle->pp_lock);
625 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800626}
Rex Zhu577bbe02015-08-28 12:56:43 +0800627
Eric Huangf3898ea2015-12-11 16:24:34 -0500628static int pp_dpm_get_pp_num_states(void *handle,
629 struct pp_states_info *data)
630{
631 struct pp_hwmgr *hwmgr;
632 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800633 struct pp_instance *pp_handle = (struct pp_instance *)handle;
634 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500635
Rex Zhu1c863802016-12-28 19:43:23 +0800636 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500637
Rex Zhu1c863802016-12-28 19:43:23 +0800638 if (ret != 0)
639 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500640
Rex Zhu1c863802016-12-28 19:43:23 +0800641 hwmgr = pp_handle->hwmgr;
642
643 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500644 return -EINVAL;
645
Rex Zhu2a507102017-02-20 17:07:36 +0800646 mutex_lock(&pp_handle->pp_lock);
647
Eric Huangf3898ea2015-12-11 16:24:34 -0500648 data->nums = hwmgr->num_ps;
649
650 for (i = 0; i < hwmgr->num_ps; i++) {
651 struct pp_power_state *state = (struct pp_power_state *)
652 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
653 switch (state->classification.ui_label) {
654 case PP_StateUILabel_Battery:
655 data->states[i] = POWER_STATE_TYPE_BATTERY;
656 break;
657 case PP_StateUILabel_Balanced:
658 data->states[i] = POWER_STATE_TYPE_BALANCED;
659 break;
660 case PP_StateUILabel_Performance:
661 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
662 break;
663 default:
664 if (state->classification.flags & PP_StateClassificationFlag_Boot)
665 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
666 else
667 data->states[i] = POWER_STATE_TYPE_DEFAULT;
668 }
669 }
Rex Zhu2a507102017-02-20 17:07:36 +0800670 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500671 return 0;
672}
673
674static int pp_dpm_get_pp_table(void *handle, char **table)
675{
676 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800677 struct pp_instance *pp_handle = (struct pp_instance *)handle;
678 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800679 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500680
Rex Zhu1c863802016-12-28 19:43:23 +0800681 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500682
Rex Zhu1c863802016-12-28 19:43:23 +0800683 if (ret != 0)
684 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500685
Rex Zhu1c863802016-12-28 19:43:23 +0800686 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800687
Eric Huang4dcf9e62016-06-01 17:08:07 -0400688 if (!hwmgr->soft_pp_table)
689 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500690
Rex Zhu2a507102017-02-20 17:07:36 +0800691 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400692 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800693 size = hwmgr->soft_pp_table_size;
694 mutex_unlock(&pp_handle->pp_lock);
695 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500696}
697
698static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
699{
700 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800701 struct pp_instance *pp_handle = (struct pp_instance *)handle;
702 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500703
Rex Zhu1c863802016-12-28 19:43:23 +0800704 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500705
Rex Zhu1c863802016-12-28 19:43:23 +0800706 if (ret != 0)
707 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500708
Rex Zhu1c863802016-12-28 19:43:23 +0800709 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800710 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400711 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000712 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
713 hwmgr->soft_pp_table_size,
714 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800715 if (!hwmgr->hardcode_pp_table) {
716 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400717 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800718 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800719 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500720
Eric Huang4dcf9e62016-06-01 17:08:07 -0400721 memcpy(hwmgr->hardcode_pp_table, buf, size);
722
723 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800724 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400725
Eric Huangdd4bdf32017-03-01 15:49:31 -0500726 ret = amd_powerplay_reset(handle);
727 if (ret)
728 return ret;
729
730 if (hwmgr->hwmgr_func->avfs_control) {
731 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
732 if (ret)
733 return ret;
734 }
735
736 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500737}
738
739static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400740 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500741{
742 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800743 struct pp_instance *pp_handle = (struct pp_instance *)handle;
744 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500745
Rex Zhu1c863802016-12-28 19:43:23 +0800746 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500747
Rex Zhu1c863802016-12-28 19:43:23 +0800748 if (ret != 0)
749 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500750
Rex Zhu1c863802016-12-28 19:43:23 +0800751 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800752
753 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800754 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800755 return 0;
756 }
Rex Zhu2a507102017-02-20 17:07:36 +0800757 mutex_lock(&pp_handle->pp_lock);
758 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
759 mutex_unlock(&pp_handle->pp_lock);
760 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500761}
762
763static int pp_dpm_print_clock_levels(void *handle,
764 enum pp_clock_type type, char *buf)
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;
Eric Huangf3898ea2015-12-11 16:24:34 -0500769
Rex Zhu1c863802016-12-28 19:43:23 +0800770 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500771
Rex Zhu1c863802016-12-28 19:43:23 +0800772 if (ret != 0)
773 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500774
Rex Zhu1c863802016-12-28 19:43:23 +0800775 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500776
Rex Zhu7383bcb2016-03-30 11:35:50 +0800777 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800778 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800779 return 0;
780 }
Rex Zhu2a507102017-02-20 17:07:36 +0800781 mutex_lock(&pp_handle->pp_lock);
782 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
783 mutex_unlock(&pp_handle->pp_lock);
784 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500785}
786
Eric Huang428bafa2016-05-12 14:51:21 -0400787static int pp_dpm_get_sclk_od(void *handle)
788{
789 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800790 struct pp_instance *pp_handle = (struct pp_instance *)handle;
791 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400792
Rex Zhu1c863802016-12-28 19:43:23 +0800793 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400794
Rex Zhu1c863802016-12-28 19:43:23 +0800795 if (ret != 0)
796 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400797
Rex Zhu1c863802016-12-28 19:43:23 +0800798 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400799
800 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800801 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400802 return 0;
803 }
Rex Zhu2a507102017-02-20 17:07:36 +0800804 mutex_lock(&pp_handle->pp_lock);
805 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
806 mutex_unlock(&pp_handle->pp_lock);
807 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400808}
809
810static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
811{
812 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800813 struct pp_instance *pp_handle = (struct pp_instance *)handle;
814 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400815
Rex Zhu1c863802016-12-28 19:43:23 +0800816 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400817
Rex Zhu1c863802016-12-28 19:43:23 +0800818 if (ret != 0)
819 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400820
Rex Zhu1c863802016-12-28 19:43:23 +0800821 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400822
823 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800824 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400825 return 0;
826 }
827
Rex Zhu2a507102017-02-20 17:07:36 +0800828 mutex_lock(&pp_handle->pp_lock);
829 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400830 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800831 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400832}
833
Eric Huangf2bdc052016-05-24 15:11:17 -0400834static int pp_dpm_get_mclk_od(void *handle)
835{
836 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800837 struct pp_instance *pp_handle = (struct pp_instance *)handle;
838 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400839
Rex Zhu1c863802016-12-28 19:43:23 +0800840 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400841
Rex Zhu1c863802016-12-28 19:43:23 +0800842 if (ret != 0)
843 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400844
Rex Zhu1c863802016-12-28 19:43:23 +0800845 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400846
847 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800848 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400849 return 0;
850 }
Rex Zhu2a507102017-02-20 17:07:36 +0800851 mutex_lock(&pp_handle->pp_lock);
852 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
853 mutex_unlock(&pp_handle->pp_lock);
854 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400855}
856
857static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
858{
859 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800860 struct pp_instance *pp_handle = (struct pp_instance *)handle;
861 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400862
Rex Zhu1c863802016-12-28 19:43:23 +0800863 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400864
Rex Zhu1c863802016-12-28 19:43:23 +0800865 if (ret != 0)
866 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400867
Rex Zhu1c863802016-12-28 19:43:23 +0800868 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400869
870 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800871 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400872 return 0;
873 }
Rex Zhu2a507102017-02-20 17:07:36 +0800874 mutex_lock(&pp_handle->pp_lock);
875 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
876 mutex_unlock(&pp_handle->pp_lock);
877 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400878}
879
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500880static int pp_dpm_read_sensor(void *handle, int idx,
881 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400882{
883 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800884 struct pp_instance *pp_handle = (struct pp_instance *)handle;
885 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400886
Rex Zhu1c863802016-12-28 19:43:23 +0800887 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400888
Rex Zhu1c863802016-12-28 19:43:23 +0800889 if (ret != 0)
890 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400891
Rex Zhu1c863802016-12-28 19:43:23 +0800892 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400893
894 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800895 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400896 return 0;
897 }
898
Rex Zhu2a507102017-02-20 17:07:36 +0800899 mutex_lock(&pp_handle->pp_lock);
900 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
901 mutex_unlock(&pp_handle->pp_lock);
902
903 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400904}
905
Alex Deucher597be302016-10-07 13:52:43 -0400906static struct amd_vce_state*
907pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
908{
909 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800910 struct pp_instance *pp_handle = (struct pp_instance *)handle;
911 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -0400912
Rex Zhu1c863802016-12-28 19:43:23 +0800913 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -0400914
Rex Zhu1c863802016-12-28 19:43:23 +0800915 if (ret != 0)
916 return NULL;
917
918 hwmgr = pp_handle->hwmgr;
919
920 if (hwmgr && idx < hwmgr->num_vce_state_tables)
921 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -0400922 return NULL;
923}
924
Eric Huang34bb2732016-09-12 16:17:44 -0400925static int pp_dpm_reset_power_profile_state(void *handle,
926 struct amd_pp_profile *request)
927{
928 struct pp_hwmgr *hwmgr;
929 struct pp_instance *pp_handle = (struct pp_instance *)handle;
930
931 if (!request || pp_check(pp_handle))
932 return -EINVAL;
933
934 hwmgr = pp_handle->hwmgr;
935
936 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
937 pr_info("%s was not implemented.\n", __func__);
938 return 0;
939 }
940
941 if (request->type == AMD_PP_GFX_PROFILE) {
942 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
943 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
944 &hwmgr->gfx_power_profile);
945 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
946 hwmgr->compute_power_profile =
947 hwmgr->default_compute_power_profile;
948 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
949 &hwmgr->compute_power_profile);
950 } else
951 return -EINVAL;
952}
953
954static int pp_dpm_get_power_profile_state(void *handle,
955 struct amd_pp_profile *query)
956{
957 struct pp_hwmgr *hwmgr;
958 struct pp_instance *pp_handle = (struct pp_instance *)handle;
959
960 if (!query || pp_check(pp_handle))
961 return -EINVAL;
962
963 hwmgr = pp_handle->hwmgr;
964
965 if (query->type == AMD_PP_GFX_PROFILE)
966 memcpy(query, &hwmgr->gfx_power_profile,
967 sizeof(struct amd_pp_profile));
968 else if (query->type == AMD_PP_COMPUTE_PROFILE)
969 memcpy(query, &hwmgr->compute_power_profile,
970 sizeof(struct amd_pp_profile));
971 else
972 return -EINVAL;
973
974 return 0;
975}
976
977static int pp_dpm_set_power_profile_state(void *handle,
978 struct amd_pp_profile *request)
979{
980 struct pp_hwmgr *hwmgr;
981 struct pp_instance *pp_handle = (struct pp_instance *)handle;
982 int ret = -1;
983
984 if (!request || pp_check(pp_handle))
985 return -EINVAL;
986
987 hwmgr = pp_handle->hwmgr;
988
989 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
990 pr_info("%s was not implemented.\n", __func__);
991 return 0;
992 }
993
994 if (request->min_sclk ||
995 request->min_mclk ||
996 request->activity_threshold ||
997 request->up_hyst ||
998 request->down_hyst) {
999 if (request->type == AMD_PP_GFX_PROFILE)
1000 memcpy(&hwmgr->gfx_power_profile, request,
1001 sizeof(struct amd_pp_profile));
1002 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1003 memcpy(&hwmgr->compute_power_profile, request,
1004 sizeof(struct amd_pp_profile));
1005 else
1006 return -EINVAL;
1007
1008 if (request->type == hwmgr->current_power_profile)
1009 ret = hwmgr->hwmgr_func->set_power_profile_state(
1010 hwmgr,
1011 request);
1012 } else {
1013 /* set power profile if it exists */
1014 switch (request->type) {
1015 case AMD_PP_GFX_PROFILE:
1016 ret = hwmgr->hwmgr_func->set_power_profile_state(
1017 hwmgr,
1018 &hwmgr->gfx_power_profile);
1019 break;
1020 case AMD_PP_COMPUTE_PROFILE:
1021 ret = hwmgr->hwmgr_func->set_power_profile_state(
1022 hwmgr,
1023 &hwmgr->compute_power_profile);
1024 break;
1025 default:
1026 return -EINVAL;
1027 }
1028 }
1029
1030 if (!ret)
1031 hwmgr->current_power_profile = request->type;
1032
1033 return 0;
1034}
1035
1036static int pp_dpm_switch_power_profile(void *handle,
1037 enum amd_pp_profile_type type)
1038{
1039 struct pp_hwmgr *hwmgr;
1040 struct amd_pp_profile request = {0};
1041 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1042
1043 if (pp_check(pp_handle))
1044 return -EINVAL;
1045
1046 hwmgr = pp_handle->hwmgr;
1047
1048 if (hwmgr->current_power_profile != type) {
1049 request.type = type;
1050 pp_dpm_set_power_profile_state(handle, &request);
1051 }
1052
1053 return 0;
1054}
1055
Alex Deucher1f7371b2015-12-02 17:46:21 -05001056const struct amd_powerplay_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001057 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001058 .load_firmware = pp_dpm_load_fw,
1059 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1060 .force_performance_level = pp_dpm_force_performance_level,
1061 .get_performance_level = pp_dpm_get_performance_level,
1062 .get_current_power_state = pp_dpm_get_current_power_state,
1063 .get_sclk = pp_dpm_get_sclk,
1064 .get_mclk = pp_dpm_get_mclk,
1065 .powergate_vce = pp_dpm_powergate_vce,
1066 .powergate_uvd = pp_dpm_powergate_uvd,
1067 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001068 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1069 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1070 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1071 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001072 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001073 .get_pp_num_states = pp_dpm_get_pp_num_states,
1074 .get_pp_table = pp_dpm_get_pp_table,
1075 .set_pp_table = pp_dpm_set_pp_table,
1076 .force_clock_level = pp_dpm_force_clock_level,
1077 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001078 .get_sclk_od = pp_dpm_get_sclk_od,
1079 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001080 .get_mclk_od = pp_dpm_get_mclk_od,
1081 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001082 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001083 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001084 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1085 .get_power_profile_state = pp_dpm_get_power_profile_state,
1086 .set_power_profile_state = pp_dpm_set_power_profile_state,
1087 .switch_power_profile = pp_dpm_switch_power_profile,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001088};
1089
Rex Zhu1c863802016-12-28 19:43:23 +08001090int amd_powerplay_create(struct amd_pp_init *pp_init,
1091 void **handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001092{
Rex Zhu1c863802016-12-28 19:43:23 +08001093 struct pp_instance *instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001094
Rex Zhu1c863802016-12-28 19:43:23 +08001095 if (pp_init == NULL || handle == NULL)
1096 return -EINVAL;
1097
1098 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
1099 if (instance == NULL)
Jammy Zhouac885b32015-07-21 17:43:02 +08001100 return -ENOMEM;
1101
Rex Zhu1c863802016-12-28 19:43:23 +08001102 instance->pp_valid = PP_VALID;
1103 instance->chip_family = pp_init->chip_family;
1104 instance->chip_id = pp_init->chip_id;
1105 instance->pm_en = pp_init->pm_en;
1106 instance->feature_mask = pp_init->feature_mask;
1107 instance->device = pp_init->device;
Rex Zhu2a507102017-02-20 17:07:36 +08001108 mutex_init(&instance->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001109 *handle = instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001110 return 0;
1111}
1112
Rex Zhu1c863802016-12-28 19:43:23 +08001113int amd_powerplay_destroy(void *handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001114{
1115 struct pp_instance *instance = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +08001116
Rex Zhu1c863802016-12-28 19:43:23 +08001117 if (instance->pm_en) {
Rex Zhu1c863802016-12-28 19:43:23 +08001118 kfree(instance->hwmgr);
1119 instance->hwmgr = NULL;
Rex Zhuba5f8842016-10-27 15:29:57 +08001120 }
Jammy Zhou3bace352015-07-21 21:18:15 +08001121
Rex Zhu1c863802016-12-28 19:43:23 +08001122 kfree(instance->smu_mgr);
1123 instance->smu_mgr = NULL;
1124 kfree(instance);
1125 instance = NULL;
Alex Deucher1f7371b2015-12-02 17:46:21 -05001126 return 0;
1127}
Rex Zhu7fb72a12015-11-19 13:35:30 +08001128
Eric Huang4dcf9e62016-06-01 17:08:07 -04001129int amd_powerplay_reset(void *handle)
1130{
1131 struct pp_instance *instance = (struct pp_instance *)handle;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001132 int ret;
1133
Rex Zhu1c863802016-12-28 19:43:23 +08001134 if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1135 return PP_DPM_DISABLED;
1136
1137 ret = pp_check(instance);
1138 if (ret != 0)
1139 return ret;
1140
Rex Zhudf1e6392017-09-01 13:46:20 +08001141 ret = pp_hw_fini(instance);
Rex Zhu1c863802016-12-28 19:43:23 +08001142 if (ret)
1143 return ret;
1144
1145 ret = hwmgr_hw_init(instance);
1146 if (ret)
1147 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001148
Rex Zhudf1e6392017-09-01 13:46:20 +08001149 return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL);
Eric Huang4dcf9e62016-06-01 17:08:07 -04001150}
1151
Rex Zhu7fb72a12015-11-19 13:35:30 +08001152/* export this function to DAL */
1153
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001154int amd_powerplay_display_configuration_change(void *handle,
1155 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001156{
1157 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001158 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1159 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001160
Rex Zhu1c863802016-12-28 19:43:23 +08001161 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001162
Rex Zhu1c863802016-12-28 19:43:23 +08001163 if (ret != 0)
1164 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001165
Rex Zhu1c863802016-12-28 19:43:23 +08001166 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +08001167 mutex_lock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001168 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhu2a507102017-02-20 17:07:36 +08001169 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001170 return 0;
1171}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001172
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001173int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001174 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001175{
1176 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001177 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1178 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001179
Rex Zhu1c863802016-12-28 19:43:23 +08001180 ret = pp_check(pp_handle);
1181
1182 if (ret != 0)
1183 return ret;
1184
1185 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001186
1187 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001188 return -EINVAL;
1189
Rex Zhu2a507102017-02-20 17:07:36 +08001190 mutex_lock(&pp_handle->pp_lock);
1191 ret = phm_get_dal_power_level(hwmgr, output);
1192 mutex_unlock(&pp_handle->pp_lock);
1193 return ret;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001194}
Rex Zhue273b042015-12-07 18:44:23 +08001195
1196int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001197 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001198{
Rex Zhue273b042015-12-07 18:44:23 +08001199 struct amd_pp_simple_clock_info simple_clocks;
1200 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001201 struct pp_hwmgr *hwmgr;
1202 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1203 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001204
Rex Zhu1c863802016-12-28 19:43:23 +08001205 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001206
Rex Zhu1c863802016-12-28 19:43:23 +08001207 if (ret != 0)
1208 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001209
Rex Zhu1c863802016-12-28 19:43:23 +08001210 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001211
Rex Zhu2a507102017-02-20 17:07:36 +08001212 mutex_lock(&pp_handle->pp_lock);
1213
Rex Zhue273b042015-12-07 18:44:23 +08001214 phm_get_dal_power_level(hwmgr, &simple_clocks);
1215
Rex Zhu2a507102017-02-20 17:07:36 +08001216 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1217 PHM_PlatformCaps_PowerContainment))
1218 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1219 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1220 else
1221 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1222 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1223
1224 if (ret != 0) {
1225 pr_info("Error in phm_get_clock_info \n");
1226 mutex_unlock(&pp_handle->pp_lock);
1227 return -EINVAL;
Rex Zhue273b042015-12-07 18:44:23 +08001228 }
1229
1230 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1231 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1232 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1233 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1234 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1235 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1236
1237 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1238 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1239
1240 clocks->max_clocks_state = simple_clocks.level;
1241
1242 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1243 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1244 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1245 }
Rex Zhu2a507102017-02-20 17:07:36 +08001246 mutex_unlock(&pp_handle->pp_lock);
Rex Zhue273b042015-12-07 18:44:23 +08001247 return 0;
Rex Zhue273b042015-12-07 18:44:23 +08001248}
1249
1250int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1251{
Rex Zhu1c863802016-12-28 19:43:23 +08001252 struct pp_hwmgr *hwmgr;
1253 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1254 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001255
Rex Zhu1c863802016-12-28 19:43:23 +08001256 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001257
Rex Zhu1c863802016-12-28 19:43:23 +08001258 if (ret != 0)
1259 return ret;
1260
1261 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001262
1263 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001264 return -EINVAL;
1265
Rex Zhu2a507102017-02-20 17:07:36 +08001266 mutex_lock(&pp_handle->pp_lock);
1267 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1268 mutex_unlock(&pp_handle->pp_lock);
1269 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001270}
1271
Eric Huangd0187722017-03-06 13:13:48 -05001272int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1273 enum amd_pp_clock_type type,
1274 struct pp_clock_levels_with_latency *clocks)
1275{
1276 struct pp_hwmgr *hwmgr;
1277 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1278 int ret = 0;
1279
1280 ret = pp_check(pp_handle);
1281 if (ret != 0)
1282 return ret;
1283
1284 if (!clocks)
1285 return -EINVAL;
1286
1287 mutex_lock(&pp_handle->pp_lock);
1288 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1289 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1290 mutex_unlock(&pp_handle->pp_lock);
1291 return ret;
1292}
1293
1294int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1295 enum amd_pp_clock_type type,
1296 struct pp_clock_levels_with_voltage *clocks)
1297{
1298 struct pp_hwmgr *hwmgr;
1299 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1300 int ret = 0;
1301
1302 ret = pp_check(pp_handle);
1303 if (ret != 0)
1304 return ret;
1305
1306 if (!clocks)
1307 return -EINVAL;
1308
1309 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1310
1311 mutex_lock(&pp_handle->pp_lock);
1312
1313 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1314
1315 mutex_unlock(&pp_handle->pp_lock);
1316 return ret;
1317}
1318
1319int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1320 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1321{
1322 struct pp_hwmgr *hwmgr;
1323 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1324 int ret = 0;
1325
1326 ret = pp_check(pp_handle);
1327 if (ret != 0)
1328 return ret;
1329
1330 if (!wm_with_clock_ranges)
1331 return -EINVAL;
1332
1333 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1334
1335 mutex_lock(&pp_handle->pp_lock);
1336 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1337 wm_with_clock_ranges);
1338 mutex_unlock(&pp_handle->pp_lock);
1339
1340 return ret;
1341}
1342
1343int amd_powerplay_display_clock_voltage_request(void *handle,
1344 struct pp_display_clock_request *clock)
1345{
1346 struct pp_hwmgr *hwmgr;
1347 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1348 int ret = 0;
1349
1350 ret = pp_check(pp_handle);
1351 if (ret != 0)
1352 return ret;
1353
1354 if (!clock)
1355 return -EINVAL;
1356
1357 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1358
1359 mutex_lock(&pp_handle->pp_lock);
1360 ret = phm_display_clock_voltage_request(hwmgr, clock);
1361 mutex_unlock(&pp_handle->pp_lock);
1362
1363 return ret;
1364}
1365
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001366int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1367 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001368{
Rex Zhue273b042015-12-07 18:44:23 +08001369 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001370 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1371 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001372
Rex Zhu1c863802016-12-28 19:43:23 +08001373 ret = pp_check(pp_handle);
1374
1375 if (ret != 0)
1376 return ret;
1377
1378 hwmgr = pp_handle->hwmgr;
1379
Rex Zhufa9e6992015-12-29 13:56:03 +08001380 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001381 return -EINVAL;
1382
Rex Zhu2a507102017-02-20 17:07:36 +08001383 mutex_lock(&pp_handle->pp_lock);
1384
Rex Zhue273b042015-12-07 18:44:23 +08001385 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001386 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001387
Rex Zhu2a507102017-02-20 17:07:36 +08001388 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001389 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001390}
1391