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