blob: ecc4141cd7163251cbac7fa1b2b9cee966980118 [file] [log] [blame]
Alex Deucher1f7371b2015-12-02 17:46:21 -05001/*
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
36static 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
Jammy Zhoue61710c2015-11-10 18:31:08 -050043 if (adev->pp_enabled) {
Alex Deucher1f7371b2015-12-02 17:46:21 -050044#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);
Alex Deucher1f7371b2015-12-02 17:46:21 -050055 ret = amd_powerplay_init(pp_init, amd_pp);
56 kfree(pp_init);
57#endif
58 } else {
59 amd_pp->pp_handle = (void *)adev;
60
61 switch (adev->asic_type) {
62#ifdef CONFIG_DRM_AMDGPU_CIK
63 case CHIP_BONAIRE:
64 case CHIP_HAWAII:
65 amd_pp->ip_funcs = &ci_dpm_ip_funcs;
66 break;
67 case CHIP_KABINI:
68 case CHIP_MULLINS:
69 case CHIP_KAVERI:
70 amd_pp->ip_funcs = &kv_dpm_ip_funcs;
71 break;
72#endif
73 case CHIP_TOPAZ:
74 amd_pp->ip_funcs = &iceland_dpm_ip_funcs;
75 break;
76 case CHIP_TONGA:
77 amd_pp->ip_funcs = &tonga_dpm_ip_funcs;
78 break;
Eric Huang899fa4c2015-09-29 14:58:53 -040079 case CHIP_FIJI:
80 amd_pp->ip_funcs = &fiji_dpm_ip_funcs;
81 break;
Alex Deucher1f7371b2015-12-02 17:46:21 -050082 case CHIP_CARRIZO:
Tom St Denis9c97e752015-11-20 13:33:44 -050083 case CHIP_STONEY:
Alex Deucher1f7371b2015-12-02 17:46:21 -050084 amd_pp->ip_funcs = &cz_dpm_ip_funcs;
85 break;
86 default:
87 ret = -EINVAL;
88 break;
89 }
90 }
91 return ret;
92}
93
94static int amdgpu_pp_early_init(void *handle)
95{
96 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
97 int ret = 0;
98
Rex Zhuedb611c2015-10-20 11:05:45 +080099#ifdef CONFIG_DRM_AMD_POWERPLAY
Rex Zhu76c8cc62015-10-17 17:57:58 +0800100 switch (adev->asic_type) {
Flora Cui2cc0c0b2016-03-14 18:33:29 -0400101 case CHIP_POLARIS11:
102 case CHIP_POLARIS10:
103 adev->pp_enabled = true;
104 break;
Jordan Lazare34669042016-01-18 17:00:03 -0500105 case CHIP_TONGA:
106 case CHIP_FIJI:
Alex Deucher70bb2462016-07-28 13:35:42 -0400107 case CHIP_TOPAZ:
Jordan Lazare34669042016-01-18 17:00:03 -0500108 case CHIP_CARRIZO:
109 case CHIP_STONEY:
Huang Ruifad2af12016-04-18 23:29:32 +0800110 adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true;
Jordan Lazare34669042016-01-18 17:00:03 -0500111 break;
112 /* These chips don't have powerplay implemenations */
113 case CHIP_BONAIRE:
114 case CHIP_HAWAII:
115 case CHIP_KABINI:
116 case CHIP_MULLINS:
117 case CHIP_KAVERI:
Jordan Lazare34669042016-01-18 17:00:03 -0500118 default:
119 adev->pp_enabled = false;
120 break;
Rex Zhu76c8cc62015-10-17 17:57:58 +0800121 }
Jammy Zhoue61710c2015-11-10 18:31:08 -0500122#else
123 adev->pp_enabled = false;
Rex Zhuedb611c2015-10-20 11:05:45 +0800124#endif
Rex Zhu76c8cc62015-10-17 17:57:58 +0800125
Alex Deucher1f7371b2015-12-02 17:46:21 -0500126 ret = amdgpu_powerplay_init(adev);
127 if (ret)
128 return ret;
129
130 if (adev->powerplay.ip_funcs->early_init)
131 ret = adev->powerplay.ip_funcs->early_init(
132 adev->powerplay.pp_handle);
133 return ret;
134}
135
Rex Zhu7ad4e7f2015-12-07 16:42:35 +0800136
137static int amdgpu_pp_late_init(void *handle)
138{
139 int ret = 0;
140 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
141
142 if (adev->powerplay.ip_funcs->late_init)
143 ret = adev->powerplay.ip_funcs->late_init(
144 adev->powerplay.pp_handle);
145
Alex Deucher898b1de2015-12-08 17:28:28 -0500146#ifdef CONFIG_DRM_AMD_POWERPLAY
Rex Zhu5349ece2016-03-29 14:34:51 +0800147 if (adev->pp_enabled && adev->pm.dpm_enabled) {
Alex Deucher898b1de2015-12-08 17:28:28 -0500148 amdgpu_pm_sysfs_init(adev);
Rex Zhu4ea2efa2016-02-25 17:32:45 +0800149 amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL);
150 }
Alex Deucher898b1de2015-12-08 17:28:28 -0500151#endif
Rex Zhu7ad4e7f2015-12-07 16:42:35 +0800152 return ret;
153}
154
Alex Deucher1f7371b2015-12-02 17:46:21 -0500155static int amdgpu_pp_sw_init(void *handle)
156{
157 int ret = 0;
158 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
159
160 if (adev->powerplay.ip_funcs->sw_init)
161 ret = adev->powerplay.ip_funcs->sw_init(
162 adev->powerplay.pp_handle);
163
164#ifdef CONFIG_DRM_AMD_POWERPLAY
Rex Zhu1587f6e2016-03-29 14:21:50 +0800165 if (adev->pp_enabled)
166 adev->pm.dpm_enabled = true;
Alex Deucher1f7371b2015-12-02 17:46:21 -0500167#endif
168
169 return ret;
170}
171
172static int amdgpu_pp_sw_fini(void *handle)
173{
174 int ret = 0;
175 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
176
177 if (adev->powerplay.ip_funcs->sw_fini)
178 ret = adev->powerplay.ip_funcs->sw_fini(
179 adev->powerplay.pp_handle);
180 if (ret)
181 return ret;
182
Alex Deucher1f7371b2015-12-02 17:46:21 -0500183 return ret;
184}
185
186static int amdgpu_pp_hw_init(void *handle)
187{
188 int ret = 0;
189 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
190
Jammy Zhoue61710c2015-11-10 18:31:08 -0500191 if (adev->pp_enabled && adev->firmware.smu_load)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500192 amdgpu_ucode_init_bo(adev);
193
194 if (adev->powerplay.ip_funcs->hw_init)
195 ret = adev->powerplay.ip_funcs->hw_init(
196 adev->powerplay.pp_handle);
197
198 return ret;
199}
200
201static int amdgpu_pp_hw_fini(void *handle)
202{
203 int ret = 0;
204 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
205
206 if (adev->powerplay.ip_funcs->hw_fini)
207 ret = adev->powerplay.ip_funcs->hw_fini(
208 adev->powerplay.pp_handle);
209
Jammy Zhoue61710c2015-11-10 18:31:08 -0500210 if (adev->pp_enabled && adev->firmware.smu_load)
Alex Deucher1f7371b2015-12-02 17:46:21 -0500211 amdgpu_ucode_fini_bo(adev);
212
213 return ret;
214}
215
Monk Liu482587e2016-05-19 14:36:01 +0800216static void amdgpu_pp_late_fini(void *handle)
217{
Dave Airlie29ccf752016-06-10 11:40:49 +1000218#ifdef CONFIG_DRM_AMD_POWERPLAY
Monk Liu482587e2016-05-19 14:36:01 +0800219 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
220
Monk Liu482587e2016-05-19 14:36:01 +0800221 if (adev->pp_enabled) {
222 amdgpu_pm_sysfs_fini(adev);
223 amd_powerplay_fini(adev->powerplay.pp_handle);
224 }
225
226 if (adev->powerplay.ip_funcs->late_fini)
227 adev->powerplay.ip_funcs->late_fini(
228 adev->powerplay.pp_handle);
229#endif
230}
231
Alex Deucher1f7371b2015-12-02 17:46:21 -0500232static int amdgpu_pp_suspend(void *handle)
233{
234 int ret = 0;
235 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
236
237 if (adev->powerplay.ip_funcs->suspend)
238 ret = adev->powerplay.ip_funcs->suspend(
239 adev->powerplay.pp_handle);
240 return ret;
241}
242
243static int amdgpu_pp_resume(void *handle)
244{
245 int ret = 0;
246 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
247
248 if (adev->powerplay.ip_funcs->resume)
249 ret = adev->powerplay.ip_funcs->resume(
250 adev->powerplay.pp_handle);
251 return ret;
252}
253
254static int amdgpu_pp_set_clockgating_state(void *handle,
255 enum amd_clockgating_state state)
256{
257 int ret = 0;
258 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
259
260 if (adev->powerplay.ip_funcs->set_clockgating_state)
261 ret = adev->powerplay.ip_funcs->set_clockgating_state(
262 adev->powerplay.pp_handle, state);
263 return ret;
264}
265
266static int amdgpu_pp_set_powergating_state(void *handle,
267 enum amd_powergating_state state)
268{
269 int ret = 0;
270 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
271
272 if (adev->powerplay.ip_funcs->set_powergating_state)
273 ret = adev->powerplay.ip_funcs->set_powergating_state(
274 adev->powerplay.pp_handle, state);
275 return ret;
276}
277
278
279static bool amdgpu_pp_is_idle(void *handle)
280{
281 bool ret = true;
282 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
283
284 if (adev->powerplay.ip_funcs->is_idle)
285 ret = adev->powerplay.ip_funcs->is_idle(
286 adev->powerplay.pp_handle);
287 return ret;
288}
289
290static int amdgpu_pp_wait_for_idle(void *handle)
291{
292 int ret = 0;
293 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
294
295 if (adev->powerplay.ip_funcs->wait_for_idle)
296 ret = adev->powerplay.ip_funcs->wait_for_idle(
297 adev->powerplay.pp_handle);
298 return ret;
299}
300
301static int amdgpu_pp_soft_reset(void *handle)
302{
303 int ret = 0;
304 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
305
306 if (adev->powerplay.ip_funcs->soft_reset)
307 ret = adev->powerplay.ip_funcs->soft_reset(
308 adev->powerplay.pp_handle);
309 return ret;
310}
311
Alex Deucher1f7371b2015-12-02 17:46:21 -0500312const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
Tom St Denis88a907d2016-05-04 14:28:35 -0400313 .name = "amdgpu_powerplay",
Alex Deucher1f7371b2015-12-02 17:46:21 -0500314 .early_init = amdgpu_pp_early_init,
Rex Zhu7ad4e7f2015-12-07 16:42:35 +0800315 .late_init = amdgpu_pp_late_init,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500316 .sw_init = amdgpu_pp_sw_init,
317 .sw_fini = amdgpu_pp_sw_fini,
318 .hw_init = amdgpu_pp_hw_init,
319 .hw_fini = amdgpu_pp_hw_fini,
Monk Liu482587e2016-05-19 14:36:01 +0800320 .late_fini = amdgpu_pp_late_fini,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500321 .suspend = amdgpu_pp_suspend,
322 .resume = amdgpu_pp_resume,
323 .is_idle = amdgpu_pp_is_idle,
324 .wait_for_idle = amdgpu_pp_wait_for_idle,
325 .soft_reset = amdgpu_pp_soft_reset,
Alex Deucher1f7371b2015-12-02 17:46:21 -0500326 .set_clockgating_state = amdgpu_pp_set_clockgating_state,
327 .set_powergating_state = amdgpu_pp_set_powergating_state,
328};