blob: 9da5b0bb66d874bb72412544d5f4410e02a3e0d3 [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"
32#include "eventmanager.h"
Alex Deucher1f7371b2015-12-02 17:46:21 -050033
Rex Zhuaf223df2016-07-28 16:51:47 +080034
Rex Zhu1c863802016-12-28 19:43:23 +080035static inline int pp_check(struct pp_instance *handle)
36{
37 if (handle == NULL || handle->pp_valid != PP_VALID)
38 return -EINVAL;
Rex Zhua969e162015-12-29 13:56:03 +080039
Rex Zhu1c863802016-12-28 19:43:23 +080040 if (handle->smu_mgr == NULL || handle->smu_mgr->smumgr_funcs == NULL)
41 return -EINVAL;
42
43 if (handle->pm_en == 0)
44 return PP_DPM_DISABLED;
45
46 if (handle->hwmgr == NULL || handle->hwmgr->hwmgr_func == NULL
47 || handle->eventmgr == NULL)
48 return PP_DPM_DISABLED;
49
50 return 0;
51}
Rex Zhu7383bcb2016-03-30 11:35:50 +080052
Alex Deucher1f7371b2015-12-02 17:46:21 -050053static int pp_early_init(void *handle)
54{
Rex Zhu1c863802016-12-28 19:43:23 +080055 int ret;
56 struct pp_instance *pp_handle = (struct pp_instance *)handle;
57
58 ret = smum_early_init(pp_handle);
59 if (ret)
60 return ret;
61
62 if ((pp_handle->pm_en == 0)
63 || cgs_is_virtualization_enabled(pp_handle->device))
64 return PP_DPM_DISABLED;
65
66 ret = hwmgr_early_init(pp_handle);
67 if (ret) {
68 pp_handle->pm_en = 0;
69 return PP_DPM_DISABLED;
70 }
71
72 ret = eventmgr_early_init(pp_handle);
73 if (ret) {
74 kfree(pp_handle->hwmgr);
75 pp_handle->hwmgr = NULL;
76 pp_handle->pm_en = 0;
77 return PP_DPM_DISABLED;
78 }
79
Alex Deucher1f7371b2015-12-02 17:46:21 -050080 return 0;
81}
82
83static int pp_sw_init(void *handle)
84{
Rex Zhu1c863802016-12-28 19:43:23 +080085 struct pp_smumgr *smumgr;
Jammy Zhou3bace352015-07-21 21:18:15 +080086 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +080087 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +080088
Rex Zhu1c863802016-12-28 19:43:23 +080089 ret = pp_check(pp_handle);
Jammy Zhou3bace352015-07-21 21:18:15 +080090
Rex Zhu1c863802016-12-28 19:43:23 +080091 if (ret == 0 || ret == PP_DPM_DISABLED) {
92 smumgr = pp_handle->smu_mgr;
Jammy Zhou3bace352015-07-21 21:18:15 +080093
Rex Zhu1c863802016-12-28 19:43:23 +080094 if (smumgr->smumgr_funcs->smu_init == NULL)
95 return -EINVAL;
Rex Zhu7383bcb2016-03-30 11:35:50 +080096
Rex Zhu1c863802016-12-28 19:43:23 +080097 ret = smumgr->smumgr_funcs->smu_init(smumgr);
Jammy Zhou3bace352015-07-21 21:18:15 +080098
Rex Zhu1c863802016-12-28 19:43:23 +080099 pr_info("amdgpu: powerplay sw initialized\n");
Huang Rui167112b2016-12-14 16:26:54 +0800100 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800101 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500102}
103
104static int pp_sw_fini(void *handle)
105{
Rex Zhu1c863802016-12-28 19:43:23 +0800106 struct pp_smumgr *smumgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800107 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800108 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhou3bace352015-07-21 21:18:15 +0800109
Rex Zhu1c863802016-12-28 19:43:23 +0800110 ret = pp_check(pp_handle);
111 if (ret == 0 || ret == PP_DPM_DISABLED) {
112 smumgr = pp_handle->smu_mgr;
Jammy Zhou3bace352015-07-21 21:18:15 +0800113
Rex Zhu1c863802016-12-28 19:43:23 +0800114 if (smumgr->smumgr_funcs->smu_fini == NULL)
115 return -EINVAL;
Jammy Zhou3bace352015-07-21 21:18:15 +0800116
Rex Zhu1c863802016-12-28 19:43:23 +0800117 ret = smumgr->smumgr_funcs->smu_fini(smumgr);
118 }
Jammy Zhou3bace352015-07-21 21:18:15 +0800119 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500120}
121
122static int pp_hw_init(void *handle)
123{
Jammy Zhouac885b32015-07-21 17:43:02 +0800124 struct pp_smumgr *smumgr;
Rex Zhue92a0372015-09-23 15:14:54 +0800125 struct pp_eventmgr *eventmgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800126 int ret = 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800127 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Jammy Zhouac885b32015-07-21 17:43:02 +0800128
Rex Zhu1c863802016-12-28 19:43:23 +0800129 ret = pp_check(pp_handle);
Jammy Zhouac885b32015-07-21 17:43:02 +0800130
Rex Zhu1c863802016-12-28 19:43:23 +0800131 if (ret == 0 || ret == PP_DPM_DISABLED) {
132 smumgr = pp_handle->smu_mgr;
Jammy Zhouac885b32015-07-21 17:43:02 +0800133
Rex Zhu1c863802016-12-28 19:43:23 +0800134 if (smumgr->smumgr_funcs->start_smu == NULL)
135 return -EINVAL;
Jammy Zhouac885b32015-07-21 17:43:02 +0800136
Rex Zhu1c863802016-12-28 19:43:23 +0800137 if(smumgr->smumgr_funcs->start_smu(smumgr)) {
138 pr_err("smc start failed\n");
139 smumgr->smumgr_funcs->smu_fini(smumgr);
140 return -EINVAL;;
141 }
142 if (ret == PP_DPM_DISABLED)
143 return PP_DPM_DISABLED;
Jammy Zhouac885b32015-07-21 17:43:02 +0800144 }
145
Rex Zhu1c863802016-12-28 19:43:23 +0800146 ret = hwmgr_hw_init(pp_handle);
147 if (ret)
148 goto err;
Rex Zhuba5f8842016-10-27 15:29:57 +0800149
150 eventmgr = pp_handle->eventmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800151 if (eventmgr->pp_eventmgr_init == NULL ||
152 eventmgr->pp_eventmgr_init(eventmgr))
153 goto err;
Rex Zhue92a0372015-09-23 15:14:54 +0800154
Alex Deucher1f7371b2015-12-02 17:46:21 -0500155 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800156err:
157 pp_handle->pm_en = 0;
158 kfree(pp_handle->eventmgr);
159 kfree(pp_handle->hwmgr);
160 pp_handle->hwmgr = NULL;
161 pp_handle->eventmgr = NULL;
162 return PP_DPM_DISABLED;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500163}
164
165static int pp_hw_fini(void *handle)
166{
Rex Zhue92a0372015-09-23 15:14:54 +0800167 struct pp_eventmgr *eventmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800168 struct pp_instance *pp_handle = (struct pp_instance *)handle;
169 int ret = 0;
Jammy Zhouac885b32015-07-21 17:43:02 +0800170
Rex Zhu1c863802016-12-28 19:43:23 +0800171 ret = pp_check(pp_handle);
Jammy Zhouac885b32015-07-21 17:43:02 +0800172
Rex Zhu1c863802016-12-28 19:43:23 +0800173 if (ret == 0) {
174 eventmgr = pp_handle->eventmgr;
Rex Zhue92a0372015-09-23 15:14:54 +0800175
Rex Zhu1c863802016-12-28 19:43:23 +0800176 if (eventmgr->pp_eventmgr_fini != NULL)
177 eventmgr->pp_eventmgr_fini(eventmgr);
Rex Zhue92a0372015-09-23 15:14:54 +0800178
Rex Zhu1c863802016-12-28 19:43:23 +0800179 hwmgr_hw_fini(pp_handle);
180 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500181 return 0;
182}
183
184static bool pp_is_idle(void *handle)
185{
Edward O'Callaghaned5121a2016-07-12 10:17:52 +1000186 return false;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500187}
188
189static int pp_wait_for_idle(void *handle)
190{
191 return 0;
192}
193
194static int pp_sw_reset(void *handle)
195{
196 return 0;
197}
198
Alex Deucher1f7371b2015-12-02 17:46:21 -0500199
Rex Zhu465f96e2016-09-18 16:52:03 +0800200int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500201{
Eric Huang03e39052016-02-09 16:26:00 -0500202 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800203 struct pp_instance *pp_handle = (struct pp_instance *)handle;
204 int ret = 0;
Eric Huang03e39052016-02-09 16:26:00 -0500205
Rex Zhu1c863802016-12-28 19:43:23 +0800206 ret = pp_check(pp_handle);
Eric Huang03e39052016-02-09 16:26:00 -0500207
Rex Zhu1c863802016-12-28 19:43:23 +0800208 if (ret != 0)
209 return ret;
Eric Huang03e39052016-02-09 16:26:00 -0500210
Rex Zhu1c863802016-12-28 19:43:23 +0800211 hwmgr = pp_handle->hwmgr;
Eric Huang03e39052016-02-09 16:26:00 -0500212
Rex Zhu7383bcb2016-03-30 11:35:50 +0800213 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800214 pr_info("%s was not implemented.\n", __func__);
Flora Cui538333f2016-02-15 15:45:59 +0800215 return 0;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800216 }
Flora Cui538333f2016-02-15 15:45:59 +0800217
Rex Zhu465f96e2016-09-18 16:52:03 +0800218 return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500219}
220
221static int pp_set_powergating_state(void *handle,
222 enum amd_powergating_state state)
223{
Eric Huang65f85e72016-02-11 15:54:45 -0500224 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800225 struct pp_instance *pp_handle = (struct pp_instance *)handle;
226 int ret = 0;
Eric Huang65f85e72016-02-11 15:54:45 -0500227
Rex Zhu1c863802016-12-28 19:43:23 +0800228 ret = pp_check(pp_handle);
Eric Huang65f85e72016-02-11 15:54:45 -0500229
Rex Zhu1c863802016-12-28 19:43:23 +0800230 if (ret != 0)
231 return ret;
Eric Huang65f85e72016-02-11 15:54:45 -0500232
Rex Zhu1c863802016-12-28 19:43:23 +0800233 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800234
235 if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800236 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800237 return 0;
238 }
Eric Huang65f85e72016-02-11 15:54:45 -0500239
240 /* Enable/disable GFX per cu powergating through SMU */
241 return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
Andrew F. Davis93a4aec2017-03-15 11:20:24 -0500242 state == AMD_PG_STATE_GATE);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500243}
244
245static int pp_suspend(void *handle)
246{
Rex Zhu577bbe02015-08-28 12:56:43 +0800247 struct pp_eventmgr *eventmgr;
248 struct pem_event_data event_data = { {0} };
Rex Zhu1c863802016-12-28 19:43:23 +0800249 struct pp_instance *pp_handle = (struct pp_instance *)handle;
250 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800251
Rex Zhu1c863802016-12-28 19:43:23 +0800252 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800253
Rex Zhu1c863802016-12-28 19:43:23 +0800254 if (ret != 0)
255 return ret;
256
Rex Zhu577bbe02015-08-28 12:56:43 +0800257 eventmgr = pp_handle->eventmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800258 pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
Rex Zhuba5f8842016-10-27 15:29:57 +0800259
Alex Deucher1f7371b2015-12-02 17:46:21 -0500260 return 0;
261}
262
263static int pp_resume(void *handle)
264{
Rex Zhu577bbe02015-08-28 12:56:43 +0800265 struct pp_eventmgr *eventmgr;
266 struct pem_event_data event_data = { {0} };
Rex Zhue0b71a72015-12-29 10:25:19 +0800267 struct pp_smumgr *smumgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800268 int ret, ret1;
269 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800270
Rex Zhu1c863802016-12-28 19:43:23 +0800271 ret1 = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800272
Rex Zhu1c863802016-12-28 19:43:23 +0800273 if (ret1 != 0 && ret1 != PP_DPM_DISABLED)
274 return ret1;
275
Rex Zhue0b71a72015-12-29 10:25:19 +0800276 smumgr = pp_handle->smu_mgr;
277
Rex Zhu1c863802016-12-28 19:43:23 +0800278 if (smumgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800279 return -EINVAL;
280
281 ret = smumgr->smumgr_funcs->start_smu(smumgr);
282 if (ret) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800283 pr_err("smc start failed\n");
Rex Zhue0b71a72015-12-29 10:25:19 +0800284 smumgr->smumgr_funcs->smu_fini(smumgr);
285 return ret;
286 }
287
Rex Zhu1c863802016-12-28 19:43:23 +0800288 if (ret1 == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800289 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800290
Rex Zhu577bbe02015-08-28 12:56:43 +0800291 eventmgr = pp_handle->eventmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800292
293 pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
Rex Zhue0b71a72015-12-29 10:25:19 +0800294
Alex Deucher1f7371b2015-12-02 17:46:21 -0500295 return 0;
296}
297
298const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400299 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500300 .early_init = pp_early_init,
301 .late_init = NULL,
302 .sw_init = pp_sw_init,
303 .sw_fini = pp_sw_fini,
304 .hw_init = pp_hw_init,
305 .hw_fini = pp_hw_fini,
306 .suspend = pp_suspend,
307 .resume = pp_resume,
308 .is_idle = pp_is_idle,
309 .wait_for_idle = pp_wait_for_idle,
310 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800311 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500312 .set_powergating_state = pp_set_powergating_state,
313};
314
315static int pp_dpm_load_fw(void *handle)
316{
317 return 0;
318}
319
320static int pp_dpm_fw_loading_complete(void *handle)
321{
322 return 0;
323}
324
325static int pp_dpm_force_performance_level(void *handle,
326 enum amd_dpm_forced_level level)
327{
Rex Zhu577bbe02015-08-28 12:56:43 +0800328 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800329 struct pp_instance *pp_handle = (struct pp_instance *)handle;
330 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800331
Rex Zhu1c863802016-12-28 19:43:23 +0800332 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800333
Rex Zhu1c863802016-12-28 19:43:23 +0800334 if (ret != 0)
335 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800336
337 hwmgr = pp_handle->hwmgr;
338
Rex Zhu7383bcb2016-03-30 11:35:50 +0800339 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800340 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800341 return 0;
342 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800343
Rex Zhu2a507102017-02-20 17:07:36 +0800344 mutex_lock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800345 hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
Rex Zhu2a507102017-02-20 17:07:36 +0800346 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500347 return 0;
348}
Rex Zhu577bbe02015-08-28 12:56:43 +0800349
Alex Deucher1f7371b2015-12-02 17:46:21 -0500350static enum amd_dpm_forced_level pp_dpm_get_performance_level(
351 void *handle)
352{
Rex Zhu577bbe02015-08-28 12:56:43 +0800353 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800354 struct pp_instance *pp_handle = (struct pp_instance *)handle;
355 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800356 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800357
Rex Zhu1c863802016-12-28 19:43:23 +0800358 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800359
Rex Zhu1c863802016-12-28 19:43:23 +0800360 if (ret != 0)
361 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800362
Rex Zhu1c863802016-12-28 19:43:23 +0800363 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800364 mutex_lock(&pp_handle->pp_lock);
365 level = hwmgr->dpm_level;
366 mutex_unlock(&pp_handle->pp_lock);
367 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500368}
Rex Zhu577bbe02015-08-28 12:56:43 +0800369
Alex Deucher1f7371b2015-12-02 17:46:21 -0500370static int pp_dpm_get_sclk(void *handle, bool low)
371{
Rex Zhu577bbe02015-08-28 12:56:43 +0800372 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800373 struct pp_instance *pp_handle = (struct pp_instance *)handle;
374 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800375
Rex Zhu1c863802016-12-28 19:43:23 +0800376 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800377
Rex Zhu1c863802016-12-28 19:43:23 +0800378 if (ret != 0)
379 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800380
Rex Zhu1c863802016-12-28 19:43:23 +0800381 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800382
383 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800384 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800385 return 0;
386 }
Rex Zhu2a507102017-02-20 17:07:36 +0800387 mutex_lock(&pp_handle->pp_lock);
388 ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
389 mutex_unlock(&pp_handle->pp_lock);
390 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500391}
Rex Zhu577bbe02015-08-28 12:56:43 +0800392
Alex Deucher1f7371b2015-12-02 17:46:21 -0500393static int pp_dpm_get_mclk(void *handle, bool low)
394{
Rex Zhu577bbe02015-08-28 12:56:43 +0800395 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800396 struct pp_instance *pp_handle = (struct pp_instance *)handle;
397 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800398
Rex Zhu1c863802016-12-28 19:43:23 +0800399 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800400
Rex Zhu1c863802016-12-28 19:43:23 +0800401 if (ret != 0)
402 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800403
Rex Zhu1c863802016-12-28 19:43:23 +0800404 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800405
406 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800407 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800408 return 0;
409 }
Rex Zhu2a507102017-02-20 17:07:36 +0800410 mutex_lock(&pp_handle->pp_lock);
411 ret = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
412 mutex_unlock(&pp_handle->pp_lock);
413 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500414}
Rex Zhu577bbe02015-08-28 12:56:43 +0800415
Alex Deucher1f7371b2015-12-02 17:46:21 -0500416static int pp_dpm_powergate_vce(void *handle, bool gate)
417{
Rex Zhu577bbe02015-08-28 12:56:43 +0800418 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800419 struct pp_instance *pp_handle = (struct pp_instance *)handle;
420 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800421
Rex Zhu1c863802016-12-28 19:43:23 +0800422 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800423
Rex Zhu1c863802016-12-28 19:43:23 +0800424 if (ret != 0)
425 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800426
Rex Zhu1c863802016-12-28 19:43:23 +0800427 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800428
429 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800430 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800431 return 0;
432 }
Rex Zhu2a507102017-02-20 17:07:36 +0800433 mutex_lock(&pp_handle->pp_lock);
434 ret = hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
435 mutex_unlock(&pp_handle->pp_lock);
436 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500437}
Rex Zhu577bbe02015-08-28 12:56:43 +0800438
Alex Deucher1f7371b2015-12-02 17:46:21 -0500439static int pp_dpm_powergate_uvd(void *handle, bool gate)
440{
Rex Zhu577bbe02015-08-28 12:56:43 +0800441 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800442 struct pp_instance *pp_handle = (struct pp_instance *)handle;
443 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800444
Rex Zhu1c863802016-12-28 19:43:23 +0800445 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800446
Rex Zhu1c863802016-12-28 19:43:23 +0800447 if (ret != 0)
448 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800449
Rex Zhu1c863802016-12-28 19:43:23 +0800450 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800451
452 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800453 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800454 return 0;
455 }
Rex Zhu2a507102017-02-20 17:07:36 +0800456 mutex_lock(&pp_handle->pp_lock);
457 ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
458 mutex_unlock(&pp_handle->pp_lock);
459 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800460}
461
462static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state)
463{
464 switch (state) {
465 case POWER_STATE_TYPE_BATTERY:
466 return PP_StateUILabel_Battery;
467 case POWER_STATE_TYPE_BALANCED:
468 return PP_StateUILabel_Balanced;
469 case POWER_STATE_TYPE_PERFORMANCE:
470 return PP_StateUILabel_Performance;
471 default:
472 return PP_StateUILabel_None;
473 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500474}
475
Baoyou Xief8a4c112016-09-30 17:58:42 +0800476static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
477 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500478{
Rex Zhu577bbe02015-08-28 12:56:43 +0800479 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800480 struct pem_event_data data = { {0} };
Rex Zhu1c863802016-12-28 19:43:23 +0800481 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800482
Rex Zhu1c863802016-12-28 19:43:23 +0800483 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800484
Rex Zhu1c863802016-12-28 19:43:23 +0800485 if (ret != 0)
486 return ret;
Rex Zhu2a507102017-02-20 17:07:36 +0800487 mutex_lock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800488 switch (event_id) {
489 case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
490 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
491 break;
492 case AMD_PP_EVENT_ENABLE_USER_STATE:
493 {
494 enum amd_pm_state_type ps;
495
Dan Carpenter99147e62017-04-03 21:42:42 +0300496 if (input == NULL) {
497 ret = -EINVAL;
498 break;
499 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800500 ps = *(unsigned long *)input;
501
502 data.requested_ui_label = power_state_convert(ps);
503 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
Rex Zhudc26a2a2016-02-25 17:16:52 +0800504 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800505 }
Rex Zhudc26a2a2016-02-25 17:16:52 +0800506 case AMD_PP_EVENT_COMPLETE_INIT:
507 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
508 break;
Eric Huang428bafa2016-05-12 14:51:21 -0400509 case AMD_PP_EVENT_READJUST_POWER_STATE:
Eric Huang428bafa2016-05-12 14:51:21 -0400510 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
511 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800512 default:
513 break;
514 }
Rex Zhu2a507102017-02-20 17:07:36 +0800515 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800516 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500517}
Rex Zhu577bbe02015-08-28 12:56:43 +0800518
Baoyou Xief8a4c112016-09-30 17:58:42 +0800519static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500520{
Rex Zhu577bbe02015-08-28 12:56:43 +0800521 struct pp_hwmgr *hwmgr;
522 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800523 struct pp_instance *pp_handle = (struct pp_instance *)handle;
524 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800525 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800526
Rex Zhu1c863802016-12-28 19:43:23 +0800527 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800528
Rex Zhu1c863802016-12-28 19:43:23 +0800529 if (ret != 0)
530 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800531
Rex Zhu1c863802016-12-28 19:43:23 +0800532 hwmgr = pp_handle->hwmgr;
533
534 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800535 return -EINVAL;
536
Rex Zhu2a507102017-02-20 17:07:36 +0800537 mutex_lock(&pp_handle->pp_lock);
538
Rex Zhu577bbe02015-08-28 12:56:43 +0800539 state = hwmgr->current_ps;
540
541 switch (state->classification.ui_label) {
542 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800543 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300544 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800545 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800546 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300547 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800548 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800549 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300550 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800551 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500552 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800553 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500554 else
Rex Zhu2a507102017-02-20 17:07:36 +0800555 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300556 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800557 }
Rex Zhu2a507102017-02-20 17:07:36 +0800558 mutex_unlock(&pp_handle->pp_lock);
559
560 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500561}
Rex Zhu577bbe02015-08-28 12:56:43 +0800562
Rex Zhucac9a192015-10-16 11:48:21 +0800563static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
564{
565 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800566 struct pp_instance *pp_handle = (struct pp_instance *)handle;
567 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800568
Rex Zhu1c863802016-12-28 19:43:23 +0800569 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800570
Rex Zhu1c863802016-12-28 19:43:23 +0800571 if (ret != 0)
572 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800573
Rex Zhu1c863802016-12-28 19:43:23 +0800574 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800575
576 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800577 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800578 return 0;
579 }
Rex Zhu2a507102017-02-20 17:07:36 +0800580 mutex_lock(&pp_handle->pp_lock);
581 ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
582 mutex_unlock(&pp_handle->pp_lock);
583 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800584}
585
586static int pp_dpm_get_fan_control_mode(void *handle)
587{
588 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800589 struct pp_instance *pp_handle = (struct pp_instance *)handle;
590 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800591
Rex Zhu1c863802016-12-28 19:43:23 +0800592 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800593
Rex Zhu1c863802016-12-28 19:43:23 +0800594 if (ret != 0)
595 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800596
Rex Zhu1c863802016-12-28 19:43:23 +0800597 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800598
599 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800600 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800601 return 0;
602 }
Rex Zhu2a507102017-02-20 17:07:36 +0800603 mutex_lock(&pp_handle->pp_lock);
604 ret = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
605 mutex_unlock(&pp_handle->pp_lock);
606 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800607}
608
609static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
610{
611 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800612 struct pp_instance *pp_handle = (struct pp_instance *)handle;
613 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800614
Rex Zhu1c863802016-12-28 19:43:23 +0800615 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800616
Rex Zhu1c863802016-12-28 19:43:23 +0800617 if (ret != 0)
618 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800619
Rex Zhu1c863802016-12-28 19:43:23 +0800620 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800621
622 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800623 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800624 return 0;
625 }
Rex Zhu2a507102017-02-20 17:07:36 +0800626 mutex_lock(&pp_handle->pp_lock);
627 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
628 mutex_unlock(&pp_handle->pp_lock);
629 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800630}
631
632static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
633{
634 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800635 struct pp_instance *pp_handle = (struct pp_instance *)handle;
636 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800637
Rex Zhu1c863802016-12-28 19:43:23 +0800638 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800639
Rex Zhu1c863802016-12-28 19:43:23 +0800640 if (ret != 0)
641 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800642
Rex Zhu1c863802016-12-28 19:43:23 +0800643 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800644
645 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800646 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800647 return 0;
648 }
Rex Zhucac9a192015-10-16 11:48:21 +0800649
Rex Zhu2a507102017-02-20 17:07:36 +0800650 mutex_lock(&pp_handle->pp_lock);
651 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
652 mutex_unlock(&pp_handle->pp_lock);
653 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800654}
655
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300656static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
657{
658 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800659 struct pp_instance *pp_handle = (struct pp_instance *)handle;
660 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300661
Rex Zhu1c863802016-12-28 19:43:23 +0800662 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300663
Rex Zhu1c863802016-12-28 19:43:23 +0800664 if (ret != 0)
665 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300666
Rex Zhu1c863802016-12-28 19:43:23 +0800667 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300668
669 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
670 return -EINVAL;
671
Rex Zhu2a507102017-02-20 17:07:36 +0800672 mutex_lock(&pp_handle->pp_lock);
673 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
674 mutex_unlock(&pp_handle->pp_lock);
675 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300676}
677
Rex Zhucac9a192015-10-16 11:48:21 +0800678static int pp_dpm_get_temperature(void *handle)
679{
680 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800681 struct pp_instance *pp_handle = (struct pp_instance *)handle;
682 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800683
Rex Zhu1c863802016-12-28 19:43:23 +0800684 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800685
Rex Zhu1c863802016-12-28 19:43:23 +0800686 if (ret != 0)
687 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800688
Rex Zhu1c863802016-12-28 19:43:23 +0800689 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800690
691 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800692 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800693 return 0;
694 }
Rex Zhu2a507102017-02-20 17:07:36 +0800695 mutex_lock(&pp_handle->pp_lock);
696 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
697 mutex_unlock(&pp_handle->pp_lock);
698 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800699}
Rex Zhu577bbe02015-08-28 12:56:43 +0800700
Eric Huangf3898ea2015-12-11 16:24:34 -0500701static int pp_dpm_get_pp_num_states(void *handle,
702 struct pp_states_info *data)
703{
704 struct pp_hwmgr *hwmgr;
705 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800706 struct pp_instance *pp_handle = (struct pp_instance *)handle;
707 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500708
Rex Zhu1c863802016-12-28 19:43:23 +0800709 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500710
Rex Zhu1c863802016-12-28 19:43:23 +0800711 if (ret != 0)
712 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500713
Rex Zhu1c863802016-12-28 19:43:23 +0800714 hwmgr = pp_handle->hwmgr;
715
716 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500717 return -EINVAL;
718
Rex Zhu2a507102017-02-20 17:07:36 +0800719 mutex_lock(&pp_handle->pp_lock);
720
Eric Huangf3898ea2015-12-11 16:24:34 -0500721 data->nums = hwmgr->num_ps;
722
723 for (i = 0; i < hwmgr->num_ps; i++) {
724 struct pp_power_state *state = (struct pp_power_state *)
725 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
726 switch (state->classification.ui_label) {
727 case PP_StateUILabel_Battery:
728 data->states[i] = POWER_STATE_TYPE_BATTERY;
729 break;
730 case PP_StateUILabel_Balanced:
731 data->states[i] = POWER_STATE_TYPE_BALANCED;
732 break;
733 case PP_StateUILabel_Performance:
734 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
735 break;
736 default:
737 if (state->classification.flags & PP_StateClassificationFlag_Boot)
738 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
739 else
740 data->states[i] = POWER_STATE_TYPE_DEFAULT;
741 }
742 }
Rex Zhu2a507102017-02-20 17:07:36 +0800743 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500744 return 0;
745}
746
747static int pp_dpm_get_pp_table(void *handle, char **table)
748{
749 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800750 struct pp_instance *pp_handle = (struct pp_instance *)handle;
751 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800752 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500753
Rex Zhu1c863802016-12-28 19:43:23 +0800754 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500755
Rex Zhu1c863802016-12-28 19:43:23 +0800756 if (ret != 0)
757 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500758
Rex Zhu1c863802016-12-28 19:43:23 +0800759 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800760
Eric Huang4dcf9e62016-06-01 17:08:07 -0400761 if (!hwmgr->soft_pp_table)
762 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500763
Rex Zhu2a507102017-02-20 17:07:36 +0800764 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400765 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800766 size = hwmgr->soft_pp_table_size;
767 mutex_unlock(&pp_handle->pp_lock);
768 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500769}
770
771static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
772{
773 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800774 struct pp_instance *pp_handle = (struct pp_instance *)handle;
775 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500776
Rex Zhu1c863802016-12-28 19:43:23 +0800777 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500778
Rex Zhu1c863802016-12-28 19:43:23 +0800779 if (ret != 0)
780 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500781
Rex Zhu1c863802016-12-28 19:43:23 +0800782 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800783 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400784 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000785 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
786 hwmgr->soft_pp_table_size,
787 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800788 if (!hwmgr->hardcode_pp_table) {
789 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400790 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800791 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800792 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500793
Eric Huang4dcf9e62016-06-01 17:08:07 -0400794 memcpy(hwmgr->hardcode_pp_table, buf, size);
795
796 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800797 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400798
Eric Huangdd4bdf32017-03-01 15:49:31 -0500799 ret = amd_powerplay_reset(handle);
800 if (ret)
801 return ret;
802
803 if (hwmgr->hwmgr_func->avfs_control) {
804 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
805 if (ret)
806 return ret;
807 }
808
809 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500810}
811
812static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400813 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500814{
815 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800816 struct pp_instance *pp_handle = (struct pp_instance *)handle;
817 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500818
Rex Zhu1c863802016-12-28 19:43:23 +0800819 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500820
Rex Zhu1c863802016-12-28 19:43:23 +0800821 if (ret != 0)
822 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500823
Rex Zhu1c863802016-12-28 19:43:23 +0800824 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800825
826 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800827 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800828 return 0;
829 }
Rex Zhu2a507102017-02-20 17:07:36 +0800830 mutex_lock(&pp_handle->pp_lock);
831 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
832 mutex_unlock(&pp_handle->pp_lock);
833 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500834}
835
836static int pp_dpm_print_clock_levels(void *handle,
837 enum pp_clock_type type, char *buf)
838{
839 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800840 struct pp_instance *pp_handle = (struct pp_instance *)handle;
841 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500842
Rex Zhu1c863802016-12-28 19:43:23 +0800843 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500844
Rex Zhu1c863802016-12-28 19:43:23 +0800845 if (ret != 0)
846 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500847
Rex Zhu1c863802016-12-28 19:43:23 +0800848 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500849
Rex Zhu7383bcb2016-03-30 11:35:50 +0800850 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800851 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800852 return 0;
853 }
Rex Zhu2a507102017-02-20 17:07:36 +0800854 mutex_lock(&pp_handle->pp_lock);
855 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
856 mutex_unlock(&pp_handle->pp_lock);
857 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500858}
859
Eric Huang428bafa2016-05-12 14:51:21 -0400860static int pp_dpm_get_sclk_od(void *handle)
861{
862 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800863 struct pp_instance *pp_handle = (struct pp_instance *)handle;
864 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400865
Rex Zhu1c863802016-12-28 19:43:23 +0800866 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400867
Rex Zhu1c863802016-12-28 19:43:23 +0800868 if (ret != 0)
869 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400870
Rex Zhu1c863802016-12-28 19:43:23 +0800871 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400872
873 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800874 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400875 return 0;
876 }
Rex Zhu2a507102017-02-20 17:07:36 +0800877 mutex_lock(&pp_handle->pp_lock);
878 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
879 mutex_unlock(&pp_handle->pp_lock);
880 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400881}
882
883static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
884{
885 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800886 struct pp_instance *pp_handle = (struct pp_instance *)handle;
887 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400888
Rex Zhu1c863802016-12-28 19:43:23 +0800889 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400890
Rex Zhu1c863802016-12-28 19:43:23 +0800891 if (ret != 0)
892 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400893
Rex Zhu1c863802016-12-28 19:43:23 +0800894 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400895
896 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800897 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400898 return 0;
899 }
900
Rex Zhu2a507102017-02-20 17:07:36 +0800901 mutex_lock(&pp_handle->pp_lock);
902 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400903 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800904 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400905}
906
Eric Huangf2bdc052016-05-24 15:11:17 -0400907static int pp_dpm_get_mclk_od(void *handle)
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;
Eric Huangf2bdc052016-05-24 15:11:17 -0400912
Rex Zhu1c863802016-12-28 19:43:23 +0800913 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400914
Rex Zhu1c863802016-12-28 19:43:23 +0800915 if (ret != 0)
916 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400917
Rex Zhu1c863802016-12-28 19:43:23 +0800918 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400919
920 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800921 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400922 return 0;
923 }
Rex Zhu2a507102017-02-20 17:07:36 +0800924 mutex_lock(&pp_handle->pp_lock);
925 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
926 mutex_unlock(&pp_handle->pp_lock);
927 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400928}
929
930static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
931{
932 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800933 struct pp_instance *pp_handle = (struct pp_instance *)handle;
934 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400935
Rex Zhu1c863802016-12-28 19:43:23 +0800936 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400937
Rex Zhu1c863802016-12-28 19:43:23 +0800938 if (ret != 0)
939 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400940
Rex Zhu1c863802016-12-28 19:43:23 +0800941 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400942
943 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800944 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400945 return 0;
946 }
Rex Zhu2a507102017-02-20 17:07:36 +0800947 mutex_lock(&pp_handle->pp_lock);
948 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
949 mutex_unlock(&pp_handle->pp_lock);
950 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400951}
952
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500953static int pp_dpm_read_sensor(void *handle, int idx,
954 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400955{
956 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800957 struct pp_instance *pp_handle = (struct pp_instance *)handle;
958 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400959
Rex Zhu1c863802016-12-28 19:43:23 +0800960 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400961
Rex Zhu1c863802016-12-28 19:43:23 +0800962 if (ret != 0)
963 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400964
Rex Zhu1c863802016-12-28 19:43:23 +0800965 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400966
967 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800968 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400969 return 0;
970 }
971
Rex Zhu2a507102017-02-20 17:07:36 +0800972 mutex_lock(&pp_handle->pp_lock);
973 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
974 mutex_unlock(&pp_handle->pp_lock);
975
976 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400977}
978
Alex Deucher597be302016-10-07 13:52:43 -0400979static struct amd_vce_state*
980pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
981{
982 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800983 struct pp_instance *pp_handle = (struct pp_instance *)handle;
984 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -0400985
Rex Zhu1c863802016-12-28 19:43:23 +0800986 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -0400987
Rex Zhu1c863802016-12-28 19:43:23 +0800988 if (ret != 0)
989 return NULL;
990
991 hwmgr = pp_handle->hwmgr;
992
993 if (hwmgr && idx < hwmgr->num_vce_state_tables)
994 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -0400995 return NULL;
996}
997
Eric Huang34bb2732016-09-12 16:17:44 -0400998static int pp_dpm_reset_power_profile_state(void *handle,
999 struct amd_pp_profile *request)
1000{
1001 struct pp_hwmgr *hwmgr;
1002 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1003
1004 if (!request || pp_check(pp_handle))
1005 return -EINVAL;
1006
1007 hwmgr = pp_handle->hwmgr;
1008
1009 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1010 pr_info("%s was not implemented.\n", __func__);
1011 return 0;
1012 }
1013
1014 if (request->type == AMD_PP_GFX_PROFILE) {
1015 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1016 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1017 &hwmgr->gfx_power_profile);
1018 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1019 hwmgr->compute_power_profile =
1020 hwmgr->default_compute_power_profile;
1021 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1022 &hwmgr->compute_power_profile);
1023 } else
1024 return -EINVAL;
1025}
1026
1027static int pp_dpm_get_power_profile_state(void *handle,
1028 struct amd_pp_profile *query)
1029{
1030 struct pp_hwmgr *hwmgr;
1031 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1032
1033 if (!query || pp_check(pp_handle))
1034 return -EINVAL;
1035
1036 hwmgr = pp_handle->hwmgr;
1037
1038 if (query->type == AMD_PP_GFX_PROFILE)
1039 memcpy(query, &hwmgr->gfx_power_profile,
1040 sizeof(struct amd_pp_profile));
1041 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1042 memcpy(query, &hwmgr->compute_power_profile,
1043 sizeof(struct amd_pp_profile));
1044 else
1045 return -EINVAL;
1046
1047 return 0;
1048}
1049
1050static int pp_dpm_set_power_profile_state(void *handle,
1051 struct amd_pp_profile *request)
1052{
1053 struct pp_hwmgr *hwmgr;
1054 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1055 int ret = -1;
1056
1057 if (!request || pp_check(pp_handle))
1058 return -EINVAL;
1059
1060 hwmgr = pp_handle->hwmgr;
1061
1062 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1063 pr_info("%s was not implemented.\n", __func__);
1064 return 0;
1065 }
1066
1067 if (request->min_sclk ||
1068 request->min_mclk ||
1069 request->activity_threshold ||
1070 request->up_hyst ||
1071 request->down_hyst) {
1072 if (request->type == AMD_PP_GFX_PROFILE)
1073 memcpy(&hwmgr->gfx_power_profile, request,
1074 sizeof(struct amd_pp_profile));
1075 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1076 memcpy(&hwmgr->compute_power_profile, request,
1077 sizeof(struct amd_pp_profile));
1078 else
1079 return -EINVAL;
1080
1081 if (request->type == hwmgr->current_power_profile)
1082 ret = hwmgr->hwmgr_func->set_power_profile_state(
1083 hwmgr,
1084 request);
1085 } else {
1086 /* set power profile if it exists */
1087 switch (request->type) {
1088 case AMD_PP_GFX_PROFILE:
1089 ret = hwmgr->hwmgr_func->set_power_profile_state(
1090 hwmgr,
1091 &hwmgr->gfx_power_profile);
1092 break;
1093 case AMD_PP_COMPUTE_PROFILE:
1094 ret = hwmgr->hwmgr_func->set_power_profile_state(
1095 hwmgr,
1096 &hwmgr->compute_power_profile);
1097 break;
1098 default:
1099 return -EINVAL;
1100 }
1101 }
1102
1103 if (!ret)
1104 hwmgr->current_power_profile = request->type;
1105
1106 return 0;
1107}
1108
1109static int pp_dpm_switch_power_profile(void *handle,
1110 enum amd_pp_profile_type type)
1111{
1112 struct pp_hwmgr *hwmgr;
1113 struct amd_pp_profile request = {0};
1114 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1115
1116 if (pp_check(pp_handle))
1117 return -EINVAL;
1118
1119 hwmgr = pp_handle->hwmgr;
1120
1121 if (hwmgr->current_power_profile != type) {
1122 request.type = type;
1123 pp_dpm_set_power_profile_state(handle, &request);
1124 }
1125
1126 return 0;
1127}
1128
Alex Deucher1f7371b2015-12-02 17:46:21 -05001129const struct amd_powerplay_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001130 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001131 .load_firmware = pp_dpm_load_fw,
1132 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1133 .force_performance_level = pp_dpm_force_performance_level,
1134 .get_performance_level = pp_dpm_get_performance_level,
1135 .get_current_power_state = pp_dpm_get_current_power_state,
1136 .get_sclk = pp_dpm_get_sclk,
1137 .get_mclk = pp_dpm_get_mclk,
1138 .powergate_vce = pp_dpm_powergate_vce,
1139 .powergate_uvd = pp_dpm_powergate_uvd,
1140 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001141 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1142 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1143 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1144 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001145 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001146 .get_pp_num_states = pp_dpm_get_pp_num_states,
1147 .get_pp_table = pp_dpm_get_pp_table,
1148 .set_pp_table = pp_dpm_set_pp_table,
1149 .force_clock_level = pp_dpm_force_clock_level,
1150 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001151 .get_sclk_od = pp_dpm_get_sclk_od,
1152 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001153 .get_mclk_od = pp_dpm_get_mclk_od,
1154 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001155 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001156 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001157 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1158 .get_power_profile_state = pp_dpm_get_power_profile_state,
1159 .set_power_profile_state = pp_dpm_set_power_profile_state,
1160 .switch_power_profile = pp_dpm_switch_power_profile,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001161};
1162
Rex Zhu1c863802016-12-28 19:43:23 +08001163int amd_powerplay_create(struct amd_pp_init *pp_init,
1164 void **handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001165{
Rex Zhu1c863802016-12-28 19:43:23 +08001166 struct pp_instance *instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001167
Rex Zhu1c863802016-12-28 19:43:23 +08001168 if (pp_init == NULL || handle == NULL)
1169 return -EINVAL;
1170
1171 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
1172 if (instance == NULL)
Jammy Zhouac885b32015-07-21 17:43:02 +08001173 return -ENOMEM;
1174
Rex Zhu1c863802016-12-28 19:43:23 +08001175 instance->pp_valid = PP_VALID;
1176 instance->chip_family = pp_init->chip_family;
1177 instance->chip_id = pp_init->chip_id;
1178 instance->pm_en = pp_init->pm_en;
1179 instance->feature_mask = pp_init->feature_mask;
1180 instance->device = pp_init->device;
Rex Zhu2a507102017-02-20 17:07:36 +08001181 mutex_init(&instance->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001182 *handle = instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001183 return 0;
1184}
1185
Rex Zhu1c863802016-12-28 19:43:23 +08001186int amd_powerplay_destroy(void *handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001187{
1188 struct pp_instance *instance = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +08001189
Rex Zhu1c863802016-12-28 19:43:23 +08001190 if (instance->pm_en) {
1191 kfree(instance->eventmgr);
1192 kfree(instance->hwmgr);
1193 instance->hwmgr = NULL;
1194 instance->eventmgr = NULL;
Rex Zhuba5f8842016-10-27 15:29:57 +08001195 }
Jammy Zhou3bace352015-07-21 21:18:15 +08001196
Rex Zhu1c863802016-12-28 19:43:23 +08001197 kfree(instance->smu_mgr);
1198 instance->smu_mgr = NULL;
1199 kfree(instance);
1200 instance = NULL;
Alex Deucher1f7371b2015-12-02 17:46:21 -05001201 return 0;
1202}
Rex Zhu7fb72a12015-11-19 13:35:30 +08001203
Eric Huang4dcf9e62016-06-01 17:08:07 -04001204int amd_powerplay_reset(void *handle)
1205{
1206 struct pp_instance *instance = (struct pp_instance *)handle;
1207 struct pp_eventmgr *eventmgr;
1208 struct pem_event_data event_data = { {0} };
1209 int ret;
1210
Rex Zhu1c863802016-12-28 19:43:23 +08001211 if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1212 return PP_DPM_DISABLED;
1213
1214 ret = pp_check(instance);
1215 if (ret != 0)
1216 return ret;
1217
1218 ret = pp_hw_fini(handle);
1219 if (ret)
1220 return ret;
1221
1222 ret = hwmgr_hw_init(instance);
1223 if (ret)
1224 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001225
1226 eventmgr = instance->eventmgr;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001227
Rex Zhu1c863802016-12-28 19:43:23 +08001228 if (eventmgr->pp_eventmgr_init == NULL)
1229 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001230
1231 ret = eventmgr->pp_eventmgr_init(eventmgr);
1232 if (ret)
1233 return ret;
1234
1235 return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
1236}
1237
Rex Zhu7fb72a12015-11-19 13:35:30 +08001238/* export this function to DAL */
1239
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001240int amd_powerplay_display_configuration_change(void *handle,
1241 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001242{
1243 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001244 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1245 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001246
Rex Zhu1c863802016-12-28 19:43:23 +08001247 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001248
Rex Zhu1c863802016-12-28 19:43:23 +08001249 if (ret != 0)
1250 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001251
Rex Zhu1c863802016-12-28 19:43:23 +08001252 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +08001253 mutex_lock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001254 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhu2a507102017-02-20 17:07:36 +08001255 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001256 return 0;
1257}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001258
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001259int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001260 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001261{
1262 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001263 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1264 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001265
Rex Zhu1c863802016-12-28 19:43:23 +08001266 ret = pp_check(pp_handle);
1267
1268 if (ret != 0)
1269 return ret;
1270
1271 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001272
1273 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001274 return -EINVAL;
1275
Rex Zhu2a507102017-02-20 17:07:36 +08001276 mutex_lock(&pp_handle->pp_lock);
1277 ret = phm_get_dal_power_level(hwmgr, output);
1278 mutex_unlock(&pp_handle->pp_lock);
1279 return ret;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001280}
Rex Zhue273b042015-12-07 18:44:23 +08001281
1282int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001283 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001284{
Rex Zhue273b042015-12-07 18:44:23 +08001285 struct amd_pp_simple_clock_info simple_clocks;
1286 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001287 struct pp_hwmgr *hwmgr;
1288 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1289 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001290
Rex Zhu1c863802016-12-28 19:43:23 +08001291 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001292
Rex Zhu1c863802016-12-28 19:43:23 +08001293 if (ret != 0)
1294 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001295
Rex Zhu1c863802016-12-28 19:43:23 +08001296 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001297
Rex Zhu2a507102017-02-20 17:07:36 +08001298 mutex_lock(&pp_handle->pp_lock);
1299
Rex Zhue273b042015-12-07 18:44:23 +08001300 phm_get_dal_power_level(hwmgr, &simple_clocks);
1301
Rex Zhu2a507102017-02-20 17:07:36 +08001302 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1303 PHM_PlatformCaps_PowerContainment))
1304 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1305 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1306 else
1307 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1308 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1309
1310 if (ret != 0) {
1311 pr_info("Error in phm_get_clock_info \n");
1312 mutex_unlock(&pp_handle->pp_lock);
1313 return -EINVAL;
Rex Zhue273b042015-12-07 18:44:23 +08001314 }
1315
1316 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1317 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1318 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1319 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1320 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1321 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1322
1323 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1324 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1325
1326 clocks->max_clocks_state = simple_clocks.level;
1327
1328 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1329 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1330 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1331 }
Rex Zhu2a507102017-02-20 17:07:36 +08001332 mutex_unlock(&pp_handle->pp_lock);
Rex Zhue273b042015-12-07 18:44:23 +08001333 return 0;
Rex Zhue273b042015-12-07 18:44:23 +08001334}
1335
1336int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1337{
Rex Zhu1c863802016-12-28 19:43:23 +08001338 struct pp_hwmgr *hwmgr;
1339 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1340 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001341
Rex Zhu1c863802016-12-28 19:43:23 +08001342 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001343
Rex Zhu1c863802016-12-28 19:43:23 +08001344 if (ret != 0)
1345 return ret;
1346
1347 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001348
1349 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001350 return -EINVAL;
1351
Rex Zhu2a507102017-02-20 17:07:36 +08001352 mutex_lock(&pp_handle->pp_lock);
1353 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1354 mutex_unlock(&pp_handle->pp_lock);
1355 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001356}
1357
Eric Huangd0187722017-03-06 13:13:48 -05001358int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1359 enum amd_pp_clock_type type,
1360 struct pp_clock_levels_with_latency *clocks)
1361{
1362 struct pp_hwmgr *hwmgr;
1363 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1364 int ret = 0;
1365
1366 ret = pp_check(pp_handle);
1367 if (ret != 0)
1368 return ret;
1369
1370 if (!clocks)
1371 return -EINVAL;
1372
1373 mutex_lock(&pp_handle->pp_lock);
1374 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1375 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1376 mutex_unlock(&pp_handle->pp_lock);
1377 return ret;
1378}
1379
1380int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1381 enum amd_pp_clock_type type,
1382 struct pp_clock_levels_with_voltage *clocks)
1383{
1384 struct pp_hwmgr *hwmgr;
1385 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1386 int ret = 0;
1387
1388 ret = pp_check(pp_handle);
1389 if (ret != 0)
1390 return ret;
1391
1392 if (!clocks)
1393 return -EINVAL;
1394
1395 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1396
1397 mutex_lock(&pp_handle->pp_lock);
1398
1399 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1400
1401 mutex_unlock(&pp_handle->pp_lock);
1402 return ret;
1403}
1404
1405int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1406 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1407{
1408 struct pp_hwmgr *hwmgr;
1409 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1410 int ret = 0;
1411
1412 ret = pp_check(pp_handle);
1413 if (ret != 0)
1414 return ret;
1415
1416 if (!wm_with_clock_ranges)
1417 return -EINVAL;
1418
1419 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1420
1421 mutex_lock(&pp_handle->pp_lock);
1422 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1423 wm_with_clock_ranges);
1424 mutex_unlock(&pp_handle->pp_lock);
1425
1426 return ret;
1427}
1428
1429int amd_powerplay_display_clock_voltage_request(void *handle,
1430 struct pp_display_clock_request *clock)
1431{
1432 struct pp_hwmgr *hwmgr;
1433 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1434 int ret = 0;
1435
1436 ret = pp_check(pp_handle);
1437 if (ret != 0)
1438 return ret;
1439
1440 if (!clock)
1441 return -EINVAL;
1442
1443 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1444
1445 mutex_lock(&pp_handle->pp_lock);
1446 ret = phm_display_clock_voltage_request(hwmgr, clock);
1447 mutex_unlock(&pp_handle->pp_lock);
1448
1449 return ret;
1450}
1451
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001452int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1453 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001454{
Rex Zhue273b042015-12-07 18:44:23 +08001455 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001456 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1457 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001458
Rex Zhu1c863802016-12-28 19:43:23 +08001459 ret = pp_check(pp_handle);
1460
1461 if (ret != 0)
1462 return ret;
1463
1464 hwmgr = pp_handle->hwmgr;
1465
Rex Zhufa9e6992015-12-29 13:56:03 +08001466 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001467 return -EINVAL;
1468
Rex Zhu2a507102017-02-20 17:07:36 +08001469 mutex_lock(&pp_handle->pp_lock);
1470
Rex Zhue273b042015-12-07 18:44:23 +08001471 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001472 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001473
Rex Zhu2a507102017-02-20 17:07:36 +08001474 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001475 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001476}
1477