0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "radeon.h"
0025 #include "trinityd.h"
0026 #include "trinity_dpm.h"
0027 #include "ppsmc.h"
0028
0029 static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
0030 {
0031 int i;
0032 u32 v = 0;
0033
0034 WREG32(SMC_MESSAGE_0, id);
0035 for (i = 0; i < rdev->usec_timeout; i++) {
0036 if (RREG32(SMC_RESP_0) != 0)
0037 break;
0038 udelay(1);
0039 }
0040 v = RREG32(SMC_RESP_0);
0041
0042 if (v != 1) {
0043 if (v == 0xFF) {
0044 DRM_ERROR("SMC failed to handle the message!\n");
0045 return -EINVAL;
0046 } else if (v == 0xFE) {
0047 DRM_ERROR("Unknown SMC message!\n");
0048 return -EINVAL;
0049 }
0050 }
0051
0052 return 0;
0053 }
0054
0055 int trinity_dpm_bapm_enable(struct radeon_device *rdev, bool enable)
0056 {
0057 if (enable)
0058 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM);
0059 else
0060 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM);
0061 }
0062
0063 int trinity_dpm_config(struct radeon_device *rdev, bool enable)
0064 {
0065 if (enable)
0066 WREG32_SMC(SMU_SCRATCH0, 1);
0067 else
0068 WREG32_SMC(SMU_SCRATCH0, 0);
0069
0070 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Config);
0071 }
0072
0073 int trinity_dpm_force_state(struct radeon_device *rdev, u32 n)
0074 {
0075 WREG32_SMC(SMU_SCRATCH0, n);
0076
0077 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState);
0078 }
0079
0080 int trinity_dpm_n_levels_disabled(struct radeon_device *rdev, u32 n)
0081 {
0082 WREG32_SMC(SMU_SCRATCH0, n);
0083
0084 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_N_LevelsDisabled);
0085 }
0086
0087 int trinity_uvd_dpm_config(struct radeon_device *rdev)
0088 {
0089 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_UVD_DPM_Config);
0090 }
0091
0092 int trinity_dpm_no_forced_level(struct radeon_device *rdev)
0093 {
0094 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
0095 }
0096
0097 int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
0098 bool enable)
0099 {
0100 if (enable)
0101 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_AllowVoltageAdjustment);
0102 else
0103 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_RemoveVoltageAdjustment);
0104 }
0105
0106 int trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev)
0107 {
0108 return trinity_notify_message_to_smu(rdev, PPSMC_MSG_PG_SIMD_Config);
0109 }
0110
0111 void trinity_acquire_mutex(struct radeon_device *rdev)
0112 {
0113 int i;
0114
0115 WREG32(SMC_INT_REQ, 1);
0116 for (i = 0; i < rdev->usec_timeout; i++) {
0117 if ((RREG32(SMC_INT_REQ) & 0xffff) == 1)
0118 break;
0119 udelay(1);
0120 }
0121 }
0122
0123 void trinity_release_mutex(struct radeon_device *rdev)
0124 {
0125 WREG32(SMC_INT_REQ, 0);
0126 }