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