diff options
author | Rex Zhu <Rex.Zhu@amd.com> | 2018-09-20 02:30:55 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-10-09 18:04:59 -0400 |
commit | c2870527f700e919fbb543baef36032be5d626e0 (patch) | |
tree | f996053555b057b64705719f88cb5c12c66333dd /drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |
parent | d5f480372ca485806443afca50ef024623f8eb03 (diff) |
drm/amdgpu: Add fan RPM setting via sysfs
Add fan1_target for get/set fan speed in RPM unit
Add fan1_min/fan1_max for get min, max fan speed in RPM unit
Add fan1_enable to enable/disable the fan1 sensor
v3: drop the hardcode value of min/max rpm in comments pointed
out by Alex.
v2: query the min/max rpm gpu support instand of hardcode value.
Reviewed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 190 |
1 files changed, 187 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 18d989e0e362..a9f68753ec7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
@@ -1172,6 +1172,11 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, | |||
1172 | struct amdgpu_device *adev = dev_get_drvdata(dev); | 1172 | struct amdgpu_device *adev = dev_get_drvdata(dev); |
1173 | int err; | 1173 | int err; |
1174 | u32 speed = 0; | 1174 | u32 speed = 0; |
1175 | u32 pwm_mode; | ||
1176 | |||
1177 | pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); | ||
1178 | if (pwm_mode != AMD_FAN_CTRL_MANUAL) | ||
1179 | return -ENODATA; | ||
1175 | 1180 | ||
1176 | /* Can't adjust fan when the card is off */ | 1181 | /* Can't adjust fan when the card is off */ |
1177 | if ((adev->flags & AMD_IS_PX) && | 1182 | if ((adev->flags & AMD_IS_PX) && |
@@ -1187,6 +1192,153 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, | |||
1187 | return sprintf(buf, "%i\n", speed); | 1192 | return sprintf(buf, "%i\n", speed); |
1188 | } | 1193 | } |
1189 | 1194 | ||
1195 | static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, | ||
1196 | struct device_attribute *attr, | ||
1197 | char *buf) | ||
1198 | { | ||
1199 | struct amdgpu_device *adev = dev_get_drvdata(dev); | ||
1200 | u32 min_rpm = 0; | ||
1201 | u32 size = sizeof(min_rpm); | ||
1202 | int r; | ||
1203 | |||
1204 | if (!adev->powerplay.pp_funcs->read_sensor) | ||
1205 | return -EINVAL; | ||
1206 | |||
1207 | r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, | ||
1208 | (void *)&min_rpm, &size); | ||
1209 | if (r) | ||
1210 | return r; | ||
1211 | |||
1212 | return snprintf(buf, PAGE_SIZE, "%d\n", min_rpm); | ||
1213 | } | ||
1214 | |||
1215 | static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, | ||
1216 | struct device_attribute *attr, | ||
1217 | char *buf) | ||
1218 | { | ||
1219 | struct amdgpu_device *adev = dev_get_drvdata(dev); | ||
1220 | u32 max_rpm = 0; | ||
1221 | u32 size = sizeof(max_rpm); | ||
1222 | int r; | ||
1223 | |||
1224 | if (!adev->powerplay.pp_funcs->read_sensor) | ||
1225 | return -EINVAL; | ||
1226 | |||
1227 | r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, | ||
1228 | (void *)&max_rpm, &size); | ||
1229 | if (r) | ||
1230 | return r; | ||
1231 | |||
1232 | return snprintf(buf, PAGE_SIZE, "%d\n", max_rpm); | ||
1233 | } | ||
1234 | |||
1235 | static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, | ||
1236 | struct device_attribute *attr, | ||
1237 | char *buf) | ||
1238 | { | ||
1239 | struct amdgpu_device *adev = dev_get_drvdata(dev); | ||
1240 | int err; | ||
1241 | u32 rpm = 0; | ||
1242 | u32 pwm_mode; | ||
1243 | |||
1244 | pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); | ||
1245 | if (pwm_mode != AMD_FAN_CTRL_MANUAL) | ||
1246 | return -ENODATA; | ||
1247 | |||
1248 | /* Can't adjust fan when the card is off */ | ||
1249 | if ((adev->flags & AMD_IS_PX) && | ||
1250 | (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
1251 | return -EINVAL; | ||
1252 | |||
1253 | if (adev->powerplay.pp_funcs->get_fan_speed_rpm) { | ||
1254 | err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); | ||
1255 | if (err) | ||
1256 | return err; | ||
1257 | } | ||
1258 | |||
1259 | return sprintf(buf, "%i\n", rpm); | ||
1260 | } | ||
1261 | |||
1262 | static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, | ||
1263 | struct device_attribute *attr, | ||
1264 | const char *buf, size_t count) | ||
1265 | { | ||
1266 | struct amdgpu_device *adev = dev_get_drvdata(dev); | ||
1267 | int err; | ||
1268 | u32 value; | ||
1269 | u32 pwm_mode; | ||
1270 | |||
1271 | pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); | ||
1272 | if (pwm_mode != AMD_FAN_CTRL_MANUAL) | ||
1273 | return -ENODATA; | ||
1274 | |||
1275 | /* Can't adjust fan when the card is off */ | ||
1276 | if ((adev->flags & AMD_IS_PX) && | ||
1277 | (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
1278 | return -EINVAL; | ||
1279 | |||
1280 | err = kstrtou32(buf, 10, &value); | ||
1281 | if (err) | ||
1282 | return err; | ||
1283 | |||
1284 | if (adev->powerplay.pp_funcs->set_fan_speed_rpm) { | ||
1285 | err = amdgpu_dpm_set_fan_speed_rpm(adev, value); | ||
1286 | if (err) | ||
1287 | return err; | ||
1288 | } | ||
1289 | |||
1290 | return count; | ||
1291 | } | ||
1292 | |||
1293 | static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, | ||
1294 | struct device_attribute *attr, | ||
1295 | char *buf) | ||
1296 | { | ||
1297 | struct amdgpu_device *adev = dev_get_drvdata(dev); | ||
1298 | u32 pwm_mode = 0; | ||
1299 | |||
1300 | if (!adev->powerplay.pp_funcs->get_fan_control_mode) | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); | ||
1304 | |||
1305 | return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); | ||
1306 | } | ||
1307 | |||
1308 | static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, | ||
1309 | struct device_attribute *attr, | ||
1310 | const char *buf, | ||
1311 | size_t count) | ||
1312 | { | ||
1313 | struct amdgpu_device *adev = dev_get_drvdata(dev); | ||
1314 | int err; | ||
1315 | int value; | ||
1316 | u32 pwm_mode; | ||
1317 | |||
1318 | /* Can't adjust fan when the card is off */ | ||
1319 | if ((adev->flags & AMD_IS_PX) && | ||
1320 | (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
1321 | return -EINVAL; | ||
1322 | |||
1323 | if (!adev->powerplay.pp_funcs->set_fan_control_mode) | ||
1324 | return -EINVAL; | ||
1325 | |||
1326 | err = kstrtoint(buf, 10, &value); | ||
1327 | if (err) | ||
1328 | return err; | ||
1329 | |||
1330 | if (value == 0) | ||
1331 | pwm_mode = AMD_FAN_CTRL_AUTO; | ||
1332 | else if (value == 1) | ||
1333 | pwm_mode = AMD_FAN_CTRL_MANUAL; | ||
1334 | else | ||
1335 | return -EINVAL; | ||
1336 | |||
1337 | amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); | ||
1338 | |||
1339 | return count; | ||
1340 | } | ||
1341 | |||
1190 | static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, | 1342 | static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, |
1191 | struct device_attribute *attr, | 1343 | struct device_attribute *attr, |
1192 | char *buf) | 1344 | char *buf) |
@@ -1406,8 +1558,16 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, | |||
1406 | * | 1558 | * |
1407 | * - pwm1_max: pulse width modulation fan control maximum level (255) | 1559 | * - pwm1_max: pulse width modulation fan control maximum level (255) |
1408 | * | 1560 | * |
1561 | * - fan1_min: an minimum value Unit: revolution/min (RPM) | ||
1562 | * | ||
1563 | * - fan1_max: an maxmum value Unit: revolution/max (RPM) | ||
1564 | * | ||
1409 | * - fan1_input: fan speed in RPM | 1565 | * - fan1_input: fan speed in RPM |
1410 | * | 1566 | * |
1567 | * - fan[1-*]_target: Desired fan speed Unit: revolution/min (RPM) | ||
1568 | * | ||
1569 | * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable | ||
1570 | * | ||
1411 | * You can use hwmon tools like sensors to view this information on your system. | 1571 | * You can use hwmon tools like sensors to view this information on your system. |
1412 | * | 1572 | * |
1413 | */ | 1573 | */ |
@@ -1420,6 +1580,10 @@ static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_ | |||
1420 | static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0); | 1580 | static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0); |
1421 | static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0); | 1581 | static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0); |
1422 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0); | 1582 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0); |
1583 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, amdgpu_hwmon_get_fan1_min, NULL, 0); | ||
1584 | static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO, amdgpu_hwmon_get_fan1_max, NULL, 0); | ||
1585 | static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_target, amdgpu_hwmon_set_fan1_target, 0); | ||
1586 | static SENSOR_DEVICE_ATTR(fan1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_enable, amdgpu_hwmon_set_fan1_enable, 0); | ||
1423 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0); | 1587 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0); |
1424 | static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, amdgpu_hwmon_show_vddgfx_label, NULL, 0); | 1588 | static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, amdgpu_hwmon_show_vddgfx_label, NULL, 0); |
1425 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, amdgpu_hwmon_show_vddnb, NULL, 0); | 1589 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, amdgpu_hwmon_show_vddnb, NULL, 0); |
@@ -1438,6 +1602,10 @@ static struct attribute *hwmon_attributes[] = { | |||
1438 | &sensor_dev_attr_pwm1_min.dev_attr.attr, | 1602 | &sensor_dev_attr_pwm1_min.dev_attr.attr, |
1439 | &sensor_dev_attr_pwm1_max.dev_attr.attr, | 1603 | &sensor_dev_attr_pwm1_max.dev_attr.attr, |
1440 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 1604 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
1605 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
1606 | &sensor_dev_attr_fan1_max.dev_attr.attr, | ||
1607 | &sensor_dev_attr_fan1_target.dev_attr.attr, | ||
1608 | &sensor_dev_attr_fan1_enable.dev_attr.attr, | ||
1441 | &sensor_dev_attr_in0_input.dev_attr.attr, | 1609 | &sensor_dev_attr_in0_input.dev_attr.attr, |
1442 | &sensor_dev_attr_in0_label.dev_attr.attr, | 1610 | &sensor_dev_attr_in0_label.dev_attr.attr, |
1443 | &sensor_dev_attr_in1_input.dev_attr.attr, | 1611 | &sensor_dev_attr_in1_input.dev_attr.attr, |
@@ -1456,13 +1624,16 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, | |||
1456 | struct amdgpu_device *adev = dev_get_drvdata(dev); | 1624 | struct amdgpu_device *adev = dev_get_drvdata(dev); |
1457 | umode_t effective_mode = attr->mode; | 1625 | umode_t effective_mode = attr->mode; |
1458 | 1626 | ||
1459 | |||
1460 | /* Skip fan attributes if fan is not present */ | 1627 | /* Skip fan attributes if fan is not present */ |
1461 | if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || | 1628 | if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || |
1462 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || | 1629 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || |
1463 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | 1630 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || |
1464 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || | 1631 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || |
1465 | attr == &sensor_dev_attr_fan1_input.dev_attr.attr)) | 1632 | attr == &sensor_dev_attr_fan1_input.dev_attr.attr || |
1633 | attr == &sensor_dev_attr_fan1_min.dev_attr.attr || | ||
1634 | attr == &sensor_dev_attr_fan1_max.dev_attr.attr || | ||
1635 | attr == &sensor_dev_attr_fan1_target.dev_attr.attr || | ||
1636 | attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) | ||
1466 | return 0; | 1637 | return 0; |
1467 | 1638 | ||
1468 | /* Skip limit attributes if DPM is not enabled */ | 1639 | /* Skip limit attributes if DPM is not enabled */ |
@@ -1472,7 +1643,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, | |||
1472 | attr == &sensor_dev_attr_pwm1.dev_attr.attr || | 1643 | attr == &sensor_dev_attr_pwm1.dev_attr.attr || |
1473 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || | 1644 | attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || |
1474 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | 1645 | attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || |
1475 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) | 1646 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || |
1647 | attr == &sensor_dev_attr_fan1_input.dev_attr.attr || | ||
1648 | attr == &sensor_dev_attr_fan1_min.dev_attr.attr || | ||
1649 | attr == &sensor_dev_attr_fan1_max.dev_attr.attr || | ||
1650 | attr == &sensor_dev_attr_fan1_target.dev_attr.attr || | ||
1651 | attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) | ||
1476 | return 0; | 1652 | return 0; |
1477 | 1653 | ||
1478 | /* mask fan attributes if we have no bindings for this asic to expose */ | 1654 | /* mask fan attributes if we have no bindings for this asic to expose */ |
@@ -1497,10 +1673,18 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, | |||
1497 | /* hide max/min values if we can't both query and manage the fan */ | 1673 | /* hide max/min values if we can't both query and manage the fan */ |
1498 | if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && | 1674 | if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && |
1499 | !adev->powerplay.pp_funcs->get_fan_speed_percent) && | 1675 | !adev->powerplay.pp_funcs->get_fan_speed_percent) && |
1676 | (!adev->powerplay.pp_funcs->set_fan_speed_rpm && | ||
1677 | !adev->powerplay.pp_funcs->get_fan_speed_rpm) && | ||
1500 | (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || | 1678 | (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || |
1501 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) | 1679 | attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) |
1502 | return 0; | 1680 | return 0; |
1503 | 1681 | ||
1682 | if ((!adev->powerplay.pp_funcs->set_fan_speed_rpm && | ||
1683 | !adev->powerplay.pp_funcs->get_fan_speed_rpm) && | ||
1684 | (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || | ||
1685 | attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) | ||
1686 | return 0; | ||
1687 | |||
1504 | /* only APUs have vddnb */ | 1688 | /* only APUs have vddnb */ |
1505 | if (!(adev->flags & AMD_IS_APU) && | 1689 | if (!(adev->flags & AMD_IS_APU) && |
1506 | (attr == &sensor_dev_attr_in1_input.dev_attr.attr || | 1690 | (attr == &sensor_dev_attr_in1_input.dev_attr.attr || |