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