Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  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
 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
 43	if (adev->pp_enabled) {
 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;
 80		case CHIP_FIJI:
 81			amd_pp->ip_funcs = &fiji_dpm_ip_funcs;
 82			break;
 83		case CHIP_CARRIZO:
 84		case CHIP_STONEY:
 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
 95static int amdgpu_pp_early_init(void *handle)
 96{
 97	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 98	int ret = 0;
 99
100#ifdef CONFIG_DRM_AMD_POWERPLAY
101	switch (adev->asic_type) {
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;
120	}
121#else
122	adev->pp_enabled = false;
123#endif
124
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
135
136static 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
145#ifdef CONFIG_DRM_AMD_POWERPLAY
146	if (adev->pp_enabled && adev->pm.dpm_enabled) {
147		amdgpu_pm_sysfs_init(adev);
148		amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL);
149	}
150#endif
151	return ret;
152}
153
154static 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
164	if (adev->pp_enabled)
165		adev->pm.dpm_enabled = true;
166#endif
167
168	return ret;
169}
170
171static 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
183	if (adev->pp_enabled) {
184		amdgpu_pm_sysfs_fini(adev);
185		amd_powerplay_fini(adev->powerplay.pp_handle);
186	}
187#endif
188
189	return ret;
190}
191
192static int amdgpu_pp_hw_init(void *handle)
193{
194	int ret = 0;
195	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
196
197	if (adev->pp_enabled && adev->firmware.smu_load)
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
207static 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
216	if (adev->pp_enabled && adev->firmware.smu_load)
217		amdgpu_ucode_fini_bo(adev);
218
219	return ret;
220}
221
222static 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
233static 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
244static 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
256static 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
269static 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
280static 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
291static 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
302static 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
311const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
312	.early_init = amdgpu_pp_early_init,
313	.late_init = amdgpu_pp_late_init,
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};