aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/ci_dpm.c
diff options
context:
space:
mode:
authorOleg Chernovskiy <algonkvel@gmail.com>2014-12-08 00:10:46 +0300
committerAlex Deucher <alexander.deucher@amd.com>2015-01-22 10:38:48 -0500
commit36689e57502bd4de86abe5e55fff60b974416a52 (patch)
treeda010de03081fa80bcb967dc1dee13f2e17513e2 /drivers/gpu/drm/radeon/ci_dpm.c
parentdrm/radeon: add hwmon interface for managing fan pwm (v2) (diff)
downloadlinux-dev-36689e57502bd4de86abe5e55fff60b974416a52.tar.xz
linux-dev-36689e57502bd4de86abe5e55fff60b974416a52.zip
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.c53
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)
{