]>
Commit | Line | Data |
---|---|---|
1f7371b2 AD |
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 | ||
e61710c5 | 43 | if (adev->pp_enabled) { |
1f7371b2 AD |
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; | |
899fa4c0 EH |
80 | case CHIP_FIJI: |
81 | amd_pp->ip_funcs = &fiji_dpm_ip_funcs; | |
82 | break; | |
1f7371b2 | 83 | case CHIP_CARRIZO: |
9c97e75f | 84 | case CHIP_STONEY: |
1f7371b2 AD |
85 | amd_pp->ip_funcs = &cz_dpm_ip_funcs; |
86 | break; | |
87 | default: | |
88 | ret = -EINVAL; | |
89 | break; | |
90 | } | |
91 | } | |
92 | return ret; | |
93 | } | |
94 | ||
95 | static int amdgpu_pp_early_init(void *handle) | |
96 | { | |
97 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
98 | int ret = 0; | |
99 | ||
edb611c1 | 100 | #ifdef CONFIG_DRM_AMD_POWERPLAY |
76c8cc6b | 101 | switch (adev->asic_type) { |
2cc0c0b5 FC |
102 | case CHIP_POLARIS11: |
103 | case CHIP_POLARIS10: | |
104 | adev->pp_enabled = true; | |
105 | break; | |
3466904d JL |
106 | case CHIP_TONGA: |
107 | case CHIP_FIJI: | |
108 | adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true; | |
109 | break; | |
110 | case CHIP_CARRIZO: | |
111 | case CHIP_STONEY: | |
112 | adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; | |
113 | break; | |
114 | /* These chips don't have powerplay implemenations */ | |
115 | case CHIP_BONAIRE: | |
116 | case CHIP_HAWAII: | |
117 | case CHIP_KABINI: | |
118 | case CHIP_MULLINS: | |
119 | case CHIP_KAVERI: | |
120 | case CHIP_TOPAZ: | |
121 | default: | |
122 | adev->pp_enabled = false; | |
123 | break; | |
76c8cc6b | 124 | } |
e61710c5 JZ |
125 | #else |
126 | adev->pp_enabled = false; | |
edb611c1 | 127 | #endif |
76c8cc6b | 128 | |
1f7371b2 AD |
129 | ret = amdgpu_powerplay_init(adev); |
130 | if (ret) | |
131 | return ret; | |
132 | ||
133 | if (adev->powerplay.ip_funcs->early_init) | |
134 | ret = adev->powerplay.ip_funcs->early_init( | |
135 | adev->powerplay.pp_handle); | |
136 | return ret; | |
137 | } | |
138 | ||
7ad4e7f0 RZ |
139 | |
140 | static int amdgpu_pp_late_init(void *handle) | |
141 | { | |
142 | int ret = 0; | |
143 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
144 | ||
145 | if (adev->powerplay.ip_funcs->late_init) | |
146 | ret = adev->powerplay.ip_funcs->late_init( | |
147 | adev->powerplay.pp_handle); | |
148 | ||
898b1dea | 149 | #ifdef CONFIG_DRM_AMD_POWERPLAY |
5349ece7 | 150 | if (adev->pp_enabled && adev->pm.dpm_enabled) { |
898b1dea | 151 | amdgpu_pm_sysfs_init(adev); |
4ea2efae RZ |
152 | amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL); |
153 | } | |
898b1dea | 154 | #endif |
7ad4e7f0 RZ |
155 | return ret; |
156 | } | |
157 | ||
1f7371b2 AD |
158 | static int amdgpu_pp_sw_init(void *handle) |
159 | { | |
160 | int ret = 0; | |
161 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
162 | ||
163 | if (adev->powerplay.ip_funcs->sw_init) | |
164 | ret = adev->powerplay.ip_funcs->sw_init( | |
165 | adev->powerplay.pp_handle); | |
166 | ||
167 | #ifdef CONFIG_DRM_AMD_POWERPLAY | |
1587f6e4 RZ |
168 | if (adev->pp_enabled) |
169 | adev->pm.dpm_enabled = true; | |
1f7371b2 AD |
170 | #endif |
171 | ||
172 | return ret; | |
173 | } | |
174 | ||
175 | static int amdgpu_pp_sw_fini(void *handle) | |
176 | { | |
177 | int ret = 0; | |
178 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
179 | ||
180 | if (adev->powerplay.ip_funcs->sw_fini) | |
181 | ret = adev->powerplay.ip_funcs->sw_fini( | |
182 | adev->powerplay.pp_handle); | |
183 | if (ret) | |
184 | return ret; | |
185 | ||
1f7371b2 AD |
186 | return ret; |
187 | } | |
188 | ||
189 | static int amdgpu_pp_hw_init(void *handle) | |
190 | { | |
191 | int ret = 0; | |
192 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
193 | ||
e61710c5 | 194 | if (adev->pp_enabled && adev->firmware.smu_load) |
1f7371b2 AD |
195 | amdgpu_ucode_init_bo(adev); |
196 | ||
197 | if (adev->powerplay.ip_funcs->hw_init) | |
198 | ret = adev->powerplay.ip_funcs->hw_init( | |
199 | adev->powerplay.pp_handle); | |
200 | ||
201 | return ret; | |
202 | } | |
203 | ||
204 | static int amdgpu_pp_hw_fini(void *handle) | |
205 | { | |
206 | int ret = 0; | |
207 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
208 | ||
209 | if (adev->powerplay.ip_funcs->hw_fini) | |
210 | ret = adev->powerplay.ip_funcs->hw_fini( | |
211 | adev->powerplay.pp_handle); | |
212 | ||
e61710c5 | 213 | if (adev->pp_enabled && adev->firmware.smu_load) |
1f7371b2 AD |
214 | amdgpu_ucode_fini_bo(adev); |
215 | ||
216 | return ret; | |
217 | } | |
218 | ||
482587e3 ML |
219 | static void amdgpu_pp_late_fini(void *handle) |
220 | { | |
29ccf759 | 221 | #ifdef CONFIG_DRM_AMD_POWERPLAY |
482587e3 ML |
222 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
223 | ||
482587e3 ML |
224 | if (adev->pp_enabled) { |
225 | amdgpu_pm_sysfs_fini(adev); | |
226 | amd_powerplay_fini(adev->powerplay.pp_handle); | |
227 | } | |
228 | ||
229 | if (adev->powerplay.ip_funcs->late_fini) | |
230 | adev->powerplay.ip_funcs->late_fini( | |
231 | adev->powerplay.pp_handle); | |
232 | #endif | |
233 | } | |
234 | ||
1f7371b2 AD |
235 | static int amdgpu_pp_suspend(void *handle) |
236 | { | |
237 | int ret = 0; | |
238 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
239 | ||
240 | if (adev->powerplay.ip_funcs->suspend) | |
241 | ret = adev->powerplay.ip_funcs->suspend( | |
242 | adev->powerplay.pp_handle); | |
243 | return ret; | |
244 | } | |
245 | ||
246 | static int amdgpu_pp_resume(void *handle) | |
247 | { | |
248 | int ret = 0; | |
249 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
250 | ||
251 | if (adev->powerplay.ip_funcs->resume) | |
252 | ret = adev->powerplay.ip_funcs->resume( | |
253 | adev->powerplay.pp_handle); | |
254 | return ret; | |
255 | } | |
256 | ||
257 | static int amdgpu_pp_set_clockgating_state(void *handle, | |
258 | enum amd_clockgating_state state) | |
259 | { | |
260 | int ret = 0; | |
261 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
262 | ||
263 | if (adev->powerplay.ip_funcs->set_clockgating_state) | |
264 | ret = adev->powerplay.ip_funcs->set_clockgating_state( | |
265 | adev->powerplay.pp_handle, state); | |
266 | return ret; | |
267 | } | |
268 | ||
269 | static int amdgpu_pp_set_powergating_state(void *handle, | |
270 | enum amd_powergating_state state) | |
271 | { | |
272 | int ret = 0; | |
273 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
274 | ||
275 | if (adev->powerplay.ip_funcs->set_powergating_state) | |
276 | ret = adev->powerplay.ip_funcs->set_powergating_state( | |
277 | adev->powerplay.pp_handle, state); | |
278 | return ret; | |
279 | } | |
280 | ||
281 | ||
282 | static bool amdgpu_pp_is_idle(void *handle) | |
283 | { | |
284 | bool ret = true; | |
285 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
286 | ||
287 | if (adev->powerplay.ip_funcs->is_idle) | |
288 | ret = adev->powerplay.ip_funcs->is_idle( | |
289 | adev->powerplay.pp_handle); | |
290 | return ret; | |
291 | } | |
292 | ||
293 | static int amdgpu_pp_wait_for_idle(void *handle) | |
294 | { | |
295 | int ret = 0; | |
296 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
297 | ||
298 | if (adev->powerplay.ip_funcs->wait_for_idle) | |
299 | ret = adev->powerplay.ip_funcs->wait_for_idle( | |
300 | adev->powerplay.pp_handle); | |
301 | return ret; | |
302 | } | |
303 | ||
304 | static int amdgpu_pp_soft_reset(void *handle) | |
305 | { | |
306 | int ret = 0; | |
307 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | |
308 | ||
309 | if (adev->powerplay.ip_funcs->soft_reset) | |
310 | ret = adev->powerplay.ip_funcs->soft_reset( | |
311 | adev->powerplay.pp_handle); | |
312 | return ret; | |
313 | } | |
314 | ||
1f7371b2 | 315 | const struct amd_ip_funcs amdgpu_pp_ip_funcs = { |
88a907d6 | 316 | .name = "amdgpu_powerplay", |
1f7371b2 | 317 | .early_init = amdgpu_pp_early_init, |
7ad4e7f0 | 318 | .late_init = amdgpu_pp_late_init, |
1f7371b2 AD |
319 | .sw_init = amdgpu_pp_sw_init, |
320 | .sw_fini = amdgpu_pp_sw_fini, | |
321 | .hw_init = amdgpu_pp_hw_init, | |
322 | .hw_fini = amdgpu_pp_hw_fini, | |
482587e3 | 323 | .late_fini = amdgpu_pp_late_fini, |
1f7371b2 AD |
324 | .suspend = amdgpu_pp_suspend, |
325 | .resume = amdgpu_pp_resume, | |
326 | .is_idle = amdgpu_pp_is_idle, | |
327 | .wait_for_idle = amdgpu_pp_wait_for_idle, | |
328 | .soft_reset = amdgpu_pp_soft_reset, | |
1f7371b2 AD |
329 | .set_clockgating_state = amdgpu_pp_set_clockgating_state, |
330 | .set_powergating_state = amdgpu_pp_set_powergating_state, | |
331 | }; |