blob: f73e80c4bf3374b136a816f4c4dc72ccca05e62d [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
Huang Rui4573f0f2017-04-10 14:40:51 +0800254 if (ret == PP_DPM_DISABLED)
255 return 0;
256 else if (ret != 0)
Rex Zhu1c863802016-12-28 19:43:23 +0800257 return ret;
258
Rex Zhu577bbe02015-08-28 12:56:43 +0800259 eventmgr = pp_handle->eventmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800260 pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
Rex Zhuba5f8842016-10-27 15:29:57 +0800261
Alex Deucher1f7371b2015-12-02 17:46:21 -0500262 return 0;
263}
264
265static int pp_resume(void *handle)
266{
Rex Zhu577bbe02015-08-28 12:56:43 +0800267 struct pp_eventmgr *eventmgr;
268 struct pem_event_data event_data = { {0} };
Rex Zhue0b71a72015-12-29 10:25:19 +0800269 struct pp_smumgr *smumgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800270 int ret, ret1;
271 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800272
Rex Zhu1c863802016-12-28 19:43:23 +0800273 ret1 = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800274
Rex Zhu1c863802016-12-28 19:43:23 +0800275 if (ret1 != 0 && ret1 != PP_DPM_DISABLED)
276 return ret1;
277
Rex Zhue0b71a72015-12-29 10:25:19 +0800278 smumgr = pp_handle->smu_mgr;
279
Rex Zhu1c863802016-12-28 19:43:23 +0800280 if (smumgr->smumgr_funcs->start_smu == NULL)
Rex Zhue0b71a72015-12-29 10:25:19 +0800281 return -EINVAL;
282
283 ret = smumgr->smumgr_funcs->start_smu(smumgr);
284 if (ret) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800285 pr_err("smc start failed\n");
Rex Zhue0b71a72015-12-29 10:25:19 +0800286 smumgr->smumgr_funcs->smu_fini(smumgr);
287 return ret;
288 }
289
Rex Zhu1c863802016-12-28 19:43:23 +0800290 if (ret1 == PP_DPM_DISABLED)
Monk Liu8fdf2692017-01-25 15:55:30 +0800291 return 0;
Rex Zhu1c863802016-12-28 19:43:23 +0800292
Rex Zhu577bbe02015-08-28 12:56:43 +0800293 eventmgr = pp_handle->eventmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800294
295 pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
Rex Zhue0b71a72015-12-29 10:25:19 +0800296
Alex Deucher1f7371b2015-12-02 17:46:21 -0500297 return 0;
298}
299
300const struct amd_ip_funcs pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400301 .name = "powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500302 .early_init = pp_early_init,
303 .late_init = NULL,
304 .sw_init = pp_sw_init,
305 .sw_fini = pp_sw_fini,
306 .hw_init = pp_hw_init,
307 .hw_fini = pp_hw_fini,
308 .suspend = pp_suspend,
309 .resume = pp_resume,
310 .is_idle = pp_is_idle,
311 .wait_for_idle = pp_wait_for_idle,
312 .soft_reset = pp_sw_reset,
Rex Zhu465f96e2016-09-18 16:52:03 +0800313 .set_clockgating_state = NULL,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500314 .set_powergating_state = pp_set_powergating_state,
315};
316
317static int pp_dpm_load_fw(void *handle)
318{
319 return 0;
320}
321
322static int pp_dpm_fw_loading_complete(void *handle)
323{
324 return 0;
325}
326
327static int pp_dpm_force_performance_level(void *handle,
328 enum amd_dpm_forced_level level)
329{
Rex Zhu577bbe02015-08-28 12:56:43 +0800330 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800331 struct pp_instance *pp_handle = (struct pp_instance *)handle;
332 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800333
Rex Zhu1c863802016-12-28 19:43:23 +0800334 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800335
Rex Zhu1c863802016-12-28 19:43:23 +0800336 if (ret != 0)
337 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800338
339 hwmgr = pp_handle->hwmgr;
340
Rex Zhu7383bcb2016-03-30 11:35:50 +0800341 if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800342 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800343 return 0;
344 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800345
Rex Zhu2a507102017-02-20 17:07:36 +0800346 mutex_lock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800347 hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
Rex Zhu2a507102017-02-20 17:07:36 +0800348 mutex_unlock(&pp_handle->pp_lock);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500349 return 0;
350}
Rex Zhu577bbe02015-08-28 12:56:43 +0800351
Alex Deucher1f7371b2015-12-02 17:46:21 -0500352static enum amd_dpm_forced_level pp_dpm_get_performance_level(
353 void *handle)
354{
Rex Zhu577bbe02015-08-28 12:56:43 +0800355 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800356 struct pp_instance *pp_handle = (struct pp_instance *)handle;
357 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800358 enum amd_dpm_forced_level level;
Rex Zhu577bbe02015-08-28 12:56:43 +0800359
Rex Zhu1c863802016-12-28 19:43:23 +0800360 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800361
Rex Zhu1c863802016-12-28 19:43:23 +0800362 if (ret != 0)
363 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800364
Rex Zhu1c863802016-12-28 19:43:23 +0800365 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800366 mutex_lock(&pp_handle->pp_lock);
367 level = hwmgr->dpm_level;
368 mutex_unlock(&pp_handle->pp_lock);
369 return level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500370}
Rex Zhu577bbe02015-08-28 12:56:43 +0800371
Alex Deucher1f7371b2015-12-02 17:46:21 -0500372static int pp_dpm_get_sclk(void *handle, bool low)
373{
Rex Zhu577bbe02015-08-28 12:56:43 +0800374 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800375 struct pp_instance *pp_handle = (struct pp_instance *)handle;
376 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800377
Rex Zhu1c863802016-12-28 19:43:23 +0800378 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800379
Rex Zhu1c863802016-12-28 19:43:23 +0800380 if (ret != 0)
381 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800382
Rex Zhu1c863802016-12-28 19:43:23 +0800383 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800384
385 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800386 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800387 return 0;
388 }
Rex Zhu2a507102017-02-20 17:07:36 +0800389 mutex_lock(&pp_handle->pp_lock);
390 ret = hwmgr->hwmgr_func->get_sclk(hwmgr, low);
391 mutex_unlock(&pp_handle->pp_lock);
392 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500393}
Rex Zhu577bbe02015-08-28 12:56:43 +0800394
Alex Deucher1f7371b2015-12-02 17:46:21 -0500395static int pp_dpm_get_mclk(void *handle, bool low)
396{
Rex Zhu577bbe02015-08-28 12:56:43 +0800397 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800398 struct pp_instance *pp_handle = (struct pp_instance *)handle;
399 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800400
Rex Zhu1c863802016-12-28 19:43:23 +0800401 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800402
Rex Zhu1c863802016-12-28 19:43:23 +0800403 if (ret != 0)
404 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800405
Rex Zhu1c863802016-12-28 19:43:23 +0800406 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800407
408 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800409 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800410 return 0;
411 }
Rex Zhu2a507102017-02-20 17:07:36 +0800412 mutex_lock(&pp_handle->pp_lock);
413 ret = hwmgr->hwmgr_func->get_mclk(hwmgr, low);
414 mutex_unlock(&pp_handle->pp_lock);
415 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500416}
Rex Zhu577bbe02015-08-28 12:56:43 +0800417
Alex Deucher1f7371b2015-12-02 17:46:21 -0500418static int pp_dpm_powergate_vce(void *handle, bool gate)
419{
Rex Zhu577bbe02015-08-28 12:56:43 +0800420 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800421 struct pp_instance *pp_handle = (struct pp_instance *)handle;
422 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800423
Rex Zhu1c863802016-12-28 19:43:23 +0800424 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800425
Rex Zhu1c863802016-12-28 19:43:23 +0800426 if (ret != 0)
427 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800428
Rex Zhu1c863802016-12-28 19:43:23 +0800429 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800430
431 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800432 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800433 return 0;
434 }
Rex Zhu2a507102017-02-20 17:07:36 +0800435 mutex_lock(&pp_handle->pp_lock);
436 ret = hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
437 mutex_unlock(&pp_handle->pp_lock);
438 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500439}
Rex Zhu577bbe02015-08-28 12:56:43 +0800440
Alex Deucher1f7371b2015-12-02 17:46:21 -0500441static int pp_dpm_powergate_uvd(void *handle, bool gate)
442{
Rex Zhu577bbe02015-08-28 12:56:43 +0800443 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800444 struct pp_instance *pp_handle = (struct pp_instance *)handle;
445 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800446
Rex Zhu1c863802016-12-28 19:43:23 +0800447 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800448
Rex Zhu1c863802016-12-28 19:43:23 +0800449 if (ret != 0)
450 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800451
Rex Zhu1c863802016-12-28 19:43:23 +0800452 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800453
454 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800455 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800456 return 0;
457 }
Rex Zhu2a507102017-02-20 17:07:36 +0800458 mutex_lock(&pp_handle->pp_lock);
459 ret = hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
460 mutex_unlock(&pp_handle->pp_lock);
461 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800462}
463
464static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state)
465{
466 switch (state) {
467 case POWER_STATE_TYPE_BATTERY:
468 return PP_StateUILabel_Battery;
469 case POWER_STATE_TYPE_BALANCED:
470 return PP_StateUILabel_Balanced;
471 case POWER_STATE_TYPE_PERFORMANCE:
472 return PP_StateUILabel_Performance;
473 default:
474 return PP_StateUILabel_None;
475 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500476}
477
Baoyou Xief8a4c112016-09-30 17:58:42 +0800478static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
479 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500480{
Rex Zhu577bbe02015-08-28 12:56:43 +0800481 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800482 struct pem_event_data data = { {0} };
Rex Zhu1c863802016-12-28 19:43:23 +0800483 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800484
Rex Zhu1c863802016-12-28 19:43:23 +0800485 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800486
Rex Zhu1c863802016-12-28 19:43:23 +0800487 if (ret != 0)
488 return ret;
Rex Zhu2a507102017-02-20 17:07:36 +0800489 mutex_lock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800490 switch (event_id) {
491 case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
492 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
493 break;
494 case AMD_PP_EVENT_ENABLE_USER_STATE:
495 {
496 enum amd_pm_state_type ps;
497
Dan Carpenter99147e62017-04-03 21:42:42 +0300498 if (input == NULL) {
499 ret = -EINVAL;
500 break;
501 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800502 ps = *(unsigned long *)input;
503
504 data.requested_ui_label = power_state_convert(ps);
505 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
Rex Zhudc26a2a2016-02-25 17:16:52 +0800506 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800507 }
Rex Zhudc26a2a2016-02-25 17:16:52 +0800508 case AMD_PP_EVENT_COMPLETE_INIT:
509 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
510 break;
Eric Huang428bafa2016-05-12 14:51:21 -0400511 case AMD_PP_EVENT_READJUST_POWER_STATE:
Eric Huang428bafa2016-05-12 14:51:21 -0400512 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
513 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800514 default:
515 break;
516 }
Rex Zhu2a507102017-02-20 17:07:36 +0800517 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu577bbe02015-08-28 12:56:43 +0800518 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500519}
Rex Zhu577bbe02015-08-28 12:56:43 +0800520
Baoyou Xief8a4c112016-09-30 17:58:42 +0800521static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500522{
Rex Zhu577bbe02015-08-28 12:56:43 +0800523 struct pp_hwmgr *hwmgr;
524 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800525 struct pp_instance *pp_handle = (struct pp_instance *)handle;
526 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800527 enum amd_pm_state_type pm_type;
Rex Zhu577bbe02015-08-28 12:56:43 +0800528
Rex Zhu1c863802016-12-28 19:43:23 +0800529 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800530
Rex Zhu1c863802016-12-28 19:43:23 +0800531 if (ret != 0)
532 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800533
Rex Zhu1c863802016-12-28 19:43:23 +0800534 hwmgr = pp_handle->hwmgr;
535
536 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800537 return -EINVAL;
538
Rex Zhu2a507102017-02-20 17:07:36 +0800539 mutex_lock(&pp_handle->pp_lock);
540
Rex Zhu577bbe02015-08-28 12:56:43 +0800541 state = hwmgr->current_ps;
542
543 switch (state->classification.ui_label) {
544 case PP_StateUILabel_Battery:
Rex Zhu2a507102017-02-20 17:07:36 +0800545 pm_type = POWER_STATE_TYPE_BATTERY;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300546 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800547 case PP_StateUILabel_Balanced:
Rex Zhu2a507102017-02-20 17:07:36 +0800548 pm_type = POWER_STATE_TYPE_BALANCED;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300549 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800550 case PP_StateUILabel_Performance:
Rex Zhu2a507102017-02-20 17:07:36 +0800551 pm_type = POWER_STATE_TYPE_PERFORMANCE;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300552 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800553 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500554 if (state->classification.flags & PP_StateClassificationFlag_Boot)
Rex Zhu2a507102017-02-20 17:07:36 +0800555 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
Eric Huangf3898ea2015-12-11 16:24:34 -0500556 else
Rex Zhu2a507102017-02-20 17:07:36 +0800557 pm_type = POWER_STATE_TYPE_DEFAULT;
Dan Carpenter0f987cd2017-04-03 21:41:47 +0300558 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800559 }
Rex Zhu2a507102017-02-20 17:07:36 +0800560 mutex_unlock(&pp_handle->pp_lock);
561
562 return pm_type;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500563}
Rex Zhu577bbe02015-08-28 12:56:43 +0800564
Rex Zhucac9a192015-10-16 11:48:21 +0800565static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
566{
567 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800568 struct pp_instance *pp_handle = (struct pp_instance *)handle;
569 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800570
Rex Zhu1c863802016-12-28 19:43:23 +0800571 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800572
Rex Zhu1c863802016-12-28 19:43:23 +0800573 if (ret != 0)
574 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800575
Rex Zhu1c863802016-12-28 19:43:23 +0800576 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800577
578 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800579 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800580 return 0;
581 }
Rex Zhu2a507102017-02-20 17:07:36 +0800582 mutex_lock(&pp_handle->pp_lock);
583 ret = hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
584 mutex_unlock(&pp_handle->pp_lock);
585 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800586}
587
588static int pp_dpm_get_fan_control_mode(void *handle)
589{
590 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800591 struct pp_instance *pp_handle = (struct pp_instance *)handle;
592 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800593
Rex Zhu1c863802016-12-28 19:43:23 +0800594 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800595
Rex Zhu1c863802016-12-28 19:43:23 +0800596 if (ret != 0)
597 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800598
Rex Zhu1c863802016-12-28 19:43:23 +0800599 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800600
601 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800602 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800603 return 0;
604 }
Rex Zhu2a507102017-02-20 17:07:36 +0800605 mutex_lock(&pp_handle->pp_lock);
606 ret = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
607 mutex_unlock(&pp_handle->pp_lock);
608 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800609}
610
611static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
612{
613 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800614 struct pp_instance *pp_handle = (struct pp_instance *)handle;
615 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800616
Rex Zhu1c863802016-12-28 19:43:23 +0800617 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800618
Rex Zhu1c863802016-12-28 19:43:23 +0800619 if (ret != 0)
620 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800621
Rex Zhu1c863802016-12-28 19:43:23 +0800622 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800623
624 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800625 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800626 return 0;
627 }
Rex Zhu2a507102017-02-20 17:07:36 +0800628 mutex_lock(&pp_handle->pp_lock);
629 ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
630 mutex_unlock(&pp_handle->pp_lock);
631 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800632}
633
634static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
635{
636 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800637 struct pp_instance *pp_handle = (struct pp_instance *)handle;
638 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800639
Rex Zhu1c863802016-12-28 19:43:23 +0800640 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800641
Rex Zhu1c863802016-12-28 19:43:23 +0800642 if (ret != 0)
643 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800644
Rex Zhu1c863802016-12-28 19:43:23 +0800645 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800646
647 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800648 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800649 return 0;
650 }
Rex Zhucac9a192015-10-16 11:48:21 +0800651
Rex Zhu2a507102017-02-20 17:07:36 +0800652 mutex_lock(&pp_handle->pp_lock);
653 ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
654 mutex_unlock(&pp_handle->pp_lock);
655 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800656}
657
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300658static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
659{
660 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800661 struct pp_instance *pp_handle = (struct pp_instance *)handle;
662 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300663
Rex Zhu1c863802016-12-28 19:43:23 +0800664 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300665
Rex Zhu1c863802016-12-28 19:43:23 +0800666 if (ret != 0)
667 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300668
Rex Zhu1c863802016-12-28 19:43:23 +0800669 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300670
671 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
672 return -EINVAL;
673
Rex Zhu2a507102017-02-20 17:07:36 +0800674 mutex_lock(&pp_handle->pp_lock);
675 ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
676 mutex_unlock(&pp_handle->pp_lock);
677 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300678}
679
Rex Zhucac9a192015-10-16 11:48:21 +0800680static int pp_dpm_get_temperature(void *handle)
681{
682 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800683 struct pp_instance *pp_handle = (struct pp_instance *)handle;
684 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800685
Rex Zhu1c863802016-12-28 19:43:23 +0800686 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800687
Rex Zhu1c863802016-12-28 19:43:23 +0800688 if (ret != 0)
689 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800690
Rex Zhu1c863802016-12-28 19:43:23 +0800691 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800692
693 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800694 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800695 return 0;
696 }
Rex Zhu2a507102017-02-20 17:07:36 +0800697 mutex_lock(&pp_handle->pp_lock);
698 ret = hwmgr->hwmgr_func->get_temperature(hwmgr);
699 mutex_unlock(&pp_handle->pp_lock);
700 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800701}
Rex Zhu577bbe02015-08-28 12:56:43 +0800702
Eric Huangf3898ea2015-12-11 16:24:34 -0500703static int pp_dpm_get_pp_num_states(void *handle,
704 struct pp_states_info *data)
705{
706 struct pp_hwmgr *hwmgr;
707 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800708 struct pp_instance *pp_handle = (struct pp_instance *)handle;
709 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500710
Rex Zhu1c863802016-12-28 19:43:23 +0800711 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500712
Rex Zhu1c863802016-12-28 19:43:23 +0800713 if (ret != 0)
714 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500715
Rex Zhu1c863802016-12-28 19:43:23 +0800716 hwmgr = pp_handle->hwmgr;
717
718 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500719 return -EINVAL;
720
Rex Zhu2a507102017-02-20 17:07:36 +0800721 mutex_lock(&pp_handle->pp_lock);
722
Eric Huangf3898ea2015-12-11 16:24:34 -0500723 data->nums = hwmgr->num_ps;
724
725 for (i = 0; i < hwmgr->num_ps; i++) {
726 struct pp_power_state *state = (struct pp_power_state *)
727 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
728 switch (state->classification.ui_label) {
729 case PP_StateUILabel_Battery:
730 data->states[i] = POWER_STATE_TYPE_BATTERY;
731 break;
732 case PP_StateUILabel_Balanced:
733 data->states[i] = POWER_STATE_TYPE_BALANCED;
734 break;
735 case PP_StateUILabel_Performance:
736 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
737 break;
738 default:
739 if (state->classification.flags & PP_StateClassificationFlag_Boot)
740 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
741 else
742 data->states[i] = POWER_STATE_TYPE_DEFAULT;
743 }
744 }
Rex Zhu2a507102017-02-20 17:07:36 +0800745 mutex_unlock(&pp_handle->pp_lock);
Eric Huangf3898ea2015-12-11 16:24:34 -0500746 return 0;
747}
748
749static int pp_dpm_get_pp_table(void *handle, char **table)
750{
751 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800752 struct pp_instance *pp_handle = (struct pp_instance *)handle;
753 int ret = 0;
Rex Zhu2a507102017-02-20 17:07:36 +0800754 int size = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500755
Rex Zhu1c863802016-12-28 19:43:23 +0800756 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500757
Rex Zhu1c863802016-12-28 19:43:23 +0800758 if (ret != 0)
759 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500760
Rex Zhu1c863802016-12-28 19:43:23 +0800761 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800762
Eric Huang4dcf9e62016-06-01 17:08:07 -0400763 if (!hwmgr->soft_pp_table)
764 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500765
Rex Zhu2a507102017-02-20 17:07:36 +0800766 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400767 *table = (char *)hwmgr->soft_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800768 size = hwmgr->soft_pp_table_size;
769 mutex_unlock(&pp_handle->pp_lock);
770 return size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500771}
772
773static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
774{
775 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800776 struct pp_instance *pp_handle = (struct pp_instance *)handle;
777 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500778
Rex Zhu1c863802016-12-28 19:43:23 +0800779 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500780
Rex Zhu1c863802016-12-28 19:43:23 +0800781 if (ret != 0)
782 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500783
Rex Zhu1c863802016-12-28 19:43:23 +0800784 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +0800785 mutex_lock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400786 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000787 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
788 hwmgr->soft_pp_table_size,
789 GFP_KERNEL);
Rex Zhu2a507102017-02-20 17:07:36 +0800790 if (!hwmgr->hardcode_pp_table) {
791 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400792 return -ENOMEM;
Rex Zhu2a507102017-02-20 17:07:36 +0800793 }
Rex Zhu7383bcb2016-03-30 11:35:50 +0800794 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500795
Eric Huang4dcf9e62016-06-01 17:08:07 -0400796 memcpy(hwmgr->hardcode_pp_table, buf, size);
797
798 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
Rex Zhu2a507102017-02-20 17:07:36 +0800799 mutex_unlock(&pp_handle->pp_lock);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400800
Eric Huangdd4bdf32017-03-01 15:49:31 -0500801 ret = amd_powerplay_reset(handle);
802 if (ret)
803 return ret;
804
805 if (hwmgr->hwmgr_func->avfs_control) {
806 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
807 if (ret)
808 return ret;
809 }
810
811 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500812}
813
814static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400815 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500816{
817 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800818 struct pp_instance *pp_handle = (struct pp_instance *)handle;
819 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500820
Rex Zhu1c863802016-12-28 19:43:23 +0800821 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500822
Rex Zhu1c863802016-12-28 19:43:23 +0800823 if (ret != 0)
824 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500825
Rex Zhu1c863802016-12-28 19:43:23 +0800826 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800827
828 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800829 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800830 return 0;
831 }
Rex Zhu2a507102017-02-20 17:07:36 +0800832 mutex_lock(&pp_handle->pp_lock);
833 hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
834 mutex_unlock(&pp_handle->pp_lock);
835 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500836}
837
838static int pp_dpm_print_clock_levels(void *handle,
839 enum pp_clock_type type, char *buf)
840{
841 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800842 struct pp_instance *pp_handle = (struct pp_instance *)handle;
843 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500844
Rex Zhu1c863802016-12-28 19:43:23 +0800845 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500846
Rex Zhu1c863802016-12-28 19:43:23 +0800847 if (ret != 0)
848 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500849
Rex Zhu1c863802016-12-28 19:43:23 +0800850 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500851
Rex Zhu7383bcb2016-03-30 11:35:50 +0800852 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800853 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800854 return 0;
855 }
Rex Zhu2a507102017-02-20 17:07:36 +0800856 mutex_lock(&pp_handle->pp_lock);
857 ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
858 mutex_unlock(&pp_handle->pp_lock);
859 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500860}
861
Eric Huang428bafa2016-05-12 14:51:21 -0400862static int pp_dpm_get_sclk_od(void *handle)
863{
864 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800865 struct pp_instance *pp_handle = (struct pp_instance *)handle;
866 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400867
Rex Zhu1c863802016-12-28 19:43:23 +0800868 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400869
Rex Zhu1c863802016-12-28 19:43:23 +0800870 if (ret != 0)
871 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400872
Rex Zhu1c863802016-12-28 19:43:23 +0800873 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400874
875 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800876 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400877 return 0;
878 }
Rex Zhu2a507102017-02-20 17:07:36 +0800879 mutex_lock(&pp_handle->pp_lock);
880 ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr);
881 mutex_unlock(&pp_handle->pp_lock);
882 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400883}
884
885static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
886{
887 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800888 struct pp_instance *pp_handle = (struct pp_instance *)handle;
889 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400890
Rex Zhu1c863802016-12-28 19:43:23 +0800891 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400892
Rex Zhu1c863802016-12-28 19:43:23 +0800893 if (ret != 0)
894 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400895
Rex Zhu1c863802016-12-28 19:43:23 +0800896 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400897
898 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800899 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400900 return 0;
901 }
902
Rex Zhu2a507102017-02-20 17:07:36 +0800903 mutex_lock(&pp_handle->pp_lock);
904 ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
Alex Deucherad4febd2017-03-31 10:51:29 -0400905 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu2a507102017-02-20 17:07:36 +0800906 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400907}
908
Eric Huangf2bdc052016-05-24 15:11:17 -0400909static int pp_dpm_get_mclk_od(void *handle)
910{
911 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800912 struct pp_instance *pp_handle = (struct pp_instance *)handle;
913 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400914
Rex Zhu1c863802016-12-28 19:43:23 +0800915 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400916
Rex Zhu1c863802016-12-28 19:43:23 +0800917 if (ret != 0)
918 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400919
Rex Zhu1c863802016-12-28 19:43:23 +0800920 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400921
922 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800923 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400924 return 0;
925 }
Rex Zhu2a507102017-02-20 17:07:36 +0800926 mutex_lock(&pp_handle->pp_lock);
927 ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr);
928 mutex_unlock(&pp_handle->pp_lock);
929 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400930}
931
932static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
933{
934 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800935 struct pp_instance *pp_handle = (struct pp_instance *)handle;
936 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400937
Rex Zhu1c863802016-12-28 19:43:23 +0800938 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400939
Rex Zhu1c863802016-12-28 19:43:23 +0800940 if (ret != 0)
941 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400942
Rex Zhu1c863802016-12-28 19:43:23 +0800943 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400944
945 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800946 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400947 return 0;
948 }
Rex Zhu2a507102017-02-20 17:07:36 +0800949 mutex_lock(&pp_handle->pp_lock);
950 ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
951 mutex_unlock(&pp_handle->pp_lock);
952 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400953}
954
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500955static int pp_dpm_read_sensor(void *handle, int idx,
956 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400957{
958 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800959 struct pp_instance *pp_handle = (struct pp_instance *)handle;
960 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400961
Rex Zhu1c863802016-12-28 19:43:23 +0800962 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400963
Rex Zhu1c863802016-12-28 19:43:23 +0800964 if (ret != 0)
965 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400966
Rex Zhu1c863802016-12-28 19:43:23 +0800967 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400968
969 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800970 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400971 return 0;
972 }
973
Rex Zhu2a507102017-02-20 17:07:36 +0800974 mutex_lock(&pp_handle->pp_lock);
975 ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
976 mutex_unlock(&pp_handle->pp_lock);
977
978 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400979}
980
Alex Deucher597be302016-10-07 13:52:43 -0400981static struct amd_vce_state*
982pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
983{
984 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800985 struct pp_instance *pp_handle = (struct pp_instance *)handle;
986 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -0400987
Rex Zhu1c863802016-12-28 19:43:23 +0800988 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -0400989
Rex Zhu1c863802016-12-28 19:43:23 +0800990 if (ret != 0)
991 return NULL;
992
993 hwmgr = pp_handle->hwmgr;
994
995 if (hwmgr && idx < hwmgr->num_vce_state_tables)
996 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -0400997 return NULL;
998}
999
Eric Huang34bb2732016-09-12 16:17:44 -04001000static int pp_dpm_reset_power_profile_state(void *handle,
1001 struct amd_pp_profile *request)
1002{
1003 struct pp_hwmgr *hwmgr;
1004 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1005
1006 if (!request || pp_check(pp_handle))
1007 return -EINVAL;
1008
1009 hwmgr = pp_handle->hwmgr;
1010
1011 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1012 pr_info("%s was not implemented.\n", __func__);
1013 return 0;
1014 }
1015
1016 if (request->type == AMD_PP_GFX_PROFILE) {
1017 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
1018 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1019 &hwmgr->gfx_power_profile);
1020 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
1021 hwmgr->compute_power_profile =
1022 hwmgr->default_compute_power_profile;
1023 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
1024 &hwmgr->compute_power_profile);
1025 } else
1026 return -EINVAL;
1027}
1028
1029static int pp_dpm_get_power_profile_state(void *handle,
1030 struct amd_pp_profile *query)
1031{
1032 struct pp_hwmgr *hwmgr;
1033 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1034
1035 if (!query || pp_check(pp_handle))
1036 return -EINVAL;
1037
1038 hwmgr = pp_handle->hwmgr;
1039
1040 if (query->type == AMD_PP_GFX_PROFILE)
1041 memcpy(query, &hwmgr->gfx_power_profile,
1042 sizeof(struct amd_pp_profile));
1043 else if (query->type == AMD_PP_COMPUTE_PROFILE)
1044 memcpy(query, &hwmgr->compute_power_profile,
1045 sizeof(struct amd_pp_profile));
1046 else
1047 return -EINVAL;
1048
1049 return 0;
1050}
1051
1052static int pp_dpm_set_power_profile_state(void *handle,
1053 struct amd_pp_profile *request)
1054{
1055 struct pp_hwmgr *hwmgr;
1056 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1057 int ret = -1;
1058
1059 if (!request || pp_check(pp_handle))
1060 return -EINVAL;
1061
1062 hwmgr = pp_handle->hwmgr;
1063
1064 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
1065 pr_info("%s was not implemented.\n", __func__);
1066 return 0;
1067 }
1068
1069 if (request->min_sclk ||
1070 request->min_mclk ||
1071 request->activity_threshold ||
1072 request->up_hyst ||
1073 request->down_hyst) {
1074 if (request->type == AMD_PP_GFX_PROFILE)
1075 memcpy(&hwmgr->gfx_power_profile, request,
1076 sizeof(struct amd_pp_profile));
1077 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1078 memcpy(&hwmgr->compute_power_profile, request,
1079 sizeof(struct amd_pp_profile));
1080 else
1081 return -EINVAL;
1082
1083 if (request->type == hwmgr->current_power_profile)
1084 ret = hwmgr->hwmgr_func->set_power_profile_state(
1085 hwmgr,
1086 request);
1087 } else {
1088 /* set power profile if it exists */
1089 switch (request->type) {
1090 case AMD_PP_GFX_PROFILE:
1091 ret = hwmgr->hwmgr_func->set_power_profile_state(
1092 hwmgr,
1093 &hwmgr->gfx_power_profile);
1094 break;
1095 case AMD_PP_COMPUTE_PROFILE:
1096 ret = hwmgr->hwmgr_func->set_power_profile_state(
1097 hwmgr,
1098 &hwmgr->compute_power_profile);
1099 break;
1100 default:
1101 return -EINVAL;
1102 }
1103 }
1104
1105 if (!ret)
1106 hwmgr->current_power_profile = request->type;
1107
1108 return 0;
1109}
1110
1111static int pp_dpm_switch_power_profile(void *handle,
1112 enum amd_pp_profile_type type)
1113{
1114 struct pp_hwmgr *hwmgr;
1115 struct amd_pp_profile request = {0};
1116 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1117
1118 if (pp_check(pp_handle))
1119 return -EINVAL;
1120
1121 hwmgr = pp_handle->hwmgr;
1122
1123 if (hwmgr->current_power_profile != type) {
1124 request.type = type;
1125 pp_dpm_set_power_profile_state(handle, &request);
1126 }
1127
1128 return 0;
1129}
1130
Alex Deucher1f7371b2015-12-02 17:46:21 -05001131const struct amd_powerplay_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001132 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001133 .load_firmware = pp_dpm_load_fw,
1134 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1135 .force_performance_level = pp_dpm_force_performance_level,
1136 .get_performance_level = pp_dpm_get_performance_level,
1137 .get_current_power_state = pp_dpm_get_current_power_state,
1138 .get_sclk = pp_dpm_get_sclk,
1139 .get_mclk = pp_dpm_get_mclk,
1140 .powergate_vce = pp_dpm_powergate_vce,
1141 .powergate_uvd = pp_dpm_powergate_uvd,
1142 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001143 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1144 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1145 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1146 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001147 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001148 .get_pp_num_states = pp_dpm_get_pp_num_states,
1149 .get_pp_table = pp_dpm_get_pp_table,
1150 .set_pp_table = pp_dpm_set_pp_table,
1151 .force_clock_level = pp_dpm_force_clock_level,
1152 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001153 .get_sclk_od = pp_dpm_get_sclk_od,
1154 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001155 .get_mclk_od = pp_dpm_get_mclk_od,
1156 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001157 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001158 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001159 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1160 .get_power_profile_state = pp_dpm_get_power_profile_state,
1161 .set_power_profile_state = pp_dpm_set_power_profile_state,
1162 .switch_power_profile = pp_dpm_switch_power_profile,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001163};
1164
Rex Zhu1c863802016-12-28 19:43:23 +08001165int amd_powerplay_create(struct amd_pp_init *pp_init,
1166 void **handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001167{
Rex Zhu1c863802016-12-28 19:43:23 +08001168 struct pp_instance *instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001169
Rex Zhu1c863802016-12-28 19:43:23 +08001170 if (pp_init == NULL || handle == NULL)
1171 return -EINVAL;
1172
1173 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
1174 if (instance == NULL)
Jammy Zhouac885b32015-07-21 17:43:02 +08001175 return -ENOMEM;
1176
Rex Zhu1c863802016-12-28 19:43:23 +08001177 instance->pp_valid = PP_VALID;
1178 instance->chip_family = pp_init->chip_family;
1179 instance->chip_id = pp_init->chip_id;
1180 instance->pm_en = pp_init->pm_en;
1181 instance->feature_mask = pp_init->feature_mask;
1182 instance->device = pp_init->device;
Rex Zhu2a507102017-02-20 17:07:36 +08001183 mutex_init(&instance->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001184 *handle = instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001185 return 0;
1186}
1187
Rex Zhu1c863802016-12-28 19:43:23 +08001188int amd_powerplay_destroy(void *handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001189{
1190 struct pp_instance *instance = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +08001191
Rex Zhu1c863802016-12-28 19:43:23 +08001192 if (instance->pm_en) {
1193 kfree(instance->eventmgr);
1194 kfree(instance->hwmgr);
1195 instance->hwmgr = NULL;
1196 instance->eventmgr = NULL;
Rex Zhuba5f8842016-10-27 15:29:57 +08001197 }
Jammy Zhou3bace352015-07-21 21:18:15 +08001198
Rex Zhu1c863802016-12-28 19:43:23 +08001199 kfree(instance->smu_mgr);
1200 instance->smu_mgr = NULL;
1201 kfree(instance);
1202 instance = NULL;
Alex Deucher1f7371b2015-12-02 17:46:21 -05001203 return 0;
1204}
Rex Zhu7fb72a12015-11-19 13:35:30 +08001205
Eric Huang4dcf9e62016-06-01 17:08:07 -04001206int amd_powerplay_reset(void *handle)
1207{
1208 struct pp_instance *instance = (struct pp_instance *)handle;
1209 struct pp_eventmgr *eventmgr;
1210 struct pem_event_data event_data = { {0} };
1211 int ret;
1212
Rex Zhu1c863802016-12-28 19:43:23 +08001213 if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1214 return PP_DPM_DISABLED;
1215
1216 ret = pp_check(instance);
1217 if (ret != 0)
1218 return ret;
1219
1220 ret = pp_hw_fini(handle);
1221 if (ret)
1222 return ret;
1223
1224 ret = hwmgr_hw_init(instance);
1225 if (ret)
1226 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001227
1228 eventmgr = instance->eventmgr;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001229
Rex Zhu1c863802016-12-28 19:43:23 +08001230 if (eventmgr->pp_eventmgr_init == NULL)
1231 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001232
1233 ret = eventmgr->pp_eventmgr_init(eventmgr);
1234 if (ret)
1235 return ret;
1236
1237 return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
1238}
1239
Rex Zhu7fb72a12015-11-19 13:35:30 +08001240/* export this function to DAL */
1241
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001242int amd_powerplay_display_configuration_change(void *handle,
1243 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001244{
1245 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001246 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1247 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001248
Rex Zhu1c863802016-12-28 19:43:23 +08001249 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001250
Rex Zhu1c863802016-12-28 19:43:23 +08001251 if (ret != 0)
1252 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001253
Rex Zhu1c863802016-12-28 19:43:23 +08001254 hwmgr = pp_handle->hwmgr;
Rex Zhu2a507102017-02-20 17:07:36 +08001255 mutex_lock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001256 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhu2a507102017-02-20 17:07:36 +08001257 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001258 return 0;
1259}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001260
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001261int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001262 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001263{
1264 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001265 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1266 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001267
Rex Zhu1c863802016-12-28 19:43:23 +08001268 ret = pp_check(pp_handle);
1269
1270 if (ret != 0)
1271 return ret;
1272
1273 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001274
1275 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001276 return -EINVAL;
1277
Rex Zhu2a507102017-02-20 17:07:36 +08001278 mutex_lock(&pp_handle->pp_lock);
1279 ret = phm_get_dal_power_level(hwmgr, output);
1280 mutex_unlock(&pp_handle->pp_lock);
1281 return ret;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001282}
Rex Zhue273b042015-12-07 18:44:23 +08001283
1284int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001285 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001286{
Rex Zhue273b042015-12-07 18:44:23 +08001287 struct amd_pp_simple_clock_info simple_clocks;
1288 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001289 struct pp_hwmgr *hwmgr;
1290 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1291 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001292
Rex Zhu1c863802016-12-28 19:43:23 +08001293 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001294
Rex Zhu1c863802016-12-28 19:43:23 +08001295 if (ret != 0)
1296 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001297
Rex Zhu1c863802016-12-28 19:43:23 +08001298 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001299
Rex Zhu2a507102017-02-20 17:07:36 +08001300 mutex_lock(&pp_handle->pp_lock);
1301
Rex Zhue273b042015-12-07 18:44:23 +08001302 phm_get_dal_power_level(hwmgr, &simple_clocks);
1303
Rex Zhu2a507102017-02-20 17:07:36 +08001304 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1305 PHM_PlatformCaps_PowerContainment))
1306 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1307 &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment);
1308 else
1309 ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware,
1310 &hw_clocks, PHM_PerformanceLevelDesignation_Activity);
1311
1312 if (ret != 0) {
1313 pr_info("Error in phm_get_clock_info \n");
1314 mutex_unlock(&pp_handle->pp_lock);
1315 return -EINVAL;
Rex Zhue273b042015-12-07 18:44:23 +08001316 }
1317
1318 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1319 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1320 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1321 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1322 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1323 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1324
1325 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1326 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1327
1328 clocks->max_clocks_state = simple_clocks.level;
1329
1330 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1331 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1332 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1333 }
Rex Zhu2a507102017-02-20 17:07:36 +08001334 mutex_unlock(&pp_handle->pp_lock);
Rex Zhue273b042015-12-07 18:44:23 +08001335 return 0;
Rex Zhue273b042015-12-07 18:44:23 +08001336}
1337
1338int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1339{
Rex Zhu1c863802016-12-28 19:43:23 +08001340 struct pp_hwmgr *hwmgr;
1341 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1342 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001343
Rex Zhu1c863802016-12-28 19:43:23 +08001344 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001345
Rex Zhu1c863802016-12-28 19:43:23 +08001346 if (ret != 0)
1347 return ret;
1348
1349 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001350
1351 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001352 return -EINVAL;
1353
Rex Zhu2a507102017-02-20 17:07:36 +08001354 mutex_lock(&pp_handle->pp_lock);
1355 ret = phm_get_clock_by_type(hwmgr, type, clocks);
1356 mutex_unlock(&pp_handle->pp_lock);
1357 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001358}
1359
Eric Huangd0187722017-03-06 13:13:48 -05001360int amd_powerplay_get_clock_by_type_with_latency(void *handle,
1361 enum amd_pp_clock_type type,
1362 struct pp_clock_levels_with_latency *clocks)
1363{
1364 struct pp_hwmgr *hwmgr;
1365 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1366 int ret = 0;
1367
1368 ret = pp_check(pp_handle);
1369 if (ret != 0)
1370 return ret;
1371
1372 if (!clocks)
1373 return -EINVAL;
1374
1375 mutex_lock(&pp_handle->pp_lock);
1376 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1377 ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks);
1378 mutex_unlock(&pp_handle->pp_lock);
1379 return ret;
1380}
1381
1382int amd_powerplay_get_clock_by_type_with_voltage(void *handle,
1383 enum amd_pp_clock_type type,
1384 struct pp_clock_levels_with_voltage *clocks)
1385{
1386 struct pp_hwmgr *hwmgr;
1387 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1388 int ret = 0;
1389
1390 ret = pp_check(pp_handle);
1391 if (ret != 0)
1392 return ret;
1393
1394 if (!clocks)
1395 return -EINVAL;
1396
1397 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1398
1399 mutex_lock(&pp_handle->pp_lock);
1400
1401 ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks);
1402
1403 mutex_unlock(&pp_handle->pp_lock);
1404 return ret;
1405}
1406
1407int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle,
1408 struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
1409{
1410 struct pp_hwmgr *hwmgr;
1411 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1412 int ret = 0;
1413
1414 ret = pp_check(pp_handle);
1415 if (ret != 0)
1416 return ret;
1417
1418 if (!wm_with_clock_ranges)
1419 return -EINVAL;
1420
1421 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1422
1423 mutex_lock(&pp_handle->pp_lock);
1424 ret = phm_set_watermarks_for_clocks_ranges(hwmgr,
1425 wm_with_clock_ranges);
1426 mutex_unlock(&pp_handle->pp_lock);
1427
1428 return ret;
1429}
1430
1431int amd_powerplay_display_clock_voltage_request(void *handle,
1432 struct pp_display_clock_request *clock)
1433{
1434 struct pp_hwmgr *hwmgr;
1435 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1436 int ret = 0;
1437
1438 ret = pp_check(pp_handle);
1439 if (ret != 0)
1440 return ret;
1441
1442 if (!clock)
1443 return -EINVAL;
1444
1445 hwmgr = ((struct pp_instance *)handle)->hwmgr;
1446
1447 mutex_lock(&pp_handle->pp_lock);
1448 ret = phm_display_clock_voltage_request(hwmgr, clock);
1449 mutex_unlock(&pp_handle->pp_lock);
1450
1451 return ret;
1452}
1453
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001454int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1455 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001456{
Rex Zhue273b042015-12-07 18:44:23 +08001457 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001458 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1459 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001460
Rex Zhu1c863802016-12-28 19:43:23 +08001461 ret = pp_check(pp_handle);
1462
1463 if (ret != 0)
1464 return ret;
1465
1466 hwmgr = pp_handle->hwmgr;
1467
Rex Zhufa9e6992015-12-29 13:56:03 +08001468 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001469 return -EINVAL;
1470
Rex Zhu2a507102017-02-20 17:07:36 +08001471 mutex_lock(&pp_handle->pp_lock);
1472
Rex Zhue273b042015-12-07 18:44:23 +08001473 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001474 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001475
Rex Zhu2a507102017-02-20 17:07:36 +08001476 mutex_unlock(&pp_handle->pp_lock);
Rex Zhu1c863802016-12-28 19:43:23 +08001477 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001478}
1479