diff options
| author | Alex Deucher <alexander.deucher@amd.com> | 2014-09-14 21:14:14 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2014-11-20 13:00:09 -0500 |
| commit | 39471ad39de827657e6ab69da96496eb0943295e (patch) | |
| tree | d3b65da5462d797edb86d2c785796bf355e2cf3b | |
| parent | 4bb62c95a7e781a238b2ab374f34b1bf91e01ddc (diff) | |
drm/radeon/dpm: add smc fan control for SI (v2)
Enable smc fan control for SI boards. Should
reduce the fan noise on systems with a higher
default fan profile.
v2: disable by default, add rpm controls
bug:
https://bugs.freedesktop.org/show_bug.cgi?id=73338
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/ppsmc.h | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_dpm.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/si_dpm.c | 330 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/si_dpm.h | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 40 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/sislands_smc.h | 25 |
6 files changed, 401 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h index 11c0e4d5c0bf..0c4eaa60b6ca 100644 --- a/drivers/gpu/drm/radeon/ppsmc.h +++ b/drivers/gpu/drm/radeon/ppsmc.h | |||
| @@ -56,6 +56,9 @@ | |||
| 56 | #define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 | 56 | #define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 |
| 57 | #define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 | 57 | #define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 |
| 58 | 58 | ||
| 59 | #define FDO_MODE_HARDWARE 0 | ||
| 60 | #define FDO_MODE_PIECE_WISE_LINEAR 1 | ||
| 61 | |||
| 59 | #define PPSMC_Result_OK ((uint8_t)0x01) | 62 | #define PPSMC_Result_OK ((uint8_t)0x01) |
| 60 | #define PPSMC_Result_Failed ((uint8_t)0xFF) | 63 | #define PPSMC_Result_Failed ((uint8_t)0xFF) |
| 61 | 64 | ||
| @@ -79,6 +82,8 @@ typedef uint8_t PPSMC_Result; | |||
| 79 | #define PPSMC_MSG_DisableCac ((uint8_t)0x54) | 82 | #define PPSMC_MSG_DisableCac ((uint8_t)0x54) |
| 80 | #define PPSMC_TDPClampingActive ((uint8_t)0x59) | 83 | #define PPSMC_TDPClampingActive ((uint8_t)0x59) |
| 81 | #define PPSMC_TDPClampingInactive ((uint8_t)0x5A) | 84 | #define PPSMC_TDPClampingInactive ((uint8_t)0x5A) |
| 85 | #define PPSMC_StartFanControl ((uint8_t)0x5B) | ||
| 86 | #define PPSMC_StopFanControl ((uint8_t)0x5C) | ||
| 82 | #define PPSMC_MSG_NoDisplay ((uint8_t)0x5D) | 87 | #define PPSMC_MSG_NoDisplay ((uint8_t)0x5D) |
| 83 | #define PPSMC_MSG_HasDisplay ((uint8_t)0x5E) | 88 | #define PPSMC_MSG_HasDisplay ((uint8_t)0x5E) |
| 84 | #define PPSMC_MSG_UVDPowerOFF ((uint8_t)0x60) | 89 | #define PPSMC_MSG_UVDPowerOFF ((uint8_t)0x60) |
diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h index 46b9d2a03018..bd499d749bc9 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.h +++ b/drivers/gpu/drm/radeon/r600_dpm.h | |||
| @@ -96,6 +96,9 @@ | |||
| 96 | #define R600_TEMP_RANGE_MIN (90 * 1000) | 96 | #define R600_TEMP_RANGE_MIN (90 * 1000) |
| 97 | #define R600_TEMP_RANGE_MAX (120 * 1000) | 97 | #define R600_TEMP_RANGE_MAX (120 * 1000) |
| 98 | 98 | ||
| 99 | #define FDO_PWM_MODE_STATIC 1 | ||
| 100 | #define FDO_PWM_MODE_STATIC_RPM 5 | ||
| 101 | |||
| 99 | enum r600_power_level { | 102 | enum r600_power_level { |
| 100 | R600_POWER_LEVEL_LOW = 0, | 103 | R600_POWER_LEVEL_LOW = 0, |
| 101 | R600_POWER_LEVEL_MEDIUM = 1, | 104 | R600_POWER_LEVEL_MEDIUM = 1, |
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index b59e1d6b27ab..cf4c420b5572 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
| @@ -3398,6 +3398,15 @@ static int si_process_firmware_header(struct radeon_device *rdev) | |||
| 3398 | 3398 | ||
| 3399 | ret = si_read_smc_sram_dword(rdev, | 3399 | ret = si_read_smc_sram_dword(rdev, |
| 3400 | SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + | 3400 | SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + |
| 3401 | SISLANDS_SMC_FIRMWARE_HEADER_fanTable, | ||
| 3402 | &tmp, si_pi->sram_end); | ||
| 3403 | if (ret) | ||
| 3404 | return ret; | ||
| 3405 | |||
| 3406 | si_pi->fan_table_start = tmp; | ||
| 3407 | |||
| 3408 | ret = si_read_smc_sram_dword(rdev, | ||
| 3409 | SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + | ||
| 3401 | SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, | 3410 | SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, |
| 3402 | &tmp, si_pi->sram_end); | 3411 | &tmp, si_pi->sram_end); |
| 3403 | if (ret) | 3412 | if (ret) |
| @@ -5825,20 +5834,20 @@ static int si_thermal_enable_alert(struct radeon_device *rdev, | |||
| 5825 | if (enable) { | 5834 | if (enable) { |
| 5826 | PPSMC_Result result; | 5835 | PPSMC_Result result; |
| 5827 | 5836 | ||
| 5828 | thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; | 5837 | thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); |
| 5829 | rdev->irq.dpm_thermal = true; | 5838 | WREG32(CG_THERMAL_INT, thermal_int); |
| 5839 | rdev->irq.dpm_thermal = false; | ||
| 5830 | result = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); | 5840 | result = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt); |
| 5831 | if (result != PPSMC_Result_OK) { | 5841 | if (result != PPSMC_Result_OK) { |
| 5832 | DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); | 5842 | DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); |
| 5833 | return -EINVAL; | 5843 | return -EINVAL; |
| 5834 | } | 5844 | } |
| 5835 | } else { | 5845 | } else { |
| 5836 | thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); | 5846 | thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; |
| 5837 | rdev->irq.dpm_thermal = false; | 5847 | WREG32(CG_THERMAL_INT, thermal_int); |
| 5848 | rdev->irq.dpm_thermal = true; | ||
| 5838 | } | 5849 | } |
| 5839 | 5850 | ||
| 5840 | WREG32(CG_THERMAL_INT, thermal_int); | ||
| 5841 | |||
| 5842 | return 0; | 5851 | return 0; |
| 5843 | } | 5852 | } |
| 5844 | 5853 | ||
| @@ -5867,6 +5876,309 @@ static int si_thermal_set_temperature_range(struct radeon_device *rdev, | |||
| 5867 | return 0; | 5876 | return 0; |
| 5868 | } | 5877 | } |
| 5869 | 5878 | ||
| 5879 | static void si_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode) | ||
| 5880 | { | ||
| 5881 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 5882 | u32 tmp; | ||
| 5883 | |||
| 5884 | if (si_pi->fan_ctrl_is_in_default_mode) { | ||
| 5885 | tmp = (RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT; | ||
| 5886 | si_pi->fan_ctrl_default_mode = tmp; | ||
| 5887 | tmp = (RREG32(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT; | ||
| 5888 | si_pi->t_min = tmp; | ||
| 5889 | si_pi->fan_ctrl_is_in_default_mode = false; | ||
| 5890 | } | ||
| 5891 | |||
| 5892 | tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; | ||
| 5893 | tmp |= TMIN(0); | ||
| 5894 | WREG32(CG_FDO_CTRL2, tmp); | ||
| 5895 | |||
| 5896 | tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; | ||
| 5897 | tmp |= FDO_PWM_MODE(mode); | ||
| 5898 | WREG32(CG_FDO_CTRL2, tmp); | ||
| 5899 | } | ||
| 5900 | |||
| 5901 | static int si_thermal_setup_fan_table(struct radeon_device *rdev) | ||
| 5902 | { | ||
| 5903 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 5904 | PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE }; | ||
| 5905 | u32 duty100; | ||
| 5906 | u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2; | ||
| 5907 | u16 fdo_min, slope1, slope2; | ||
| 5908 | u32 reference_clock, tmp; | ||
| 5909 | int ret; | ||
| 5910 | u64 tmp64; | ||
| 5911 | |||
| 5912 | if (!si_pi->fan_table_start) { | ||
| 5913 | rdev->pm.dpm.fan.ucode_fan_control = false; | ||
| 5914 | return 0; | ||
| 5915 | } | ||
| 5916 | |||
| 5917 | duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; | ||
| 5918 | |||
| 5919 | if (duty100 == 0) { | ||
| 5920 | rdev->pm.dpm.fan.ucode_fan_control = false; | ||
| 5921 | return 0; | ||
| 5922 | } | ||
| 5923 | |||
| 5924 | tmp64 = (u64)rdev->pm.dpm.fan.pwm_min * duty100; | ||
| 5925 | do_div(tmp64, 10000); | ||
| 5926 | fdo_min = (u16)tmp64; | ||
| 5927 | |||
| 5928 | t_diff1 = rdev->pm.dpm.fan.t_med - rdev->pm.dpm.fan.t_min; | ||
| 5929 | t_diff2 = rdev->pm.dpm.fan.t_high - rdev->pm.dpm.fan.t_med; | ||
| 5930 | |||
| 5931 | pwm_diff1 = rdev->pm.dpm.fan.pwm_med - rdev->pm.dpm.fan.pwm_min; | ||
| 5932 | pwm_diff2 = rdev->pm.dpm.fan.pwm_high - rdev->pm.dpm.fan.pwm_med; | ||
| 5933 | |||
| 5934 | slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); | ||
| 5935 | slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); | ||
| 5936 | |||
| 5937 | fan_table.slope1 = cpu_to_be16(slope1); | ||
| 5938 | fan_table.slope2 = cpu_to_be16(slope2); | ||
| 5939 | |||
| 5940 | fan_table.fdo_min = cpu_to_be16(fdo_min); | ||
| 5941 | |||
| 5942 | fan_table.hys_down = cpu_to_be16(rdev->pm.dpm.fan.t_hyst); | ||
| 5943 | |||
| 5944 | fan_table.hys_up = cpu_to_be16(1); | ||
| 5945 | |||
| 5946 | fan_table.hys_slope = cpu_to_be16(1); | ||
| 5947 | |||
| 5948 | fan_table.temp_resp_lim = cpu_to_be16(5); | ||
| 5949 | |||
| 5950 | reference_clock = radeon_get_xclk(rdev); | ||
| 5951 | |||
| 5952 | fan_table.refresh_period = cpu_to_be32((rdev->pm.dpm.fan.cycle_delay * | ||
| 5953 | reference_clock) / 1600); | ||
| 5954 | |||
| 5955 | fan_table.fdo_max = cpu_to_be16((u16)duty100); | ||
| 5956 | |||
| 5957 | tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; | ||
| 5958 | fan_table.temp_src = (uint8_t)tmp; | ||
| 5959 | |||
| 5960 | ret = si_copy_bytes_to_smc(rdev, | ||
| 5961 | si_pi->fan_table_start, | ||
| 5962 | (u8 *)(&fan_table), | ||
| 5963 | sizeof(fan_table), | ||
| 5964 | si_pi->sram_end); | ||
| 5965 | |||
| 5966 | if (ret) { | ||
| 5967 | DRM_ERROR("Failed to load fan table to the SMC."); | ||
| 5968 | rdev->pm.dpm.fan.ucode_fan_control = false; | ||
| 5969 | } | ||
| 5970 | |||
| 5971 | return 0; | ||
| 5972 | } | ||
| 5973 | |||
| 5974 | static int si_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) | ||
| 5975 | { | ||
| 5976 | PPSMC_Result ret; | ||
| 5977 | |||
| 5978 | ret = si_send_msg_to_smc(rdev, PPSMC_StartFanControl); | ||
| 5979 | if (ret == PPSMC_Result_OK) | ||
| 5980 | return 0; | ||
| 5981 | else | ||
| 5982 | return -EINVAL; | ||
| 5983 | } | ||
| 5984 | |||
| 5985 | static int si_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) | ||
| 5986 | { | ||
| 5987 | PPSMC_Result ret; | ||
| 5988 | |||
| 5989 | ret = si_send_msg_to_smc(rdev, PPSMC_StopFanControl); | ||
| 5990 | if (ret == PPSMC_Result_OK) | ||
| 5991 | return 0; | ||
| 5992 | else | ||
| 5993 | return -EINVAL; | ||
| 5994 | } | ||
| 5995 | |||
| 5996 | #if 0 | ||
| 5997 | static int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, | ||
| 5998 | u32 *speed) | ||
| 5999 | { | ||
| 6000 | u32 duty, duty100; | ||
| 6001 | u64 tmp64; | ||
| 6002 | |||
| 6003 | if (rdev->pm.no_fan) | ||
| 6004 | return -ENOENT; | ||
| 6005 | |||
| 6006 | duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; | ||
| 6007 | duty = (RREG32(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT; | ||
| 6008 | |||
| 6009 | if (duty100 == 0) | ||
| 6010 | return -EINVAL; | ||
| 6011 | |||
| 6012 | tmp64 = (u64)duty * 100; | ||
| 6013 | do_div(tmp64, duty100); | ||
| 6014 | *speed = (u32)tmp64; | ||
| 6015 | |||
| 6016 | if (*speed > 100) | ||
| 6017 | *speed = 100; | ||
| 6018 | |||
| 6019 | return 0; | ||
| 6020 | } | ||
| 6021 | |||
| 6022 | static int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, | ||
| 6023 | u32 speed) | ||
| 6024 | { | ||
| 6025 | u32 tmp; | ||
| 6026 | u32 duty, duty100; | ||
| 6027 | u64 tmp64; | ||
| 6028 | |||
| 6029 | if (rdev->pm.no_fan) | ||
| 6030 | return -ENOENT; | ||
| 6031 | |||
| 6032 | if (speed > 100) | ||
| 6033 | return -EINVAL; | ||
| 6034 | |||
| 6035 | if (rdev->pm.dpm.fan.ucode_fan_control) | ||
| 6036 | si_fan_ctrl_stop_smc_fan_control(rdev); | ||
| 6037 | |||
| 6038 | duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; | ||
| 6039 | |||
| 6040 | if (duty100 == 0) | ||
| 6041 | return -EINVAL; | ||
| 6042 | |||
| 6043 | tmp64 = (u64)speed * duty100; | ||
| 6044 | do_div(tmp64, 100); | ||
| 6045 | duty = (u32)tmp64; | ||
| 6046 | |||
| 6047 | tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK; | ||
| 6048 | tmp |= FDO_STATIC_DUTY(duty); | ||
| 6049 | WREG32(CG_FDO_CTRL0, tmp); | ||
| 6050 | |||
| 6051 | si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); | ||
| 6052 | |||
| 6053 | return 0; | ||
| 6054 | } | ||
| 6055 | |||
| 6056 | static int si_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, | ||
| 6057 | u32 *speed) | ||
| 6058 | { | ||
| 6059 | u32 tach_period; | ||
| 6060 | u32 xclk = radeon_get_xclk(rdev); | ||
| 6061 | |||
| 6062 | if (rdev->pm.no_fan) | ||
| 6063 | return -ENOENT; | ||
| 6064 | |||
| 6065 | if (rdev->pm.fan_pulses_per_revolution == 0) | ||
| 6066 | return -ENOENT; | ||
| 6067 | |||
| 6068 | tach_period = (RREG32(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT; | ||
| 6069 | if (tach_period == 0) | ||
| 6070 | return -ENOENT; | ||
| 6071 | |||
| 6072 | *speed = 60 * xclk * 10000 / tach_period; | ||
| 6073 | |||
| 6074 | return 0; | ||
| 6075 | } | ||
| 6076 | |||
| 6077 | static int si_fan_ctrl_set_fan_speed_rpm(struct radeon_device *rdev, | ||
| 6078 | u32 speed) | ||
| 6079 | { | ||
| 6080 | u32 tach_period, tmp; | ||
| 6081 | u32 xclk = radeon_get_xclk(rdev); | ||
| 6082 | |||
| 6083 | if (rdev->pm.no_fan) | ||
| 6084 | return -ENOENT; | ||
| 6085 | |||
| 6086 | if (rdev->pm.fan_pulses_per_revolution == 0) | ||
| 6087 | return -ENOENT; | ||
| 6088 | |||
| 6089 | if ((speed < rdev->pm.fan_min_rpm) || | ||
| 6090 | (speed > rdev->pm.fan_max_rpm)) | ||
| 6091 | return -EINVAL; | ||
| 6092 | |||
| 6093 | if (rdev->pm.dpm.fan.ucode_fan_control) | ||
| 6094 | si_fan_ctrl_stop_smc_fan_control(rdev); | ||
| 6095 | |||
| 6096 | tach_period = 60 * xclk * 10000 / (8 * speed); | ||
| 6097 | tmp = RREG32(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK; | ||
| 6098 | tmp |= TARGET_PERIOD(tach_period); | ||
| 6099 | WREG32(CG_TACH_CTRL, tmp); | ||
| 6100 | |||
| 6101 | si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); | ||
| 6102 | |||
| 6103 | return 0; | ||
| 6104 | } | ||
| 6105 | #endif | ||
| 6106 | |||
| 6107 | static void si_fan_ctrl_set_default_mode(struct radeon_device *rdev) | ||
| 6108 | { | ||
| 6109 | struct si_power_info *si_pi = si_get_pi(rdev); | ||
| 6110 | u32 tmp; | ||
| 6111 | |||
| 6112 | if (!si_pi->fan_ctrl_is_in_default_mode) { | ||
| 6113 | tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; | ||
| 6114 | tmp |= FDO_PWM_MODE(si_pi->fan_ctrl_default_mode); | ||
| 6115 | WREG32(CG_FDO_CTRL2, tmp); | ||
| 6116 | |||
| 6117 | tmp = RREG32(CG_FDO_CTRL2) & TMIN_MASK; | ||
| 6118 | tmp |= TMIN(si_pi->t_min); | ||
| 6119 | WREG32(CG_FDO_CTRL2, tmp); | ||
| 6120 | si_pi->fan_ctrl_is_in_default_mode = true; | ||
| 6121 | } | ||
| 6122 | } | ||
| 6123 | |||
| 6124 | static void si_thermal_start_smc_fan_control(struct radeon_device *rdev) | ||
| 6125 | { | ||
| 6126 | if (rdev->pm.dpm.fan.ucode_fan_control) { | ||
| 6127 | si_fan_ctrl_start_smc_fan_control(rdev); | ||
| 6128 | si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); | ||
| 6129 | } | ||
| 6130 | } | ||
| 6131 | |||
| 6132 | static void si_thermal_initialize(struct radeon_device *rdev) | ||
| 6133 | { | ||
| 6134 | u32 tmp; | ||
| 6135 | |||
| 6136 | if (rdev->pm.fan_pulses_per_revolution) { | ||
| 6137 | tmp = RREG32(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK; | ||
| 6138 | tmp |= EDGE_PER_REV(rdev->pm.fan_pulses_per_revolution -1); | ||
| 6139 | WREG32(CG_TACH_CTRL, tmp); | ||
| 6140 | } | ||
| 6141 | |||
| 6142 | tmp = RREG32(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK; | ||
| 6143 | tmp |= TACH_PWM_RESP_RATE(0x28); | ||
| 6144 | WREG32(CG_FDO_CTRL2, tmp); | ||
| 6145 | } | ||
| 6146 | |||
| 6147 | static int si_thermal_start_thermal_controller(struct radeon_device *rdev) | ||
| 6148 | { | ||
| 6149 | int ret; | ||
| 6150 | |||
| 6151 | si_thermal_initialize(rdev); | ||
| 6152 | ret = si_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); | ||
| 6153 | if (ret) | ||
| 6154 | return ret; | ||
| 6155 | ret = si_thermal_enable_alert(rdev, true); | ||
| 6156 | if (ret) | ||
| 6157 | return ret; | ||
| 6158 | if (rdev->pm.dpm.fan.ucode_fan_control) { | ||
| 6159 | ret = si_halt_smc(rdev); | ||
| 6160 | if (ret) | ||
| 6161 | return ret; | ||
| 6162 | ret = si_thermal_setup_fan_table(rdev); | ||
| 6163 | if (ret) | ||
| 6164 | return ret; | ||
| 6165 | ret = si_resume_smc(rdev); | ||
| 6166 | if (ret) | ||
| 6167 | return ret; | ||
| 6168 | si_thermal_start_smc_fan_control(rdev); | ||
| 6169 | } | ||
| 6170 | |||
| 6171 | return 0; | ||
| 6172 | } | ||
| 6173 | |||
| 6174 | static void si_thermal_stop_thermal_controller(struct radeon_device *rdev) | ||
| 6175 | { | ||
| 6176 | if (!rdev->pm.no_fan) { | ||
| 6177 | si_fan_ctrl_set_default_mode(rdev); | ||
| 6178 | si_fan_ctrl_stop_smc_fan_control(rdev); | ||
| 6179 | } | ||
| 6180 | } | ||
| 6181 | |||
| 5870 | int si_dpm_enable(struct radeon_device *rdev) | 6182 | int si_dpm_enable(struct radeon_device *rdev) |
| 5871 | { | 6183 | { |
| 5872 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); | 6184 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
| @@ -5979,6 +6291,8 @@ int si_dpm_enable(struct radeon_device *rdev) | |||
| 5979 | 6291 | ||
| 5980 | si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); | 6292 | si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); |
| 5981 | 6293 | ||
| 6294 | si_thermal_start_thermal_controller(rdev); | ||
| 6295 | |||
| 5982 | ni_update_current_ps(rdev, boot_ps); | 6296 | ni_update_current_ps(rdev, boot_ps); |
| 5983 | 6297 | ||
| 5984 | return 0; | 6298 | return 0; |
| @@ -6019,6 +6333,7 @@ void si_dpm_disable(struct radeon_device *rdev) | |||
| 6019 | 6333 | ||
| 6020 | if (!si_is_smc_running(rdev)) | 6334 | if (!si_is_smc_running(rdev)) |
| 6021 | return; | 6335 | return; |
| 6336 | si_thermal_stop_thermal_controller(rdev); | ||
| 6022 | si_disable_ulv(rdev); | 6337 | si_disable_ulv(rdev); |
| 6023 | si_clear_vc(rdev); | 6338 | si_clear_vc(rdev); |
| 6024 | if (pi->thermal_protection) | 6339 | if (pi->thermal_protection) |
| @@ -6557,6 +6872,9 @@ int si_dpm_init(struct radeon_device *rdev) | |||
| 6557 | rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc = | 6872 | rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc = |
| 6558 | rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; | 6873 | rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; |
| 6559 | 6874 | ||
| 6875 | si_pi->fan_ctrl_is_in_default_mode = true; | ||
| 6876 | rdev->pm.dpm.fan.ucode_fan_control = false; | ||
| 6877 | |||
| 6560 | return 0; | 6878 | return 0; |
| 6561 | } | 6879 | } |
| 6562 | 6880 | ||
diff --git a/drivers/gpu/drm/radeon/si_dpm.h b/drivers/gpu/drm/radeon/si_dpm.h index 8b5c06a0832d..d16bb1b5f10f 100644 --- a/drivers/gpu/drm/radeon/si_dpm.h +++ b/drivers/gpu/drm/radeon/si_dpm.h | |||
| @@ -182,6 +182,7 @@ struct si_power_info { | |||
| 182 | u32 dte_table_start; | 182 | u32 dte_table_start; |
| 183 | u32 spll_table_start; | 183 | u32 spll_table_start; |
| 184 | u32 papm_cfg_table_start; | 184 | u32 papm_cfg_table_start; |
| 185 | u32 fan_table_start; | ||
| 185 | /* CAC stuff */ | 186 | /* CAC stuff */ |
| 186 | const struct si_cac_config_reg *cac_weights; | 187 | const struct si_cac_config_reg *cac_weights; |
| 187 | const struct si_cac_config_reg *lcac_config; | 188 | const struct si_cac_config_reg *lcac_config; |
| @@ -197,6 +198,10 @@ struct si_power_info { | |||
| 197 | /* SVI2 */ | 198 | /* SVI2 */ |
| 198 | u8 svd_gpio_id; | 199 | u8 svd_gpio_id; |
| 199 | u8 svc_gpio_id; | 200 | u8 svc_gpio_id; |
| 201 | /* fan control */ | ||
| 202 | bool fan_ctrl_is_in_default_mode; | ||
| 203 | u32 t_min; | ||
| 204 | u32 fan_ctrl_default_mode; | ||
| 200 | }; | 205 | }; |
| 201 | 206 | ||
| 202 | #define SISLANDS_INITIAL_STATE_ARB_INDEX 0 | 207 | #define SISLANDS_INITIAL_STATE_ARB_INDEX 0 |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 6635da9ec986..c549c16a4fe4 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -180,7 +180,10 @@ | |||
| 180 | #define DIG_THERM_DPM(x) ((x) << 14) | 180 | #define DIG_THERM_DPM(x) ((x) << 14) |
| 181 | #define DIG_THERM_DPM_MASK 0x003FC000 | 181 | #define DIG_THERM_DPM_MASK 0x003FC000 |
| 182 | #define DIG_THERM_DPM_SHIFT 14 | 182 | #define DIG_THERM_DPM_SHIFT 14 |
| 183 | 183 | #define CG_THERMAL_STATUS 0x704 | |
| 184 | #define FDO_PWM_DUTY(x) ((x) << 9) | ||
| 185 | #define FDO_PWM_DUTY_MASK (0xff << 9) | ||
| 186 | #define FDO_PWM_DUTY_SHIFT 9 | ||
| 184 | #define CG_THERMAL_INT 0x708 | 187 | #define CG_THERMAL_INT 0x708 |
| 185 | #define DIG_THERM_INTH(x) ((x) << 8) | 188 | #define DIG_THERM_INTH(x) ((x) << 8) |
| 186 | #define DIG_THERM_INTH_MASK 0x0000FF00 | 189 | #define DIG_THERM_INTH_MASK 0x0000FF00 |
| @@ -191,6 +194,10 @@ | |||
| 191 | #define THERM_INT_MASK_HIGH (1 << 24) | 194 | #define THERM_INT_MASK_HIGH (1 << 24) |
| 192 | #define THERM_INT_MASK_LOW (1 << 25) | 195 | #define THERM_INT_MASK_LOW (1 << 25) |
| 193 | 196 | ||
| 197 | #define CG_MULT_THERMAL_CTRL 0x710 | ||
| 198 | #define TEMP_SEL(x) ((x) << 20) | ||
| 199 | #define TEMP_SEL_MASK (0xff << 20) | ||
| 200 | #define TEMP_SEL_SHIFT 20 | ||
| 194 | #define CG_MULT_THERMAL_STATUS 0x714 | 201 | #define CG_MULT_THERMAL_STATUS 0x714 |
| 195 | #define ASIC_MAX_TEMP(x) ((x) << 0) | 202 | #define ASIC_MAX_TEMP(x) ((x) << 0) |
| 196 | #define ASIC_MAX_TEMP_MASK 0x000001ff | 203 | #define ASIC_MAX_TEMP_MASK 0x000001ff |
| @@ -199,6 +206,37 @@ | |||
| 199 | #define CTF_TEMP_MASK 0x0003fe00 | 206 | #define CTF_TEMP_MASK 0x0003fe00 |
| 200 | #define CTF_TEMP_SHIFT 9 | 207 | #define CTF_TEMP_SHIFT 9 |
| 201 | 208 | ||
| 209 | #define CG_FDO_CTRL0 0x754 | ||
| 210 | #define FDO_STATIC_DUTY(x) ((x) << 0) | ||
| 211 | #define FDO_STATIC_DUTY_MASK 0x0000000F | ||
| 212 | #define FDO_STATIC_DUTY_SHIFT 0 | ||
| 213 | #define CG_FDO_CTRL1 0x758 | ||
| 214 | #define FMAX_DUTY100(x) ((x) << 0) | ||
| 215 | #define FMAX_DUTY100_MASK 0x0000000F | ||
| 216 | #define FMAX_DUTY100_SHIFT 0 | ||
| 217 | #define CG_FDO_CTRL2 0x75C | ||
| 218 | #define TMIN(x) ((x) << 0) | ||
| 219 | #define TMIN_MASK 0x0000000F | ||
| 220 | #define TMIN_SHIFT 0 | ||
| 221 | #define FDO_PWM_MODE(x) ((x) << 11) | ||
| 222 | #define FDO_PWM_MODE_MASK (3 << 11) | ||
| 223 | #define FDO_PWM_MODE_SHIFT 11 | ||
| 224 | #define TACH_PWM_RESP_RATE(x) ((x) << 25) | ||
| 225 | #define TACH_PWM_RESP_RATE_MASK (0x7f << 25) | ||
| 226 | #define TACH_PWM_RESP_RATE_SHIFT 25 | ||
| 227 | |||
| 228 | #define CG_TACH_CTRL 0x770 | ||
| 229 | # define EDGE_PER_REV(x) ((x) << 0) | ||
| 230 | # define EDGE_PER_REV_MASK (0x7 << 0) | ||
| 231 | # define EDGE_PER_REV_SHIFT 0 | ||
| 232 | # define TARGET_PERIOD(x) ((x) << 3) | ||
| 233 | # define TARGET_PERIOD_MASK 0xfffffff8 | ||
| 234 | # define TARGET_PERIOD_SHIFT 3 | ||
| 235 | #define CG_TACH_STATUS 0x774 | ||
| 236 | # define TACH_PERIOD(x) ((x) << 0) | ||
| 237 | # define TACH_PERIOD_MASK 0xffffffff | ||
| 238 | # define TACH_PERIOD_SHIFT 0 | ||
| 239 | |||
| 202 | #define GENERAL_PWRMGT 0x780 | 240 | #define GENERAL_PWRMGT 0x780 |
| 203 | # define GLOBAL_PWRMGT_EN (1 << 0) | 241 | # define GLOBAL_PWRMGT_EN (1 << 0) |
| 204 | # define STATIC_PM_EN (1 << 1) | 242 | # define STATIC_PM_EN (1 << 1) |
diff --git a/drivers/gpu/drm/radeon/sislands_smc.h b/drivers/gpu/drm/radeon/sislands_smc.h index 623a0b1e2d9d..3c779838d9ab 100644 --- a/drivers/gpu/drm/radeon/sislands_smc.h +++ b/drivers/gpu/drm/radeon/sislands_smc.h | |||
| @@ -245,6 +245,31 @@ typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE; | |||
| 245 | #define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c | 245 | #define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c |
| 246 | #define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120 | 246 | #define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120 |
| 247 | 247 | ||
| 248 | struct PP_SIslands_FanTable | ||
| 249 | { | ||
| 250 | uint8_t fdo_mode; | ||
| 251 | uint8_t padding; | ||
| 252 | int16_t temp_min; | ||
| 253 | int16_t temp_med; | ||
| 254 | int16_t temp_max; | ||
| 255 | int16_t slope1; | ||
| 256 | int16_t slope2; | ||
| 257 | int16_t fdo_min; | ||
| 258 | int16_t hys_up; | ||
| 259 | int16_t hys_down; | ||
| 260 | int16_t hys_slope; | ||
| 261 | int16_t temp_resp_lim; | ||
| 262 | int16_t temp_curr; | ||
| 263 | int16_t slope_curr; | ||
| 264 | int16_t pwm_curr; | ||
| 265 | uint32_t refresh_period; | ||
| 266 | int16_t fdo_max; | ||
| 267 | uint8_t temp_src; | ||
| 268 | int8_t padding2; | ||
| 269 | }; | ||
| 270 | |||
| 271 | typedef struct PP_SIslands_FanTable PP_SIslands_FanTable; | ||
| 272 | |||
| 248 | #define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 | 273 | #define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 |
| 249 | #define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 | 274 | #define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 |
| 250 | 275 | ||
