blob: 8132d464dcb646303afd06c49b1b33612fefbe4c [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,
242 state == AMD_PG_STATE_GATE ? true : false);
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
344 hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
345
Alex Deucher1f7371b2015-12-02 17:46:21 -0500346 return 0;
347}
Rex Zhu577bbe02015-08-28 12:56:43 +0800348
Alex Deucher1f7371b2015-12-02 17:46:21 -0500349static enum amd_dpm_forced_level pp_dpm_get_performance_level(
350 void *handle)
351{
Rex Zhu577bbe02015-08-28 12:56:43 +0800352 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800353 struct pp_instance *pp_handle = (struct pp_instance *)handle;
354 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800355
Rex Zhu1c863802016-12-28 19:43:23 +0800356 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800357
Rex Zhu1c863802016-12-28 19:43:23 +0800358 if (ret != 0)
359 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800360
Rex Zhu1c863802016-12-28 19:43:23 +0800361 hwmgr = pp_handle->hwmgr;
Rex Zhu577bbe02015-08-28 12:56:43 +0800362
Rex Zhu1c863802016-12-28 19:43:23 +0800363 return hwmgr->dpm_level;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500364}
Rex Zhu577bbe02015-08-28 12:56:43 +0800365
Alex Deucher1f7371b2015-12-02 17:46:21 -0500366static int pp_dpm_get_sclk(void *handle, bool low)
367{
Rex Zhu577bbe02015-08-28 12:56:43 +0800368 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800369 struct pp_instance *pp_handle = (struct pp_instance *)handle;
370 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800371
Rex Zhu1c863802016-12-28 19:43:23 +0800372 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800373
Rex Zhu1c863802016-12-28 19:43:23 +0800374 if (ret != 0)
375 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800376
Rex Zhu1c863802016-12-28 19:43:23 +0800377 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800378
379 if (hwmgr->hwmgr_func->get_sclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800380 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800381 return 0;
382 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800383
384 return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500385}
Rex Zhu577bbe02015-08-28 12:56:43 +0800386
Alex Deucher1f7371b2015-12-02 17:46:21 -0500387static int pp_dpm_get_mclk(void *handle, bool low)
388{
Rex Zhu577bbe02015-08-28 12:56:43 +0800389 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800390 struct pp_instance *pp_handle = (struct pp_instance *)handle;
391 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800392
Rex Zhu1c863802016-12-28 19:43:23 +0800393 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800394
Rex Zhu1c863802016-12-28 19:43:23 +0800395 if (ret != 0)
396 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800397
Rex Zhu1c863802016-12-28 19:43:23 +0800398 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800399
400 if (hwmgr->hwmgr_func->get_mclk == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800401 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800402 return 0;
403 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800404
405 return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500406}
Rex Zhu577bbe02015-08-28 12:56:43 +0800407
Alex Deucher1f7371b2015-12-02 17:46:21 -0500408static int pp_dpm_powergate_vce(void *handle, bool gate)
409{
Rex Zhu577bbe02015-08-28 12:56:43 +0800410 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800411 struct pp_instance *pp_handle = (struct pp_instance *)handle;
412 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800413
Rex Zhu1c863802016-12-28 19:43:23 +0800414 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800415
Rex Zhu1c863802016-12-28 19:43:23 +0800416 if (ret != 0)
417 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800418
Rex Zhu1c863802016-12-28 19:43:23 +0800419 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800420
421 if (hwmgr->hwmgr_func->powergate_vce == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800422 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800423 return 0;
424 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800425
426 return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
Alex Deucher1f7371b2015-12-02 17:46:21 -0500427}
Rex Zhu577bbe02015-08-28 12:56:43 +0800428
Alex Deucher1f7371b2015-12-02 17:46:21 -0500429static int pp_dpm_powergate_uvd(void *handle, bool gate)
430{
Rex Zhu577bbe02015-08-28 12:56:43 +0800431 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800432 struct pp_instance *pp_handle = (struct pp_instance *)handle;
433 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800434
Rex Zhu1c863802016-12-28 19:43:23 +0800435 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800436
Rex Zhu1c863802016-12-28 19:43:23 +0800437 if (ret != 0)
438 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800439
Rex Zhu1c863802016-12-28 19:43:23 +0800440 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800441
442 if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800443 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800444 return 0;
445 }
Rex Zhu577bbe02015-08-28 12:56:43 +0800446
447 return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
448}
449
450static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state)
451{
452 switch (state) {
453 case POWER_STATE_TYPE_BATTERY:
454 return PP_StateUILabel_Battery;
455 case POWER_STATE_TYPE_BALANCED:
456 return PP_StateUILabel_Balanced;
457 case POWER_STATE_TYPE_PERFORMANCE:
458 return PP_StateUILabel_Performance;
459 default:
460 return PP_StateUILabel_None;
461 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500462}
463
Baoyou Xief8a4c112016-09-30 17:58:42 +0800464static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
465 void *input, void *output)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500466{
Rex Zhu577bbe02015-08-28 12:56:43 +0800467 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800468 struct pem_event_data data = { {0} };
Rex Zhu1c863802016-12-28 19:43:23 +0800469 struct pp_instance *pp_handle = (struct pp_instance *)handle;
Rex Zhu577bbe02015-08-28 12:56:43 +0800470
Rex Zhu1c863802016-12-28 19:43:23 +0800471 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800472
Rex Zhu1c863802016-12-28 19:43:23 +0800473 if (ret != 0)
474 return ret;
Rex Zhuba5f8842016-10-27 15:29:57 +0800475
Rex Zhu577bbe02015-08-28 12:56:43 +0800476 switch (event_id) {
477 case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
478 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
479 break;
480 case AMD_PP_EVENT_ENABLE_USER_STATE:
481 {
482 enum amd_pm_state_type ps;
483
484 if (input == NULL)
485 return -EINVAL;
486 ps = *(unsigned long *)input;
487
488 data.requested_ui_label = power_state_convert(ps);
489 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
Rex Zhudc26a2a2016-02-25 17:16:52 +0800490 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800491 }
Rex Zhudc26a2a2016-02-25 17:16:52 +0800492 case AMD_PP_EVENT_COMPLETE_INIT:
493 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
494 break;
Eric Huang428bafa2016-05-12 14:51:21 -0400495 case AMD_PP_EVENT_READJUST_POWER_STATE:
Eric Huang428bafa2016-05-12 14:51:21 -0400496 ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
497 break;
Rex Zhu577bbe02015-08-28 12:56:43 +0800498 default:
499 break;
500 }
501 return ret;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500502}
Rex Zhu577bbe02015-08-28 12:56:43 +0800503
Baoyou Xief8a4c112016-09-30 17:58:42 +0800504static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500505{
Rex Zhu577bbe02015-08-28 12:56:43 +0800506 struct pp_hwmgr *hwmgr;
507 struct pp_power_state *state;
Rex Zhu1c863802016-12-28 19:43:23 +0800508 struct pp_instance *pp_handle = (struct pp_instance *)handle;
509 int ret = 0;
Rex Zhu577bbe02015-08-28 12:56:43 +0800510
Rex Zhu1c863802016-12-28 19:43:23 +0800511 ret = pp_check(pp_handle);
Rex Zhu577bbe02015-08-28 12:56:43 +0800512
Rex Zhu1c863802016-12-28 19:43:23 +0800513 if (ret != 0)
514 return ret;
Rex Zhu577bbe02015-08-28 12:56:43 +0800515
Rex Zhu1c863802016-12-28 19:43:23 +0800516 hwmgr = pp_handle->hwmgr;
517
518 if (hwmgr->current_ps == NULL)
Rex Zhu577bbe02015-08-28 12:56:43 +0800519 return -EINVAL;
520
521 state = hwmgr->current_ps;
522
523 switch (state->classification.ui_label) {
524 case PP_StateUILabel_Battery:
525 return POWER_STATE_TYPE_BATTERY;
526 case PP_StateUILabel_Balanced:
527 return POWER_STATE_TYPE_BALANCED;
528 case PP_StateUILabel_Performance:
529 return POWER_STATE_TYPE_PERFORMANCE;
530 default:
Eric Huangf3898ea2015-12-11 16:24:34 -0500531 if (state->classification.flags & PP_StateClassificationFlag_Boot)
532 return POWER_STATE_TYPE_INTERNAL_BOOT;
533 else
534 return POWER_STATE_TYPE_DEFAULT;
Rex Zhu577bbe02015-08-28 12:56:43 +0800535 }
Alex Deucher1f7371b2015-12-02 17:46:21 -0500536}
Rex Zhu577bbe02015-08-28 12:56:43 +0800537
Rex Zhucac9a192015-10-16 11:48:21 +0800538static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode)
539{
540 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800541 struct pp_instance *pp_handle = (struct pp_instance *)handle;
542 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800543
Rex Zhu1c863802016-12-28 19:43:23 +0800544 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800545
Rex Zhu1c863802016-12-28 19:43:23 +0800546 if (ret != 0)
547 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800548
Rex Zhu1c863802016-12-28 19:43:23 +0800549 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800550
551 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800552 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800553 return 0;
554 }
Rex Zhucac9a192015-10-16 11:48:21 +0800555
556 return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
557}
558
559static int pp_dpm_get_fan_control_mode(void *handle)
560{
561 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800562 struct pp_instance *pp_handle = (struct pp_instance *)handle;
563 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800564
Rex Zhu1c863802016-12-28 19:43:23 +0800565 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800566
Rex Zhu1c863802016-12-28 19:43:23 +0800567 if (ret != 0)
568 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800569
Rex Zhu1c863802016-12-28 19:43:23 +0800570 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800571
572 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800573 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800574 return 0;
575 }
Rex Zhucac9a192015-10-16 11:48:21 +0800576
577 return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
578}
579
580static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
581{
582 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800583 struct pp_instance *pp_handle = (struct pp_instance *)handle;
584 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800585
Rex Zhu1c863802016-12-28 19:43:23 +0800586 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800587
Rex Zhu1c863802016-12-28 19:43:23 +0800588 if (ret != 0)
589 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800590
Rex Zhu1c863802016-12-28 19:43:23 +0800591 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800592
593 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800594 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800595 return 0;
596 }
Rex Zhucac9a192015-10-16 11:48:21 +0800597
598 return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
599}
600
601static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed)
602{
603 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800604 struct pp_instance *pp_handle = (struct pp_instance *)handle;
605 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800606
Rex Zhu1c863802016-12-28 19:43:23 +0800607 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800608
Rex Zhu1c863802016-12-28 19:43:23 +0800609 if (ret != 0)
610 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800611
Rex Zhu1c863802016-12-28 19:43:23 +0800612 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800613
614 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800615 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800616 return 0;
617 }
Rex Zhucac9a192015-10-16 11:48:21 +0800618
619 return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
620}
621
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300622static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
623{
624 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800625 struct pp_instance *pp_handle = (struct pp_instance *)handle;
626 int ret = 0;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300627
Rex Zhu1c863802016-12-28 19:43:23 +0800628 ret = pp_check(pp_handle);
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300629
Rex Zhu1c863802016-12-28 19:43:23 +0800630 if (ret != 0)
631 return ret;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300632
Rex Zhu1c863802016-12-28 19:43:23 +0800633 hwmgr = pp_handle->hwmgr;
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +0300634
635 if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
636 return -EINVAL;
637
638 return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
639}
640
Rex Zhucac9a192015-10-16 11:48:21 +0800641static int pp_dpm_get_temperature(void *handle)
642{
643 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800644 struct pp_instance *pp_handle = (struct pp_instance *)handle;
645 int ret = 0;
Rex Zhucac9a192015-10-16 11:48:21 +0800646
Rex Zhu1c863802016-12-28 19:43:23 +0800647 ret = pp_check(pp_handle);
Rex Zhucac9a192015-10-16 11:48:21 +0800648
Rex Zhu1c863802016-12-28 19:43:23 +0800649 if (ret != 0)
650 return ret;
Rex Zhucac9a192015-10-16 11:48:21 +0800651
Rex Zhu1c863802016-12-28 19:43:23 +0800652 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800653
654 if (hwmgr->hwmgr_func->get_temperature == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800655 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800656 return 0;
657 }
Rex Zhucac9a192015-10-16 11:48:21 +0800658
659 return hwmgr->hwmgr_func->get_temperature(hwmgr);
660}
Rex Zhu577bbe02015-08-28 12:56:43 +0800661
Eric Huangf3898ea2015-12-11 16:24:34 -0500662static int pp_dpm_get_pp_num_states(void *handle,
663 struct pp_states_info *data)
664{
665 struct pp_hwmgr *hwmgr;
666 int i;
Rex Zhu1c863802016-12-28 19:43:23 +0800667 struct pp_instance *pp_handle = (struct pp_instance *)handle;
668 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500669
Rex Zhu1c863802016-12-28 19:43:23 +0800670 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500671
Rex Zhu1c863802016-12-28 19:43:23 +0800672 if (ret != 0)
673 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500674
Rex Zhu1c863802016-12-28 19:43:23 +0800675 hwmgr = pp_handle->hwmgr;
676
677 if (hwmgr->ps == NULL)
Eric Huangf3898ea2015-12-11 16:24:34 -0500678 return -EINVAL;
679
680 data->nums = hwmgr->num_ps;
681
682 for (i = 0; i < hwmgr->num_ps; i++) {
683 struct pp_power_state *state = (struct pp_power_state *)
684 ((unsigned long)hwmgr->ps + i * hwmgr->ps_size);
685 switch (state->classification.ui_label) {
686 case PP_StateUILabel_Battery:
687 data->states[i] = POWER_STATE_TYPE_BATTERY;
688 break;
689 case PP_StateUILabel_Balanced:
690 data->states[i] = POWER_STATE_TYPE_BALANCED;
691 break;
692 case PP_StateUILabel_Performance:
693 data->states[i] = POWER_STATE_TYPE_PERFORMANCE;
694 break;
695 default:
696 if (state->classification.flags & PP_StateClassificationFlag_Boot)
697 data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT;
698 else
699 data->states[i] = POWER_STATE_TYPE_DEFAULT;
700 }
701 }
702
703 return 0;
704}
705
706static int pp_dpm_get_pp_table(void *handle, char **table)
707{
708 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800709 struct pp_instance *pp_handle = (struct pp_instance *)handle;
710 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500711
Rex Zhu1c863802016-12-28 19:43:23 +0800712 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500713
Rex Zhu1c863802016-12-28 19:43:23 +0800714 if (ret != 0)
715 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500716
Rex Zhu1c863802016-12-28 19:43:23 +0800717 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800718
Eric Huang4dcf9e62016-06-01 17:08:07 -0400719 if (!hwmgr->soft_pp_table)
720 return -EINVAL;
Eric Huangf3898ea2015-12-11 16:24:34 -0500721
Eric Huang4dcf9e62016-06-01 17:08:07 -0400722 *table = (char *)hwmgr->soft_pp_table;
723
724 return hwmgr->soft_pp_table_size;
Eric Huangf3898ea2015-12-11 16:24:34 -0500725}
726
727static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
728{
729 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800730 struct pp_instance *pp_handle = (struct pp_instance *)handle;
731 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500732
Rex Zhu1c863802016-12-28 19:43:23 +0800733 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500734
Rex Zhu1c863802016-12-28 19:43:23 +0800735 if (ret != 0)
736 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500737
Rex Zhu1c863802016-12-28 19:43:23 +0800738 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800739
Eric Huang4dcf9e62016-06-01 17:08:07 -0400740 if (!hwmgr->hardcode_pp_table) {
Edward O'Callaghanefdf7a932016-09-04 12:36:19 +1000741 hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table,
742 hwmgr->soft_pp_table_size,
743 GFP_KERNEL);
Eric Huang4dcf9e62016-06-01 17:08:07 -0400744
745 if (!hwmgr->hardcode_pp_table)
746 return -ENOMEM;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800747 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500748
Eric Huang4dcf9e62016-06-01 17:08:07 -0400749 memcpy(hwmgr->hardcode_pp_table, buf, size);
750
751 hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
752
Eric Huangdd4bdf32017-03-01 15:49:31 -0500753 ret = amd_powerplay_reset(handle);
754 if (ret)
755 return ret;
756
757 if (hwmgr->hwmgr_func->avfs_control) {
758 ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false);
759 if (ret)
760 return ret;
761 }
762
763 return 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500764}
765
766static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400767 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500768{
769 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800770 struct pp_instance *pp_handle = (struct pp_instance *)handle;
771 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500772
Rex Zhu1c863802016-12-28 19:43:23 +0800773 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500774
Rex Zhu1c863802016-12-28 19:43:23 +0800775 if (ret != 0)
776 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500777
Rex Zhu1c863802016-12-28 19:43:23 +0800778 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800779
780 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800781 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800782 return 0;
783 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500784
Eric Huang56327082016-04-12 14:57:23 -0400785 return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
Eric Huangf3898ea2015-12-11 16:24:34 -0500786}
787
788static int pp_dpm_print_clock_levels(void *handle,
789 enum pp_clock_type type, char *buf)
790{
791 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800792 struct pp_instance *pp_handle = (struct pp_instance *)handle;
793 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500794
Rex Zhu1c863802016-12-28 19:43:23 +0800795 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500796
Rex Zhu1c863802016-12-28 19:43:23 +0800797 if (ret != 0)
798 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500799
Rex Zhu1c863802016-12-28 19:43:23 +0800800 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500801
Rex Zhu7383bcb2016-03-30 11:35:50 +0800802 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800803 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800804 return 0;
805 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500806 return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
807}
808
Eric Huang428bafa2016-05-12 14:51:21 -0400809static int pp_dpm_get_sclk_od(void *handle)
810{
811 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800812 struct pp_instance *pp_handle = (struct pp_instance *)handle;
813 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400814
Rex Zhu1c863802016-12-28 19:43:23 +0800815 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400816
Rex Zhu1c863802016-12-28 19:43:23 +0800817 if (ret != 0)
818 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400819
Rex Zhu1c863802016-12-28 19:43:23 +0800820 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400821
822 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800823 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400824 return 0;
825 }
826
827 return hwmgr->hwmgr_func->get_sclk_od(hwmgr);
828}
829
830static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
831{
832 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800833 struct pp_instance *pp_handle = (struct pp_instance *)handle;
834 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400835
Rex Zhu1c863802016-12-28 19:43:23 +0800836 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400837
Rex Zhu1c863802016-12-28 19:43:23 +0800838 if (ret != 0)
839 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400840
Rex Zhu1c863802016-12-28 19:43:23 +0800841 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400842
843 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800844 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400845 return 0;
846 }
847
848 return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
849}
850
Eric Huangf2bdc052016-05-24 15:11:17 -0400851static int pp_dpm_get_mclk_od(void *handle)
852{
853 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800854 struct pp_instance *pp_handle = (struct pp_instance *)handle;
855 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400856
Rex Zhu1c863802016-12-28 19:43:23 +0800857 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400858
Rex Zhu1c863802016-12-28 19:43:23 +0800859 if (ret != 0)
860 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400861
Rex Zhu1c863802016-12-28 19:43:23 +0800862 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400863
864 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800865 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400866 return 0;
867 }
868
869 return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
870}
871
872static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
873{
874 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800875 struct pp_instance *pp_handle = (struct pp_instance *)handle;
876 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400877
Rex Zhu1c863802016-12-28 19:43:23 +0800878 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400879
Rex Zhu1c863802016-12-28 19:43:23 +0800880 if (ret != 0)
881 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400882
Rex Zhu1c863802016-12-28 19:43:23 +0800883 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400884
885 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800886 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400887 return 0;
888 }
889
890 return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
891}
892
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500893static int pp_dpm_read_sensor(void *handle, int idx,
894 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400895{
896 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800897 struct pp_instance *pp_handle = (struct pp_instance *)handle;
898 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400899
Rex Zhu1c863802016-12-28 19:43:23 +0800900 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400901
Rex Zhu1c863802016-12-28 19:43:23 +0800902 if (ret != 0)
903 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400904
Rex Zhu1c863802016-12-28 19:43:23 +0800905 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400906
907 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800908 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400909 return 0;
910 }
911
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500912 return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
Tom St Denisa6e36952016-09-15 10:07:34 -0400913}
914
Alex Deucher597be302016-10-07 13:52:43 -0400915static struct amd_vce_state*
916pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
917{
918 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800919 struct pp_instance *pp_handle = (struct pp_instance *)handle;
920 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -0400921
Rex Zhu1c863802016-12-28 19:43:23 +0800922 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -0400923
Rex Zhu1c863802016-12-28 19:43:23 +0800924 if (ret != 0)
925 return NULL;
926
927 hwmgr = pp_handle->hwmgr;
928
929 if (hwmgr && idx < hwmgr->num_vce_state_tables)
930 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -0400931 return NULL;
932}
933
Eric Huang34bb2732016-09-12 16:17:44 -0400934static int pp_dpm_reset_power_profile_state(void *handle,
935 struct amd_pp_profile *request)
936{
937 struct pp_hwmgr *hwmgr;
938 struct pp_instance *pp_handle = (struct pp_instance *)handle;
939
940 if (!request || pp_check(pp_handle))
941 return -EINVAL;
942
943 hwmgr = pp_handle->hwmgr;
944
945 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
946 pr_info("%s was not implemented.\n", __func__);
947 return 0;
948 }
949
950 if (request->type == AMD_PP_GFX_PROFILE) {
951 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
952 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
953 &hwmgr->gfx_power_profile);
954 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
955 hwmgr->compute_power_profile =
956 hwmgr->default_compute_power_profile;
957 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
958 &hwmgr->compute_power_profile);
959 } else
960 return -EINVAL;
961}
962
963static int pp_dpm_get_power_profile_state(void *handle,
964 struct amd_pp_profile *query)
965{
966 struct pp_hwmgr *hwmgr;
967 struct pp_instance *pp_handle = (struct pp_instance *)handle;
968
969 if (!query || pp_check(pp_handle))
970 return -EINVAL;
971
972 hwmgr = pp_handle->hwmgr;
973
974 if (query->type == AMD_PP_GFX_PROFILE)
975 memcpy(query, &hwmgr->gfx_power_profile,
976 sizeof(struct amd_pp_profile));
977 else if (query->type == AMD_PP_COMPUTE_PROFILE)
978 memcpy(query, &hwmgr->compute_power_profile,
979 sizeof(struct amd_pp_profile));
980 else
981 return -EINVAL;
982
983 return 0;
984}
985
986static int pp_dpm_set_power_profile_state(void *handle,
987 struct amd_pp_profile *request)
988{
989 struct pp_hwmgr *hwmgr;
990 struct pp_instance *pp_handle = (struct pp_instance *)handle;
991 int ret = -1;
992
993 if (!request || pp_check(pp_handle))
994 return -EINVAL;
995
996 hwmgr = pp_handle->hwmgr;
997
998 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
999 pr_info("%s was not implemented.\n", __func__);
1000 return 0;
1001 }
1002
1003 if (request->min_sclk ||
1004 request->min_mclk ||
1005 request->activity_threshold ||
1006 request->up_hyst ||
1007 request->down_hyst) {
1008 if (request->type == AMD_PP_GFX_PROFILE)
1009 memcpy(&hwmgr->gfx_power_profile, request,
1010 sizeof(struct amd_pp_profile));
1011 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1012 memcpy(&hwmgr->compute_power_profile, request,
1013 sizeof(struct amd_pp_profile));
1014 else
1015 return -EINVAL;
1016
1017 if (request->type == hwmgr->current_power_profile)
1018 ret = hwmgr->hwmgr_func->set_power_profile_state(
1019 hwmgr,
1020 request);
1021 } else {
1022 /* set power profile if it exists */
1023 switch (request->type) {
1024 case AMD_PP_GFX_PROFILE:
1025 ret = hwmgr->hwmgr_func->set_power_profile_state(
1026 hwmgr,
1027 &hwmgr->gfx_power_profile);
1028 break;
1029 case AMD_PP_COMPUTE_PROFILE:
1030 ret = hwmgr->hwmgr_func->set_power_profile_state(
1031 hwmgr,
1032 &hwmgr->compute_power_profile);
1033 break;
1034 default:
1035 return -EINVAL;
1036 }
1037 }
1038
1039 if (!ret)
1040 hwmgr->current_power_profile = request->type;
1041
1042 return 0;
1043}
1044
1045static int pp_dpm_switch_power_profile(void *handle,
1046 enum amd_pp_profile_type type)
1047{
1048 struct pp_hwmgr *hwmgr;
1049 struct amd_pp_profile request = {0};
1050 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1051
1052 if (pp_check(pp_handle))
1053 return -EINVAL;
1054
1055 hwmgr = pp_handle->hwmgr;
1056
1057 if (hwmgr->current_power_profile != type) {
1058 request.type = type;
1059 pp_dpm_set_power_profile_state(handle, &request);
1060 }
1061
1062 return 0;
1063}
1064
Alex Deucher1f7371b2015-12-02 17:46:21 -05001065const struct amd_powerplay_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001066 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001067 .load_firmware = pp_dpm_load_fw,
1068 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1069 .force_performance_level = pp_dpm_force_performance_level,
1070 .get_performance_level = pp_dpm_get_performance_level,
1071 .get_current_power_state = pp_dpm_get_current_power_state,
1072 .get_sclk = pp_dpm_get_sclk,
1073 .get_mclk = pp_dpm_get_mclk,
1074 .powergate_vce = pp_dpm_powergate_vce,
1075 .powergate_uvd = pp_dpm_powergate_uvd,
1076 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001077 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1078 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1079 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1080 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001081 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001082 .get_pp_num_states = pp_dpm_get_pp_num_states,
1083 .get_pp_table = pp_dpm_get_pp_table,
1084 .set_pp_table = pp_dpm_set_pp_table,
1085 .force_clock_level = pp_dpm_force_clock_level,
1086 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001087 .get_sclk_od = pp_dpm_get_sclk_od,
1088 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001089 .get_mclk_od = pp_dpm_get_mclk_od,
1090 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001091 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001092 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001093 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1094 .get_power_profile_state = pp_dpm_get_power_profile_state,
1095 .set_power_profile_state = pp_dpm_set_power_profile_state,
1096 .switch_power_profile = pp_dpm_switch_power_profile,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001097};
1098
Rex Zhu1c863802016-12-28 19:43:23 +08001099int amd_powerplay_create(struct amd_pp_init *pp_init,
1100 void **handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001101{
Rex Zhu1c863802016-12-28 19:43:23 +08001102 struct pp_instance *instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001103
Rex Zhu1c863802016-12-28 19:43:23 +08001104 if (pp_init == NULL || handle == NULL)
1105 return -EINVAL;
1106
1107 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
1108 if (instance == NULL)
Jammy Zhouac885b32015-07-21 17:43:02 +08001109 return -ENOMEM;
1110
Rex Zhu1c863802016-12-28 19:43:23 +08001111 instance->pp_valid = PP_VALID;
1112 instance->chip_family = pp_init->chip_family;
1113 instance->chip_id = pp_init->chip_id;
1114 instance->pm_en = pp_init->pm_en;
1115 instance->feature_mask = pp_init->feature_mask;
1116 instance->device = pp_init->device;
1117 *handle = instance;
Rex Zhue92a0372015-09-23 15:14:54 +08001118
Jammy Zhouac885b32015-07-21 17:43:02 +08001119 return 0;
1120}
1121
Rex Zhu1c863802016-12-28 19:43:23 +08001122int amd_powerplay_destroy(void *handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001123{
1124 struct pp_instance *instance = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +08001125
Rex Zhu1c863802016-12-28 19:43:23 +08001126 if (instance->pm_en) {
1127 kfree(instance->eventmgr);
1128 kfree(instance->hwmgr);
1129 instance->hwmgr = NULL;
1130 instance->eventmgr = NULL;
Rex Zhuba5f8842016-10-27 15:29:57 +08001131 }
Jammy Zhou3bace352015-07-21 21:18:15 +08001132
Rex Zhu1c863802016-12-28 19:43:23 +08001133 kfree(instance->smu_mgr);
1134 instance->smu_mgr = NULL;
1135 kfree(instance);
1136 instance = NULL;
Alex Deucher1f7371b2015-12-02 17:46:21 -05001137 return 0;
1138}
Rex Zhu7fb72a12015-11-19 13:35:30 +08001139
Eric Huang4dcf9e62016-06-01 17:08:07 -04001140int amd_powerplay_reset(void *handle)
1141{
1142 struct pp_instance *instance = (struct pp_instance *)handle;
1143 struct pp_eventmgr *eventmgr;
1144 struct pem_event_data event_data = { {0} };
1145 int ret;
1146
Rex Zhu1c863802016-12-28 19:43:23 +08001147 if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1148 return PP_DPM_DISABLED;
1149
1150 ret = pp_check(instance);
1151 if (ret != 0)
1152 return ret;
1153
1154 ret = pp_hw_fini(handle);
1155 if (ret)
1156 return ret;
1157
1158 ret = hwmgr_hw_init(instance);
1159 if (ret)
1160 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001161
1162 eventmgr = instance->eventmgr;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001163
Rex Zhu1c863802016-12-28 19:43:23 +08001164 if (eventmgr->pp_eventmgr_init == NULL)
1165 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001166
1167 ret = eventmgr->pp_eventmgr_init(eventmgr);
1168 if (ret)
1169 return ret;
1170
1171 return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
1172}
1173
Rex Zhu7fb72a12015-11-19 13:35:30 +08001174/* export this function to DAL */
1175
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001176int amd_powerplay_display_configuration_change(void *handle,
1177 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001178{
1179 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001180 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1181 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001182
Rex Zhu1c863802016-12-28 19:43:23 +08001183 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001184
Rex Zhu1c863802016-12-28 19:43:23 +08001185 if (ret != 0)
1186 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001187
Rex Zhu1c863802016-12-28 19:43:23 +08001188 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001189
Rex Zhu7fb72a12015-11-19 13:35:30 +08001190 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhue0b71a72015-12-29 10:25:19 +08001191
Rex Zhu7fb72a12015-11-19 13:35:30 +08001192 return 0;
1193}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001194
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001195int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001196 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001197{
1198 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001199 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1200 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001201
Rex Zhu1c863802016-12-28 19:43:23 +08001202 ret = pp_check(pp_handle);
1203
1204 if (ret != 0)
1205 return ret;
1206
1207 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001208
1209 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001210 return -EINVAL;
1211
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001212 return phm_get_dal_power_level(hwmgr, output);
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001213}
Rex Zhue273b042015-12-07 18:44:23 +08001214
1215int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001216 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001217{
Rex Zhue273b042015-12-07 18:44:23 +08001218 struct amd_pp_simple_clock_info simple_clocks;
1219 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001220 struct pp_hwmgr *hwmgr;
1221 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1222 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001223
Rex Zhu1c863802016-12-28 19:43:23 +08001224 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001225
Rex Zhu1c863802016-12-28 19:43:23 +08001226 if (ret != 0)
1227 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001228
Rex Zhu1c863802016-12-28 19:43:23 +08001229 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001230
Rex Zhue273b042015-12-07 18:44:23 +08001231 phm_get_dal_power_level(hwmgr, &simple_clocks);
1232
1233 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
1234 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment))
1235 PP_ASSERT_WITH_CODE(0, "Error in PHM_GetPowerContainmentClockInfo", return -1);
1236 } else {
1237 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity))
1238 PP_ASSERT_WITH_CODE(0, "Error in PHM_GetClockInfo", return -1);
1239 }
1240
1241 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1242 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1243 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1244 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1245 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1246 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1247
1248 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1249 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1250
1251 clocks->max_clocks_state = simple_clocks.level;
1252
1253 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1254 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1255 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1256 }
1257
1258 return 0;
1259
1260}
1261
1262int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1263{
1264 int result = -1;
Rex Zhu1c863802016-12-28 19:43:23 +08001265 struct pp_hwmgr *hwmgr;
1266 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1267 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001268
Rex Zhu1c863802016-12-28 19:43:23 +08001269 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001270
Rex Zhu1c863802016-12-28 19:43:23 +08001271 if (ret != 0)
1272 return ret;
1273
1274 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001275
1276 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001277 return -EINVAL;
1278
Rex Zhue273b042015-12-07 18:44:23 +08001279 result = phm_get_clock_by_type(hwmgr, type, clocks);
1280
1281 return result;
1282}
1283
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001284int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1285 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001286{
Rex Zhue273b042015-12-07 18:44:23 +08001287 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001288 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);
1292
1293 if (ret != 0)
1294 return ret;
1295
1296 hwmgr = pp_handle->hwmgr;
1297
Rex Zhufa9e6992015-12-29 13:56:03 +08001298
1299 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001300 return -EINVAL;
1301
Rex Zhue273b042015-12-07 18:44:23 +08001302 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001303 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001304
Rex Zhu1c863802016-12-28 19:43:23 +08001305 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001306}
1307