drm/amd/powerplay: add event manager sub-component
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / amd_powerplay.c
1 /*
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  */
23 #include <linux/types.h>
24 #include <linux/kernel.h>
25 #include <linux/gfp.h>
26 #include <linux/slab.h>
27 #include "amd_shared.h"
28 #include "amd_powerplay.h"
29 #include "pp_instance.h"
30
31 static int pp_early_init(void *handle)
32 {
33         return 0;
34 }
35
36 static int pp_sw_init(void *handle)
37 {
38         struct pp_instance *pp_handle;
39         struct pp_hwmgr  *hwmgr;
40         int ret = 0;
41
42         if (handle == NULL)
43                 return -EINVAL;
44
45         pp_handle = (struct pp_instance *)handle;
46         hwmgr = pp_handle->hwmgr;
47
48         if (hwmgr == NULL || hwmgr->pptable_func == NULL ||
49             hwmgr->hwmgr_func == NULL ||
50             hwmgr->pptable_func->pptable_init == NULL ||
51             hwmgr->hwmgr_func->backend_init == NULL)
52                 return -EINVAL;
53
54         ret = hwmgr->pptable_func->pptable_init(hwmgr);
55
56         if (ret == 0)
57                 ret = hwmgr->hwmgr_func->backend_init(hwmgr);
58
59         return ret;
60 }
61
62 static int pp_sw_fini(void *handle)
63 {
64         struct pp_instance *pp_handle;
65         struct pp_hwmgr  *hwmgr;
66         int ret = 0;
67
68         if (handle == NULL)
69                 return -EINVAL;
70
71         pp_handle = (struct pp_instance *)handle;
72         hwmgr = pp_handle->hwmgr;
73
74         if (hwmgr != NULL || hwmgr->hwmgr_func != NULL ||
75             hwmgr->hwmgr_func->backend_fini != NULL)
76                 ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
77
78         return ret;
79 }
80
81 static int pp_hw_init(void *handle)
82 {
83         struct pp_instance *pp_handle;
84         struct pp_smumgr *smumgr;
85         struct pp_eventmgr *eventmgr;
86         int ret = 0;
87
88         if (handle == NULL)
89                 return -EINVAL;
90
91         pp_handle = (struct pp_instance *)handle;
92         smumgr = pp_handle->smu_mgr;
93
94         if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
95                 smumgr->smumgr_funcs->smu_init == NULL ||
96                 smumgr->smumgr_funcs->start_smu == NULL)
97                 return -EINVAL;
98
99         ret = smumgr->smumgr_funcs->smu_init(smumgr);
100         if (ret) {
101                 printk(KERN_ERR "[ powerplay ] smc initialization failed\n");
102                 return ret;
103         }
104
105         ret = smumgr->smumgr_funcs->start_smu(smumgr);
106         if (ret) {
107                 printk(KERN_ERR "[ powerplay ] smc start failed\n");
108                 smumgr->smumgr_funcs->smu_fini(smumgr);
109                 return ret;
110         }
111
112         hw_init_power_state_table(pp_handle->hwmgr);
113         eventmgr = pp_handle->eventmgr;
114
115         if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
116                 return -EINVAL;
117
118         ret = eventmgr->pp_eventmgr_init(eventmgr);
119         return 0;
120 }
121
122 static int pp_hw_fini(void *handle)
123 {
124         struct pp_instance *pp_handle;
125         struct pp_smumgr *smumgr;
126         struct pp_eventmgr *eventmgr;
127
128         if (handle == NULL)
129                 return -EINVAL;
130
131         pp_handle = (struct pp_instance *)handle;
132         eventmgr = pp_handle->eventmgr;
133
134         if (eventmgr != NULL || eventmgr->pp_eventmgr_fini != NULL)
135                 eventmgr->pp_eventmgr_fini(eventmgr);
136
137         smumgr = pp_handle->smu_mgr;
138
139         if (smumgr != NULL || smumgr->smumgr_funcs != NULL ||
140                 smumgr->smumgr_funcs->smu_fini != NULL)
141                 smumgr->smumgr_funcs->smu_fini(smumgr);
142
143         return 0;
144 }
145
146 static bool pp_is_idle(void *handle)
147 {
148         return 0;
149 }
150
151 static int pp_wait_for_idle(void *handle)
152 {
153         return 0;
154 }
155
156 static int pp_sw_reset(void *handle)
157 {
158         return 0;
159 }
160
161 static void pp_print_status(void *handle)
162 {
163
164 }
165
166 static int pp_set_clockgating_state(void *handle,
167                                     enum amd_clockgating_state state)
168 {
169         return 0;
170 }
171
172 static int pp_set_powergating_state(void *handle,
173                                     enum amd_powergating_state state)
174 {
175         return 0;
176 }
177
178 static int pp_suspend(void *handle)
179 {
180         return 0;
181 }
182
183 static int pp_resume(void *handle)
184 {
185         return 0;
186 }
187
188 const struct amd_ip_funcs pp_ip_funcs = {
189         .early_init = pp_early_init,
190         .late_init = NULL,
191         .sw_init = pp_sw_init,
192         .sw_fini = pp_sw_fini,
193         .hw_init = pp_hw_init,
194         .hw_fini = pp_hw_fini,
195         .suspend = pp_suspend,
196         .resume = pp_resume,
197         .is_idle = pp_is_idle,
198         .wait_for_idle = pp_wait_for_idle,
199         .soft_reset = pp_sw_reset,
200         .print_status = pp_print_status,
201         .set_clockgating_state = pp_set_clockgating_state,
202         .set_powergating_state = pp_set_powergating_state,
203 };
204
205 static int pp_dpm_load_fw(void *handle)
206 {
207         return 0;
208 }
209
210 static int pp_dpm_fw_loading_complete(void *handle)
211 {
212         return 0;
213 }
214
215 static int pp_dpm_force_performance_level(void *handle,
216                                         enum amd_dpm_forced_level level)
217 {
218         return 0;
219 }
220 static enum amd_dpm_forced_level pp_dpm_get_performance_level(
221                                                                 void *handle)
222 {
223         return 0;
224 }
225 static int pp_dpm_get_sclk(void *handle, bool low)
226 {
227         return 0;
228 }
229 static int pp_dpm_get_mclk(void *handle, bool low)
230 {
231         return 0;
232 }
233 static int pp_dpm_powergate_vce(void *handle, bool gate)
234 {
235         return 0;
236 }
237 static int pp_dpm_powergate_uvd(void *handle, bool gate)
238 {
239         return 0;
240 }
241
242 int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output)
243 {
244         return 0;
245 }
246 enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
247 {
248         return 0;
249 }
250 static void
251 pp_debugfs_print_current_performance_level(void *handle,
252                                                struct seq_file *m)
253 {
254         return;
255 }
256
257 const struct amd_powerplay_funcs pp_dpm_funcs = {
258         .get_temperature = NULL,
259         .load_firmware = pp_dpm_load_fw,
260         .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
261         .force_performance_level = pp_dpm_force_performance_level,
262         .get_performance_level = pp_dpm_get_performance_level,
263         .get_current_power_state = pp_dpm_get_current_power_state,
264         .get_sclk = pp_dpm_get_sclk,
265         .get_mclk = pp_dpm_get_mclk,
266         .powergate_vce = pp_dpm_powergate_vce,
267         .powergate_uvd = pp_dpm_powergate_uvd,
268         .dispatch_tasks = pp_dpm_dispatch_tasks,
269         .print_current_performance_level = pp_debugfs_print_current_performance_level,
270 };
271
272 static int amd_pp_instance_init(struct amd_pp_init *pp_init,
273                                 struct amd_powerplay *amd_pp)
274 {
275         int ret;
276         struct pp_instance *handle;
277
278         handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL);
279         if (handle == NULL)
280                 return -ENOMEM;
281
282         ret = smum_init(pp_init, handle);
283         if (ret)
284                 goto fail_smum;
285
286         ret = hwmgr_init(pp_init, handle);
287         if (ret)
288                 goto fail_hwmgr;
289
290         ret = eventmgr_init(handle);
291         if (ret)
292                 goto fail_eventmgr;
293
294         amd_pp->pp_handle = handle;
295         return 0;
296
297 fail_eventmgr:
298         hwmgr_fini(handle->hwmgr);
299 fail_hwmgr:
300         smum_fini(handle->smu_mgr);
301 fail_smum:
302         kfree(handle);
303         return ret;
304 }
305
306 static int amd_pp_instance_fini(void *handle)
307 {
308         struct pp_instance *instance = (struct pp_instance *)handle;
309
310         if (instance == NULL)
311                 return -EINVAL;
312
313         eventmgr_fini(instance->eventmgr);
314
315         hwmgr_fini(instance->hwmgr);
316
317         smum_fini(instance->smu_mgr);
318
319         kfree(handle);
320         return 0;
321 }
322
323 int amd_powerplay_init(struct amd_pp_init *pp_init,
324                        struct amd_powerplay *amd_pp)
325 {
326         int ret;
327
328         if (pp_init == NULL || amd_pp == NULL)
329                 return -EINVAL;
330
331         ret = amd_pp_instance_init(pp_init, amd_pp);
332
333         if (ret)
334                 return ret;
335
336         amd_pp->ip_funcs = &pp_ip_funcs;
337         amd_pp->pp_funcs = &pp_dpm_funcs;
338
339         return 0;
340 }
341
342 int amd_powerplay_fini(void *handle)
343 {
344         amd_pp_instance_fini(handle);
345
346         return 0;
347 }