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