drm/amd/powerplay: add basic powerplay framework
[linux-2.6-block.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_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  * Authors: AMD
23  *
24  */
25 #include "atom.h"
26 #include "amdgpu.h"
27 #include "amd_shared.h"
28 #include <linux/module.h>
29 #include <linux/moduleparam.h>
30 #include "amdgpu_pm.h"
31 #include <drm/amdgpu_drm.h>
32 #include "amdgpu_powerplay.h"
33 #include "cik_dpm.h"
34 #include "vi_dpm.h"
35
36 static int amdgpu_powerplay_init(struct amdgpu_device *adev)
37 {
38         int ret = 0;
39         struct amd_powerplay *amd_pp;
40
41         amd_pp = &(adev->powerplay);
42
43         if (amdgpu_powerplay) {
44 #ifdef CONFIG_DRM_AMD_POWERPLAY
45                 struct amd_pp_init *pp_init;
46
47                 pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL);
48
49                 if (pp_init == NULL)
50                         return -ENOMEM;
51
52                 pp_init->chip_family = adev->family;
53                 pp_init->chip_id = adev->asic_type;
54                 pp_init->device = amdgpu_cgs_create_device(adev);
55
56                 ret = amd_powerplay_init(pp_init, amd_pp);
57                 kfree(pp_init);
58 #endif
59         } else {
60                 amd_pp->pp_handle = (void *)adev;
61
62                 switch (adev->asic_type) {
63 #ifdef CONFIG_DRM_AMDGPU_CIK
64                 case CHIP_BONAIRE:
65                 case CHIP_HAWAII:
66                         amd_pp->ip_funcs = &ci_dpm_ip_funcs;
67                         break;
68                 case CHIP_KABINI:
69                 case CHIP_MULLINS:
70                 case CHIP_KAVERI:
71                         amd_pp->ip_funcs = &kv_dpm_ip_funcs;
72                         break;
73 #endif
74                 case CHIP_TOPAZ:
75                         amd_pp->ip_funcs = &iceland_dpm_ip_funcs;
76                         break;
77                 case CHIP_TONGA:
78                         amd_pp->ip_funcs = &tonga_dpm_ip_funcs;
79                         break;
80                 case CHIP_CARRIZO:
81                         amd_pp->ip_funcs = &cz_dpm_ip_funcs;
82                         break;
83                 default:
84                         ret = -EINVAL;
85                         break;
86                 }
87         }
88         return ret;
89 }
90
91 static int amdgpu_pp_early_init(void *handle)
92 {
93         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
94         int ret = 0;
95
96         ret = amdgpu_powerplay_init(adev);
97         if (ret)
98                 return ret;
99
100         if (adev->powerplay.ip_funcs->early_init)
101                 ret = adev->powerplay.ip_funcs->early_init(
102                                         adev->powerplay.pp_handle);
103         return ret;
104 }
105
106 static int amdgpu_pp_sw_init(void *handle)
107 {
108         int ret = 0;
109         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
110
111         if (adev->powerplay.ip_funcs->sw_init)
112                 ret = adev->powerplay.ip_funcs->sw_init(
113                                         adev->powerplay.pp_handle);
114
115 #ifdef CONFIG_DRM_AMD_POWERPLAY
116         if (amdgpu_powerplay) {
117                 adev->pm.dpm_enabled = true;
118                 amdgpu_pm_sysfs_init(adev);
119         }
120 #endif
121
122         return ret;
123 }
124
125 static int amdgpu_pp_sw_fini(void *handle)
126 {
127         int ret = 0;
128         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
129
130         if (adev->powerplay.ip_funcs->sw_fini)
131                 ret = adev->powerplay.ip_funcs->sw_fini(
132                                         adev->powerplay.pp_handle);
133         if (ret)
134                 return ret;
135
136 #ifdef CONFIG_DRM_AMD_POWERPLAY
137         if (amdgpu_powerplay) {
138                 amdgpu_pm_sysfs_fini(adev);
139                 amd_powerplay_fini(adev->powerplay.pp_handle);
140         }
141 #endif
142
143         return ret;
144 }
145
146 static int amdgpu_pp_hw_init(void *handle)
147 {
148         int ret = 0;
149         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
150
151         if (amdgpu_powerplay && adev->firmware.smu_load)
152                 amdgpu_ucode_init_bo(adev);
153
154         if (adev->powerplay.ip_funcs->hw_init)
155                 ret = adev->powerplay.ip_funcs->hw_init(
156                                         adev->powerplay.pp_handle);
157
158         return ret;
159 }
160
161 static int amdgpu_pp_hw_fini(void *handle)
162 {
163         int ret = 0;
164         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
165
166         if (adev->powerplay.ip_funcs->hw_fini)
167                 ret = adev->powerplay.ip_funcs->hw_fini(
168                                         adev->powerplay.pp_handle);
169
170         if (amdgpu_powerplay && adev->firmware.smu_load)
171                 amdgpu_ucode_fini_bo(adev);
172
173         return ret;
174 }
175
176 static int amdgpu_pp_suspend(void *handle)
177 {
178         int ret = 0;
179         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
180
181         if (adev->powerplay.ip_funcs->suspend)
182                 ret = adev->powerplay.ip_funcs->suspend(
183                                          adev->powerplay.pp_handle);
184         return ret;
185 }
186
187 static int amdgpu_pp_resume(void *handle)
188 {
189         int ret = 0;
190         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
191
192         if (adev->powerplay.ip_funcs->resume)
193                 ret = adev->powerplay.ip_funcs->resume(
194                                         adev->powerplay.pp_handle);
195         return ret;
196 }
197
198 static int amdgpu_pp_set_clockgating_state(void *handle,
199                                         enum amd_clockgating_state state)
200 {
201         int ret = 0;
202         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
203
204         if (adev->powerplay.ip_funcs->set_clockgating_state)
205                 ret = adev->powerplay.ip_funcs->set_clockgating_state(
206                                 adev->powerplay.pp_handle, state);
207         return ret;
208 }
209
210 static int amdgpu_pp_set_powergating_state(void *handle,
211                                         enum amd_powergating_state state)
212 {
213         int ret = 0;
214         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
215
216         if (adev->powerplay.ip_funcs->set_powergating_state)
217                 ret = adev->powerplay.ip_funcs->set_powergating_state(
218                                  adev->powerplay.pp_handle, state);
219         return ret;
220 }
221
222
223 static bool amdgpu_pp_is_idle(void *handle)
224 {
225         bool ret = true;
226         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
227
228         if (adev->powerplay.ip_funcs->is_idle)
229                 ret = adev->powerplay.ip_funcs->is_idle(
230                                         adev->powerplay.pp_handle);
231         return ret;
232 }
233
234 static int amdgpu_pp_wait_for_idle(void *handle)
235 {
236         int ret = 0;
237         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
238
239         if (adev->powerplay.ip_funcs->wait_for_idle)
240                 ret = adev->powerplay.ip_funcs->wait_for_idle(
241                                         adev->powerplay.pp_handle);
242         return ret;
243 }
244
245 static int amdgpu_pp_soft_reset(void *handle)
246 {
247         int ret = 0;
248         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
249
250         if (adev->powerplay.ip_funcs->soft_reset)
251                 ret = adev->powerplay.ip_funcs->soft_reset(
252                                         adev->powerplay.pp_handle);
253         return ret;
254 }
255
256 static void amdgpu_pp_print_status(void *handle)
257 {
258         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
259
260         if (adev->powerplay.ip_funcs->print_status)
261                 adev->powerplay.ip_funcs->print_status(
262                                         adev->powerplay.pp_handle);
263 }
264
265 const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
266         .early_init = amdgpu_pp_early_init,
267         .late_init = NULL,
268         .sw_init = amdgpu_pp_sw_init,
269         .sw_fini = amdgpu_pp_sw_fini,
270         .hw_init = amdgpu_pp_hw_init,
271         .hw_fini = amdgpu_pp_hw_fini,
272         .suspend = amdgpu_pp_suspend,
273         .resume = amdgpu_pp_resume,
274         .is_idle = amdgpu_pp_is_idle,
275         .wait_for_idle = amdgpu_pp_wait_for_idle,
276         .soft_reset = amdgpu_pp_soft_reset,
277         .print_status = amdgpu_pp_print_status,
278         .set_clockgating_state = amdgpu_pp_set_clockgating_state,
279         .set_powergating_state = amdgpu_pp_set_powergating_state,
280 };