diff options
author | Oleg Chernovskiy <algonkvel@gmail.com> | 2014-12-08 00:10:46 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-01-22 10:38:48 -0500 |
commit | 36689e57502bd4de86abe5e55fff60b974416a52 (patch) | |
tree | da010de03081fa80bcb967dc1dee13f2e17513e2 /drivers/gpu/drm/radeon/ci_dpm.c | |
parent | 99736703a9beedcb9afc69cde8e13846c713a4a3 (diff) | |
download | linux-36689e57502bd4de86abe5e55fff60b974416a52.tar.bz2 |
drm/radeon: bind fan control on CI cards to hwmon interface (v2)
This adds a possibility to control fan on CI parts
via exported hwmon variables. Note that automatic
ucode fan management pauses if you choose to enable
manual fan control. Use with caution!
v2: agd5f: fix formatting, squash in:
minor fix for pwm1_enable exposed value
Track smc control in addition to fan mode
This fixes pwm1_enable being constantly set
to 1 because of enabled smc control
also handle the case where smc fan control is disabled.
Signed-off-by: Oleg Chernovskiy <algonkvel@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/ci_dpm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/ci_dpm.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index f373a81ba3d5..9d4699b946d7 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -187,6 +187,9 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate); static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, PPSMC_Msg msg, u32 parameter); +static void ci_thermal_start_smc_fan_control(struct radeon_device *rdev); +static void ci_fan_ctrl_set_default_mode(struct radeon_device *rdev); + static struct ci_power_info *ci_get_pi(struct radeon_device *rdev) { struct ci_power_info *pi = rdev->pm.dpm.priv; @@ -1043,22 +1046,24 @@ static int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) return -EINVAL; } + pi->fan_is_controlled_by_smc = true; return 0; } -#if 0 static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) { PPSMC_Result ret; + struct ci_power_info *pi = ci_get_pi(rdev); ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl); - if (ret == PPSMC_Result_OK) + if (ret == PPSMC_Result_OK) { + pi->fan_is_controlled_by_smc = false; return 0; - else + } else return -EINVAL; } -static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, +int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, u32 *speed) { u32 duty, duty100; @@ -1083,21 +1088,22 @@ static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, return 0; } -static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, +int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, u32 speed) { u32 tmp; u32 duty, duty100; u64 tmp64; + struct ci_power_info *pi = ci_get_pi(rdev); if (rdev->pm.no_fan) return -ENOENT; - if (speed > 100) + if (pi->fan_is_controlled_by_smc) return -EINVAL; - if (rdev->pm.dpm.fan.ucode_fan_control) - ci_fan_ctrl_stop_smc_fan_control(rdev); + if (speed > 100) + return -EINVAL; duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; @@ -1112,11 +1118,38 @@ static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, tmp |= FDO_STATIC_DUTY(duty); WREG32_SMC(CG_FDO_CTRL0, tmp); - ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); - return 0; } +void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode) +{ + if (mode) { + /* stop auto-manage */ + if (rdev->pm.dpm.fan.ucode_fan_control) + ci_fan_ctrl_stop_smc_fan_control(rdev); + ci_fan_ctrl_set_static_mode(rdev, mode); + } else { + /* restart auto-manage */ + if (rdev->pm.dpm.fan.ucode_fan_control) + ci_thermal_start_smc_fan_control(rdev); + else + ci_fan_ctrl_set_default_mode(rdev); + } +} + +u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev) +{ + struct ci_power_info *pi = ci_get_pi(rdev); + u32 tmp; + + if (pi->fan_is_controlled_by_smc) + return 0; + + tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; + return (tmp >> FDO_PWM_MODE_SHIFT); +} + +#if 0 static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, u32 *speed) { |