xref: /dragonfly/sys/dev/drm/radeon/trinity_smc.c (revision 57e252bf)
1*57e252bfSMichael Neumann /*
2*57e252bfSMichael Neumann  * Copyright 2012 Advanced Micro Devices, Inc.
3*57e252bfSMichael Neumann  *
4*57e252bfSMichael Neumann  * Permission is hereby granted, free of charge, to any person obtaining a
5*57e252bfSMichael Neumann  * copy of this software and associated documentation files (the "Software"),
6*57e252bfSMichael Neumann  * to deal in the Software without restriction, including without limitation
7*57e252bfSMichael Neumann  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*57e252bfSMichael Neumann  * and/or sell copies of the Software, and to permit persons to whom the
9*57e252bfSMichael Neumann  * Software is furnished to do so, subject to the following conditions:
10*57e252bfSMichael Neumann  *
11*57e252bfSMichael Neumann  * The above copyright notice and this permission notice shall be included in
12*57e252bfSMichael Neumann  * all copies or substantial portions of the Software.
13*57e252bfSMichael Neumann  *
14*57e252bfSMichael Neumann  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*57e252bfSMichael Neumann  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*57e252bfSMichael Neumann  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*57e252bfSMichael Neumann  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*57e252bfSMichael Neumann  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*57e252bfSMichael Neumann  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*57e252bfSMichael Neumann  * OTHER DEALINGS IN THE SOFTWARE.
21*57e252bfSMichael Neumann  *
22*57e252bfSMichael Neumann  */
23*57e252bfSMichael Neumann 
24*57e252bfSMichael Neumann #include <drm/drmP.h>
25*57e252bfSMichael Neumann #include "radeon.h"
26*57e252bfSMichael Neumann #include "trinityd.h"
27*57e252bfSMichael Neumann #include "trinity_dpm.h"
28*57e252bfSMichael Neumann #include "ppsmc.h"
29*57e252bfSMichael Neumann 
30*57e252bfSMichael Neumann struct trinity_ps *trinity_get_ps(struct radeon_ps *rps);
31*57e252bfSMichael Neumann struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev);
32*57e252bfSMichael Neumann 
33*57e252bfSMichael Neumann static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
34*57e252bfSMichael Neumann {
35*57e252bfSMichael Neumann 	int i;
36*57e252bfSMichael Neumann 	u32 v = 0;
37*57e252bfSMichael Neumann 
38*57e252bfSMichael Neumann 	WREG32(SMC_MESSAGE_0, id);
39*57e252bfSMichael Neumann 	for (i = 0; i < rdev->usec_timeout; i++) {
40*57e252bfSMichael Neumann 		if (RREG32(SMC_RESP_0) != 0)
41*57e252bfSMichael Neumann 			break;
42*57e252bfSMichael Neumann 		DRM_UDELAY(1);
43*57e252bfSMichael Neumann 	}
44*57e252bfSMichael Neumann 	v = RREG32(SMC_RESP_0);
45*57e252bfSMichael Neumann 
46*57e252bfSMichael Neumann 	if (v != 1) {
47*57e252bfSMichael Neumann 		if (v == 0xFF) {
48*57e252bfSMichael Neumann 			DRM_ERROR("SMC failed to handle the message!\n");
49*57e252bfSMichael Neumann 			return -EINVAL;
50*57e252bfSMichael Neumann 		} else if (v == 0xFE) {
51*57e252bfSMichael Neumann 			DRM_ERROR("Unknown SMC message!\n");
52*57e252bfSMichael Neumann 			return -EINVAL;
53*57e252bfSMichael Neumann 		}
54*57e252bfSMichael Neumann 	}
55*57e252bfSMichael Neumann 
56*57e252bfSMichael Neumann 	return 0;
57*57e252bfSMichael Neumann }
58*57e252bfSMichael Neumann 
59*57e252bfSMichael Neumann int trinity_dpm_config(struct radeon_device *rdev, bool enable)
60*57e252bfSMichael Neumann {
61*57e252bfSMichael Neumann 	if (enable)
62*57e252bfSMichael Neumann 		WREG32_SMC(SMU_SCRATCH0, 1);
63*57e252bfSMichael Neumann 	else
64*57e252bfSMichael Neumann 		WREG32_SMC(SMU_SCRATCH0, 0);
65*57e252bfSMichael Neumann 
66*57e252bfSMichael Neumann 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Config);
67*57e252bfSMichael Neumann }
68*57e252bfSMichael Neumann 
69*57e252bfSMichael Neumann int trinity_dpm_force_state(struct radeon_device *rdev, u32 n)
70*57e252bfSMichael Neumann {
71*57e252bfSMichael Neumann 	WREG32_SMC(SMU_SCRATCH0, n);
72*57e252bfSMichael Neumann 
73*57e252bfSMichael Neumann 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState);
74*57e252bfSMichael Neumann }
75*57e252bfSMichael Neumann 
76*57e252bfSMichael Neumann int trinity_dpm_n_levels_disabled(struct radeon_device *rdev, u32 n)
77*57e252bfSMichael Neumann {
78*57e252bfSMichael Neumann 	WREG32_SMC(SMU_SCRATCH0, n);
79*57e252bfSMichael Neumann 
80*57e252bfSMichael Neumann 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_N_LevelsDisabled);
81*57e252bfSMichael Neumann }
82*57e252bfSMichael Neumann 
83*57e252bfSMichael Neumann int trinity_uvd_dpm_config(struct radeon_device *rdev)
84*57e252bfSMichael Neumann {
85*57e252bfSMichael Neumann 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_UVD_DPM_Config);
86*57e252bfSMichael Neumann }
87*57e252bfSMichael Neumann 
88*57e252bfSMichael Neumann int trinity_dpm_no_forced_level(struct radeon_device *rdev)
89*57e252bfSMichael Neumann {
90*57e252bfSMichael Neumann 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
91*57e252bfSMichael Neumann }
92*57e252bfSMichael Neumann 
93*57e252bfSMichael Neumann int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
94*57e252bfSMichael Neumann 					  bool enable)
95*57e252bfSMichael Neumann {
96*57e252bfSMichael Neumann 	if (enable)
97*57e252bfSMichael Neumann 		return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_AllowVoltageAdjustment);
98*57e252bfSMichael Neumann 	else
99*57e252bfSMichael Neumann 		return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_RemoveVoltageAdjustment);
100*57e252bfSMichael Neumann }
101*57e252bfSMichael Neumann 
102*57e252bfSMichael Neumann int trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev)
103*57e252bfSMichael Neumann {
104*57e252bfSMichael Neumann 	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_PG_SIMD_Config);
105*57e252bfSMichael Neumann }
106*57e252bfSMichael Neumann 
107*57e252bfSMichael Neumann void trinity_acquire_mutex(struct radeon_device *rdev)
108*57e252bfSMichael Neumann {
109*57e252bfSMichael Neumann 	int i;
110*57e252bfSMichael Neumann 
111*57e252bfSMichael Neumann 	WREG32(SMC_INT_REQ, 1);
112*57e252bfSMichael Neumann 	for (i = 0; i < rdev->usec_timeout; i++) {
113*57e252bfSMichael Neumann 		if ((RREG32(SMC_INT_REQ) & 0xffff) == 1)
114*57e252bfSMichael Neumann 			break;
115*57e252bfSMichael Neumann 		DRM_UDELAY(1);
116*57e252bfSMichael Neumann 	}
117*57e252bfSMichael Neumann }
118*57e252bfSMichael Neumann 
119*57e252bfSMichael Neumann void trinity_release_mutex(struct radeon_device *rdev)
120*57e252bfSMichael Neumann {
121*57e252bfSMichael Neumann 	WREG32(SMC_INT_REQ, 0);
122*57e252bfSMichael Neumann }
123