blob: fde8fcd46b58409187b6d4c4b37e16246818b607 [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
753 return amd_powerplay_reset(handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500754}
755
756static int pp_dpm_force_clock_level(void *handle,
Eric Huang56327082016-04-12 14:57:23 -0400757 enum pp_clock_type type, uint32_t mask)
Eric Huangf3898ea2015-12-11 16:24:34 -0500758{
759 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800760 struct pp_instance *pp_handle = (struct pp_instance *)handle;
761 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500762
Rex Zhu1c863802016-12-28 19:43:23 +0800763 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500764
Rex Zhu1c863802016-12-28 19:43:23 +0800765 if (ret != 0)
766 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500767
Rex Zhu1c863802016-12-28 19:43:23 +0800768 hwmgr = pp_handle->hwmgr;
Rex Zhu7383bcb2016-03-30 11:35:50 +0800769
770 if (hwmgr->hwmgr_func->force_clock_level == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800771 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800772 return 0;
773 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500774
Eric Huang56327082016-04-12 14:57:23 -0400775 return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
Eric Huangf3898ea2015-12-11 16:24:34 -0500776}
777
778static int pp_dpm_print_clock_levels(void *handle,
779 enum pp_clock_type type, char *buf)
780{
781 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800782 struct pp_instance *pp_handle = (struct pp_instance *)handle;
783 int ret = 0;
Eric Huangf3898ea2015-12-11 16:24:34 -0500784
Rex Zhu1c863802016-12-28 19:43:23 +0800785 ret = pp_check(pp_handle);
Eric Huangf3898ea2015-12-11 16:24:34 -0500786
Rex Zhu1c863802016-12-28 19:43:23 +0800787 if (ret != 0)
788 return ret;
Eric Huangf3898ea2015-12-11 16:24:34 -0500789
Rex Zhu1c863802016-12-28 19:43:23 +0800790 hwmgr = pp_handle->hwmgr;
Eric Huangf3898ea2015-12-11 16:24:34 -0500791
Rex Zhu7383bcb2016-03-30 11:35:50 +0800792 if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800793 pr_info("%s was not implemented.\n", __func__);
Rex Zhu7383bcb2016-03-30 11:35:50 +0800794 return 0;
795 }
Eric Huangf3898ea2015-12-11 16:24:34 -0500796 return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
797}
798
Eric Huang428bafa2016-05-12 14:51:21 -0400799static int pp_dpm_get_sclk_od(void *handle)
800{
801 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800802 struct pp_instance *pp_handle = (struct pp_instance *)handle;
803 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400804
Rex Zhu1c863802016-12-28 19:43:23 +0800805 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400806
Rex Zhu1c863802016-12-28 19:43:23 +0800807 if (ret != 0)
808 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400809
Rex Zhu1c863802016-12-28 19:43:23 +0800810 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400811
812 if (hwmgr->hwmgr_func->get_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800813 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400814 return 0;
815 }
816
817 return hwmgr->hwmgr_func->get_sclk_od(hwmgr);
818}
819
820static int pp_dpm_set_sclk_od(void *handle, uint32_t value)
821{
822 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800823 struct pp_instance *pp_handle = (struct pp_instance *)handle;
824 int ret = 0;
Eric Huang428bafa2016-05-12 14:51:21 -0400825
Rex Zhu1c863802016-12-28 19:43:23 +0800826 ret = pp_check(pp_handle);
Eric Huang428bafa2016-05-12 14:51:21 -0400827
Rex Zhu1c863802016-12-28 19:43:23 +0800828 if (ret != 0)
829 return ret;
Eric Huang428bafa2016-05-12 14:51:21 -0400830
Rex Zhu1c863802016-12-28 19:43:23 +0800831 hwmgr = pp_handle->hwmgr;
Eric Huang428bafa2016-05-12 14:51:21 -0400832
833 if (hwmgr->hwmgr_func->set_sclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800834 pr_info("%s was not implemented.\n", __func__);
Eric Huang428bafa2016-05-12 14:51:21 -0400835 return 0;
836 }
837
838 return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value);
839}
840
Eric Huangf2bdc052016-05-24 15:11:17 -0400841static int pp_dpm_get_mclk_od(void *handle)
842{
843 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800844 struct pp_instance *pp_handle = (struct pp_instance *)handle;
845 int ret = 0;
Eric Huangf2bdc052016-05-24 15:11:17 -0400846
Rex Zhu1c863802016-12-28 19:43:23 +0800847 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400848
Rex Zhu1c863802016-12-28 19:43:23 +0800849 if (ret != 0)
850 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400851
Rex Zhu1c863802016-12-28 19:43:23 +0800852 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400853
854 if (hwmgr->hwmgr_func->get_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800855 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400856 return 0;
857 }
858
859 return hwmgr->hwmgr_func->get_mclk_od(hwmgr);
860}
861
862static int pp_dpm_set_mclk_od(void *handle, uint32_t value)
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 Huangf2bdc052016-05-24 15:11:17 -0400867
Rex Zhu1c863802016-12-28 19:43:23 +0800868 ret = pp_check(pp_handle);
Eric Huangf2bdc052016-05-24 15:11:17 -0400869
Rex Zhu1c863802016-12-28 19:43:23 +0800870 if (ret != 0)
871 return ret;
Eric Huangf2bdc052016-05-24 15:11:17 -0400872
Rex Zhu1c863802016-12-28 19:43:23 +0800873 hwmgr = pp_handle->hwmgr;
Eric Huangf2bdc052016-05-24 15:11:17 -0400874
875 if (hwmgr->hwmgr_func->set_mclk_od == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800876 pr_info("%s was not implemented.\n", __func__);
Eric Huangf2bdc052016-05-24 15:11:17 -0400877 return 0;
878 }
879
880 return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value);
881}
882
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500883static int pp_dpm_read_sensor(void *handle, int idx,
884 void *value, int *size)
Tom St Denisa6e36952016-09-15 10:07:34 -0400885{
886 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800887 struct pp_instance *pp_handle = (struct pp_instance *)handle;
888 int ret = 0;
Tom St Denisa6e36952016-09-15 10:07:34 -0400889
Rex Zhu1c863802016-12-28 19:43:23 +0800890 ret = pp_check(pp_handle);
Tom St Denisa6e36952016-09-15 10:07:34 -0400891
Rex Zhu1c863802016-12-28 19:43:23 +0800892 if (ret != 0)
893 return ret;
Tom St Denisa6e36952016-09-15 10:07:34 -0400894
Rex Zhu1c863802016-12-28 19:43:23 +0800895 hwmgr = pp_handle->hwmgr;
Tom St Denisa6e36952016-09-15 10:07:34 -0400896
897 if (hwmgr->hwmgr_func->read_sensor == NULL) {
Huang Rui0fb829d2016-12-26 14:24:05 +0800898 pr_info("%s was not implemented.\n", __func__);
Tom St Denisa6e36952016-09-15 10:07:34 -0400899 return 0;
900 }
901
Tom St Denis9f8df7d2017-02-09 14:29:01 -0500902 return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
Tom St Denisa6e36952016-09-15 10:07:34 -0400903}
904
Alex Deucher597be302016-10-07 13:52:43 -0400905static struct amd_vce_state*
906pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
907{
908 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +0800909 struct pp_instance *pp_handle = (struct pp_instance *)handle;
910 int ret = 0;
Alex Deucher597be302016-10-07 13:52:43 -0400911
Rex Zhu1c863802016-12-28 19:43:23 +0800912 ret = pp_check(pp_handle);
Alex Deucher597be302016-10-07 13:52:43 -0400913
Rex Zhu1c863802016-12-28 19:43:23 +0800914 if (ret != 0)
915 return NULL;
916
917 hwmgr = pp_handle->hwmgr;
918
919 if (hwmgr && idx < hwmgr->num_vce_state_tables)
920 return &hwmgr->vce_states[idx];
Alex Deucher597be302016-10-07 13:52:43 -0400921 return NULL;
922}
923
Eric Huang34bb2732016-09-12 16:17:44 -0400924static int pp_dpm_reset_power_profile_state(void *handle,
925 struct amd_pp_profile *request)
926{
927 struct pp_hwmgr *hwmgr;
928 struct pp_instance *pp_handle = (struct pp_instance *)handle;
929
930 if (!request || pp_check(pp_handle))
931 return -EINVAL;
932
933 hwmgr = pp_handle->hwmgr;
934
935 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
936 pr_info("%s was not implemented.\n", __func__);
937 return 0;
938 }
939
940 if (request->type == AMD_PP_GFX_PROFILE) {
941 hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
942 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
943 &hwmgr->gfx_power_profile);
944 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
945 hwmgr->compute_power_profile =
946 hwmgr->default_compute_power_profile;
947 return hwmgr->hwmgr_func->set_power_profile_state(hwmgr,
948 &hwmgr->compute_power_profile);
949 } else
950 return -EINVAL;
951}
952
953static int pp_dpm_get_power_profile_state(void *handle,
954 struct amd_pp_profile *query)
955{
956 struct pp_hwmgr *hwmgr;
957 struct pp_instance *pp_handle = (struct pp_instance *)handle;
958
959 if (!query || pp_check(pp_handle))
960 return -EINVAL;
961
962 hwmgr = pp_handle->hwmgr;
963
964 if (query->type == AMD_PP_GFX_PROFILE)
965 memcpy(query, &hwmgr->gfx_power_profile,
966 sizeof(struct amd_pp_profile));
967 else if (query->type == AMD_PP_COMPUTE_PROFILE)
968 memcpy(query, &hwmgr->compute_power_profile,
969 sizeof(struct amd_pp_profile));
970 else
971 return -EINVAL;
972
973 return 0;
974}
975
976static int pp_dpm_set_power_profile_state(void *handle,
977 struct amd_pp_profile *request)
978{
979 struct pp_hwmgr *hwmgr;
980 struct pp_instance *pp_handle = (struct pp_instance *)handle;
981 int ret = -1;
982
983 if (!request || pp_check(pp_handle))
984 return -EINVAL;
985
986 hwmgr = pp_handle->hwmgr;
987
988 if (hwmgr->hwmgr_func->set_power_profile_state == NULL) {
989 pr_info("%s was not implemented.\n", __func__);
990 return 0;
991 }
992
993 if (request->min_sclk ||
994 request->min_mclk ||
995 request->activity_threshold ||
996 request->up_hyst ||
997 request->down_hyst) {
998 if (request->type == AMD_PP_GFX_PROFILE)
999 memcpy(&hwmgr->gfx_power_profile, request,
1000 sizeof(struct amd_pp_profile));
1001 else if (request->type == AMD_PP_COMPUTE_PROFILE)
1002 memcpy(&hwmgr->compute_power_profile, request,
1003 sizeof(struct amd_pp_profile));
1004 else
1005 return -EINVAL;
1006
1007 if (request->type == hwmgr->current_power_profile)
1008 ret = hwmgr->hwmgr_func->set_power_profile_state(
1009 hwmgr,
1010 request);
1011 } else {
1012 /* set power profile if it exists */
1013 switch (request->type) {
1014 case AMD_PP_GFX_PROFILE:
1015 ret = hwmgr->hwmgr_func->set_power_profile_state(
1016 hwmgr,
1017 &hwmgr->gfx_power_profile);
1018 break;
1019 case AMD_PP_COMPUTE_PROFILE:
1020 ret = hwmgr->hwmgr_func->set_power_profile_state(
1021 hwmgr,
1022 &hwmgr->compute_power_profile);
1023 break;
1024 default:
1025 return -EINVAL;
1026 }
1027 }
1028
1029 if (!ret)
1030 hwmgr->current_power_profile = request->type;
1031
1032 return 0;
1033}
1034
1035static int pp_dpm_switch_power_profile(void *handle,
1036 enum amd_pp_profile_type type)
1037{
1038 struct pp_hwmgr *hwmgr;
1039 struct amd_pp_profile request = {0};
1040 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1041
1042 if (pp_check(pp_handle))
1043 return -EINVAL;
1044
1045 hwmgr = pp_handle->hwmgr;
1046
1047 if (hwmgr->current_power_profile != type) {
1048 request.type = type;
1049 pp_dpm_set_power_profile_state(handle, &request);
1050 }
1051
1052 return 0;
1053}
1054
Alex Deucher1f7371b2015-12-02 17:46:21 -05001055const struct amd_powerplay_funcs pp_dpm_funcs = {
Rex Zhucac9a192015-10-16 11:48:21 +08001056 .get_temperature = pp_dpm_get_temperature,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001057 .load_firmware = pp_dpm_load_fw,
1058 .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
1059 .force_performance_level = pp_dpm_force_performance_level,
1060 .get_performance_level = pp_dpm_get_performance_level,
1061 .get_current_power_state = pp_dpm_get_current_power_state,
1062 .get_sclk = pp_dpm_get_sclk,
1063 .get_mclk = pp_dpm_get_mclk,
1064 .powergate_vce = pp_dpm_powergate_vce,
1065 .powergate_uvd = pp_dpm_powergate_uvd,
1066 .dispatch_tasks = pp_dpm_dispatch_tasks,
Rex Zhucac9a192015-10-16 11:48:21 +08001067 .set_fan_control_mode = pp_dpm_set_fan_control_mode,
1068 .get_fan_control_mode = pp_dpm_get_fan_control_mode,
1069 .set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
1070 .get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
Grazvydas Ignotas72a16a92016-10-29 23:28:58 +03001071 .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
Eric Huangf3898ea2015-12-11 16:24:34 -05001072 .get_pp_num_states = pp_dpm_get_pp_num_states,
1073 .get_pp_table = pp_dpm_get_pp_table,
1074 .set_pp_table = pp_dpm_set_pp_table,
1075 .force_clock_level = pp_dpm_force_clock_level,
1076 .print_clock_levels = pp_dpm_print_clock_levels,
Eric Huang428bafa2016-05-12 14:51:21 -04001077 .get_sclk_od = pp_dpm_get_sclk_od,
1078 .set_sclk_od = pp_dpm_set_sclk_od,
Eric Huangf2bdc052016-05-24 15:11:17 -04001079 .get_mclk_od = pp_dpm_get_mclk_od,
1080 .set_mclk_od = pp_dpm_set_mclk_od,
Tom St Denisa6e36952016-09-15 10:07:34 -04001081 .read_sensor = pp_dpm_read_sensor,
Alex Deucher597be302016-10-07 13:52:43 -04001082 .get_vce_clock_state = pp_dpm_get_vce_clock_state,
Eric Huang34bb2732016-09-12 16:17:44 -04001083 .reset_power_profile_state = pp_dpm_reset_power_profile_state,
1084 .get_power_profile_state = pp_dpm_get_power_profile_state,
1085 .set_power_profile_state = pp_dpm_set_power_profile_state,
1086 .switch_power_profile = pp_dpm_switch_power_profile,
Alex Deucher1f7371b2015-12-02 17:46:21 -05001087};
1088
Rex Zhu1c863802016-12-28 19:43:23 +08001089int amd_powerplay_create(struct amd_pp_init *pp_init,
1090 void **handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001091{
Rex Zhu1c863802016-12-28 19:43:23 +08001092 struct pp_instance *instance;
Jammy Zhouac885b32015-07-21 17:43:02 +08001093
Rex Zhu1c863802016-12-28 19:43:23 +08001094 if (pp_init == NULL || handle == NULL)
1095 return -EINVAL;
1096
1097 instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
1098 if (instance == NULL)
Jammy Zhouac885b32015-07-21 17:43:02 +08001099 return -ENOMEM;
1100
Rex Zhu1c863802016-12-28 19:43:23 +08001101 instance->pp_valid = PP_VALID;
1102 instance->chip_family = pp_init->chip_family;
1103 instance->chip_id = pp_init->chip_id;
1104 instance->pm_en = pp_init->pm_en;
1105 instance->feature_mask = pp_init->feature_mask;
1106 instance->device = pp_init->device;
1107 *handle = instance;
Rex Zhue92a0372015-09-23 15:14:54 +08001108
Jammy Zhouac885b32015-07-21 17:43:02 +08001109 return 0;
1110}
1111
Rex Zhu1c863802016-12-28 19:43:23 +08001112int amd_powerplay_destroy(void *handle)
Jammy Zhouac885b32015-07-21 17:43:02 +08001113{
1114 struct pp_instance *instance = (struct pp_instance *)handle;
Rex Zhue92a0372015-09-23 15:14:54 +08001115
Rex Zhu1c863802016-12-28 19:43:23 +08001116 if (instance->pm_en) {
1117 kfree(instance->eventmgr);
1118 kfree(instance->hwmgr);
1119 instance->hwmgr = NULL;
1120 instance->eventmgr = NULL;
Rex Zhuba5f8842016-10-27 15:29:57 +08001121 }
Jammy Zhou3bace352015-07-21 21:18:15 +08001122
Rex Zhu1c863802016-12-28 19:43:23 +08001123 kfree(instance->smu_mgr);
1124 instance->smu_mgr = NULL;
1125 kfree(instance);
1126 instance = NULL;
Alex Deucher1f7371b2015-12-02 17:46:21 -05001127 return 0;
1128}
Rex Zhu7fb72a12015-11-19 13:35:30 +08001129
Eric Huang4dcf9e62016-06-01 17:08:07 -04001130int amd_powerplay_reset(void *handle)
1131{
1132 struct pp_instance *instance = (struct pp_instance *)handle;
1133 struct pp_eventmgr *eventmgr;
1134 struct pem_event_data event_data = { {0} };
1135 int ret;
1136
Rex Zhu1c863802016-12-28 19:43:23 +08001137 if (cgs_is_virtualization_enabled(instance->smu_mgr->device))
1138 return PP_DPM_DISABLED;
1139
1140 ret = pp_check(instance);
1141 if (ret != 0)
1142 return ret;
1143
1144 ret = pp_hw_fini(handle);
1145 if (ret)
1146 return ret;
1147
1148 ret = hwmgr_hw_init(instance);
1149 if (ret)
1150 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001151
1152 eventmgr = instance->eventmgr;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001153
Rex Zhu1c863802016-12-28 19:43:23 +08001154 if (eventmgr->pp_eventmgr_init == NULL)
1155 return PP_DPM_DISABLED;
Eric Huang4dcf9e62016-06-01 17:08:07 -04001156
1157 ret = eventmgr->pp_eventmgr_init(eventmgr);
1158 if (ret)
1159 return ret;
1160
1161 return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
1162}
1163
Rex Zhu7fb72a12015-11-19 13:35:30 +08001164/* export this function to DAL */
1165
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001166int amd_powerplay_display_configuration_change(void *handle,
1167 const struct amd_pp_display_configuration *display_config)
Rex Zhu7fb72a12015-11-19 13:35:30 +08001168{
1169 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001170 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1171 int ret = 0;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001172
Rex Zhu1c863802016-12-28 19:43:23 +08001173 ret = pp_check(pp_handle);
Rex Zhu7fb72a12015-11-19 13:35:30 +08001174
Rex Zhu1c863802016-12-28 19:43:23 +08001175 if (ret != 0)
1176 return ret;
Rex Zhu7fb72a12015-11-19 13:35:30 +08001177
Rex Zhu1c863802016-12-28 19:43:23 +08001178 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001179
Rex Zhu7fb72a12015-11-19 13:35:30 +08001180 phm_store_dal_configuration_data(hwmgr, display_config);
Rex Zhue0b71a72015-12-29 10:25:19 +08001181
Rex Zhu7fb72a12015-11-19 13:35:30 +08001182 return 0;
1183}
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001184
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001185int amd_powerplay_get_display_power_level(void *handle,
Rex Zhu47329132015-12-10 16:49:50 +08001186 struct amd_pp_simple_clock_info *output)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001187{
1188 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001189 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1190 int ret = 0;
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001191
Rex Zhu1c863802016-12-28 19:43:23 +08001192 ret = pp_check(pp_handle);
1193
1194 if (ret != 0)
1195 return ret;
1196
1197 hwmgr = pp_handle->hwmgr;
Rex Zhua969e162015-12-29 13:56:03 +08001198
1199 if (output == NULL)
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001200 return -EINVAL;
1201
Vitaly Prosyak1c9a9082015-12-03 10:27:57 -05001202 return phm_get_dal_power_level(hwmgr, output);
Vitaly Prosyakc4dd2062015-11-30 16:39:53 -05001203}
Rex Zhue273b042015-12-07 18:44:23 +08001204
1205int amd_powerplay_get_current_clocks(void *handle,
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001206 struct amd_pp_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001207{
Rex Zhue273b042015-12-07 18:44:23 +08001208 struct amd_pp_simple_clock_info simple_clocks;
1209 struct pp_clock_info hw_clocks;
Rex Zhu1c863802016-12-28 19:43:23 +08001210 struct pp_hwmgr *hwmgr;
1211 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1212 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001213
Rex Zhu1c863802016-12-28 19:43:23 +08001214 ret = pp_check(pp_handle);
Rex Zhufa9e6992015-12-29 13:56:03 +08001215
Rex Zhu1c863802016-12-28 19:43:23 +08001216 if (ret != 0)
1217 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001218
Rex Zhu1c863802016-12-28 19:43:23 +08001219 hwmgr = pp_handle->hwmgr;
Rex Zhuba5f8842016-10-27 15:29:57 +08001220
Rex Zhue273b042015-12-07 18:44:23 +08001221 phm_get_dal_power_level(hwmgr, &simple_clocks);
1222
1223 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
1224 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment))
1225 PP_ASSERT_WITH_CODE(0, "Error in PHM_GetPowerContainmentClockInfo", return -1);
1226 } else {
1227 if (0 != phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity))
1228 PP_ASSERT_WITH_CODE(0, "Error in PHM_GetClockInfo", return -1);
1229 }
1230
1231 clocks->min_engine_clock = hw_clocks.min_eng_clk;
1232 clocks->max_engine_clock = hw_clocks.max_eng_clk;
1233 clocks->min_memory_clock = hw_clocks.min_mem_clk;
1234 clocks->max_memory_clock = hw_clocks.max_mem_clk;
1235 clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
1236 clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
1237
1238 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1239 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1240
1241 clocks->max_clocks_state = simple_clocks.level;
1242
1243 if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) {
1244 clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
1245 clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
1246 }
1247
1248 return 0;
1249
1250}
1251
1252int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
1253{
1254 int result = -1;
Rex Zhu1c863802016-12-28 19:43:23 +08001255 struct pp_hwmgr *hwmgr;
1256 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1257 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001258
Rex Zhu1c863802016-12-28 19:43:23 +08001259 ret = pp_check(pp_handle);
Rex Zhue273b042015-12-07 18:44:23 +08001260
Rex Zhu1c863802016-12-28 19:43:23 +08001261 if (ret != 0)
1262 return ret;
1263
1264 hwmgr = pp_handle->hwmgr;
Rex Zhufa9e6992015-12-29 13:56:03 +08001265
1266 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001267 return -EINVAL;
1268
Rex Zhue273b042015-12-07 18:44:23 +08001269 result = phm_get_clock_by_type(hwmgr, type, clocks);
1270
1271 return result;
1272}
1273
David Rokhvarg155f1127c2015-12-14 10:51:39 -05001274int amd_powerplay_get_display_mode_validation_clocks(void *handle,
1275 struct amd_pp_simple_clock_info *clocks)
Rex Zhue273b042015-12-07 18:44:23 +08001276{
Rex Zhue273b042015-12-07 18:44:23 +08001277 struct pp_hwmgr *hwmgr;
Rex Zhu1c863802016-12-28 19:43:23 +08001278 struct pp_instance *pp_handle = (struct pp_instance *)handle;
1279 int ret = 0;
Rex Zhue273b042015-12-07 18:44:23 +08001280
Rex Zhu1c863802016-12-28 19:43:23 +08001281 ret = pp_check(pp_handle);
1282
1283 if (ret != 0)
1284 return ret;
1285
1286 hwmgr = pp_handle->hwmgr;
1287
Rex Zhufa9e6992015-12-29 13:56:03 +08001288
1289 if (clocks == NULL)
Rex Zhue273b042015-12-07 18:44:23 +08001290 return -EINVAL;
1291
Rex Zhue273b042015-12-07 18:44:23 +08001292 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
Rex Zhu1c863802016-12-28 19:43:23 +08001293 ret = phm_get_max_high_clocks(hwmgr, clocks);
Rex Zhue273b042015-12-07 18:44:23 +08001294
Rex Zhu1c863802016-12-28 19:43:23 +08001295 return ret;
Rex Zhue273b042015-12-07 18:44:23 +08001296}
1297