[PATCH] RFC: drm/amdgpu/pp: writable hwmon/pwm1_min on vega10

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sapphire Vega 64 Nitro+ is too noisy at idle, frequently switching
between zero-rpm mode and 1200 RPM.

As pwm1_min is currently always 0 (and thus completely useless), I:
- Made it writable so I can adjust min fan speed for "automatic" fan
control
- Changed amdgpu_hwmon_get_pwm1_min to return the value from fan
configuration table instead of 0

Probably pwm1_auto_point#_pwm and pwm1_auto_point#_temp are a better
interface to configure the fan curve, but for me it is not clear how
zero-rpm mode and parameters like FanThrottlingRpm should map to it.

Signed-off-by: Aleksandr Mezin <mezin.alexander at gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 37 +++++++++++++++++-
 .../gpu/drm/amd/include/kgd_pp_interface.h    |  2 +
 drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 39 +++++++++++++++++++
 .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c    |  2 +
 .../drm/amd/powerplay/hwmgr/vega10_thermal.c  | 23 +++++++++++
 .../drm/amd/powerplay/hwmgr/vega10_thermal.h  |  4 ++
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h     |  2 +
 7 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 8f98629fbe59..588f4b4fdc76 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -1057,7 +1057,40 @@ static ssize_t amdgpu_hwmon_get_pwm1_min(struct device *dev,
 					 struct device_attribute *attr,
 					 char *buf)
 {
-	return sprintf(buf, "%i\n", 0);
+	struct amdgpu_device *adev = dev_get_drvdata(dev);
+	void *handle = adev->powerplay.pp_handle;
+	int err;
+	u16 value = 0;
+
+	if (adev->powerplay.pp_funcs->get_min_fan_pwm) {
+		err = adev->powerplay.pp_funcs->get_min_fan_pwm(handle, &value);
+		if (err)
+			return err;
+	}
+
+	return sprintf(buf, "%u\n", (unsigned int)value);
+}
+
+static ssize_t amdgpu_hwmon_set_pwm1_min(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct amdgpu_device *adev = dev_get_drvdata(dev);
+	void *handle = adev->powerplay.pp_handle;
+	int err;
+	u16 value;
+
+	err = kstrtou16(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (adev->powerplay.pp_funcs->set_min_fan_pwm) {
+		err = adev->powerplay.pp_funcs->set_min_fan_pwm(handle, value);
+		if (err)
+			return err;
+	}
+
+	return count;
 }
 
 static ssize_t amdgpu_hwmon_get_pwm1_max(struct device *dev,
@@ -1371,7 +1404,7 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NU
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1);
 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1, amdgpu_hwmon_set_pwm1, 0);
 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_min, amdgpu_hwmon_set_pwm1_min, 0);
 static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0);
 static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0);
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 6a41b81c7325..e421a6752d01 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -269,6 +269,8 @@ struct amd_pm_funcs {
 	int (*get_display_mode_validation_clocks)(void *handle,
 		struct amd_pp_simple_clock_info *clocks);
 	int (*notify_smu_enable_pwe)(void *handle);
+	int (*set_min_fan_pwm)(void *handle, u16 value);
+	int (*get_min_fan_pwm)(void *handle, u16 *value);
 };
 
 #endif
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index 7a646f94b478..f3c4b0b937e3 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -522,6 +522,43 @@ static uint32_t pp_dpm_get_fan_control_mode(void *handle)
 	return mode;
 }
 
+static int pp_dpm_set_min_fan_pwm(void *handle, uint16_t value)
+{
+	struct pp_hwmgr *hwmgr = handle;
+	int ret = 0;
+
+	if (!hwmgr || !hwmgr->pm_en)
+		return -EINVAL;
+
+	if (hwmgr->hwmgr_func->set_min_fan_pwm == NULL) {
+		pr_info("%s was not implemented.\n", __func__);
+		return 0;
+	}
+	mutex_lock(&hwmgr->smu_lock);
+	ret = hwmgr->hwmgr_func->set_min_fan_pwm(hwmgr, value);
+	mutex_unlock(&hwmgr->smu_lock);
+	return ret;
+}
+
+static int pp_dpm_get_min_fan_pwm(void *handle, uint16_t *value)
+{
+	struct pp_hwmgr *hwmgr = handle;
+	int ret = 0;
+
+	if (!hwmgr || !hwmgr->pm_en)
+		return -EINVAL;
+
+	if (hwmgr->hwmgr_func->get_min_fan_pwm == NULL) {
+		*value = 0;
+		return 0;
+	}
+
+	mutex_lock(&hwmgr->smu_lock);
+	ret = hwmgr->hwmgr_func->get_min_fan_pwm(hwmgr, value);
+	mutex_unlock(&hwmgr->smu_lock);
+	return ret;
+}
+
 static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
 {
 	struct pp_hwmgr *hwmgr = handle;
@@ -1269,4 +1306,6 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
 	.display_clock_voltage_request = pp_display_clock_voltage_request,
 	.get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
 	.notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
+	.set_min_fan_pwm = pp_dpm_set_min_fan_pwm,
+	.get_min_fan_pwm = pp_dpm_get_min_fan_pwm,
 };
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index fb86c24394ff..6d766949ff26 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -4913,6 +4913,8 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
 	.set_power_profile_mode = vega10_set_power_profile_mode,
 	.set_power_limit = vega10_set_power_limit,
 	.odn_edit_dpm_table = vega10_odn_edit_dpm_table,
+	.get_min_fan_pwm = vega10_fan_ctrl_get_min_pwm,
+	.set_min_fan_pwm = vega10_fan_ctrl_set_min_pwm,
 };
 
 int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
index aa044c1955fe..28ebea24576b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
@@ -616,3 +616,26 @@ int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
 	}
 	return 0;
 }
+
+int vega10_fan_ctrl_get_min_pwm(struct pp_hwmgr *hwmgr, uint16_t *value)
+{
+	struct vega10_hwmgr *data = hwmgr->backend;
+	PPTable_t *table = &(data->smc_state_table.pp_table);
+
+	*value = table->FanPwmMin;
+	return 0;
+}
+
+int vega10_fan_ctrl_set_min_pwm(struct pp_hwmgr *hwmgr, uint16_t value)
+{
+	struct vega10_hwmgr *data = hwmgr->backend;
+	PPTable_t *table = &(data->smc_state_table.pp_table);
+
+	if (value > 255)
+		value = 255;
+
+	table->FanPwmMin = value;
+	hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = value * 100 / 255;
+
+	return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetFanMinPwm, table->FanPwmMin);
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
index 21e7c4dfa2ca..bce15e293e6b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
@@ -73,6 +73,10 @@ extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr);
 extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
 extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
 				struct PP_TemperatureRange *range);
+extern int vega10_fan_ctrl_get_min_pwm(struct pp_hwmgr *hwmgr,
+				uint16_t *value);
+extern int vega10_fan_ctrl_set_min_pwm(struct pp_hwmgr *hwmgr,
+				uint16_t value);
 
 
 #endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index d3d96260f440..f104b8212e89 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -328,6 +328,8 @@ struct pp_hwmgr_func {
 	int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n);
 	int (*powergate_mmhub)(struct pp_hwmgr *hwmgr);
 	int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr);
+	int (*get_min_fan_pwm)(struct pp_hwmgr *hwmgr, uint16_t *value);
+	int (*set_min_fan_pwm)(struct pp_hwmgr *hwmgr, uint16_t value);
 };
 
 struct pp_table_func {
-- 
2.18.0



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux