diff --git a/CHANGES b/CHANGES index e89327d0..d66974d9 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ ask CVS about it: Module w83781d: Improve w83783s support, w83627hf always has 2 pwm Module w83781d: Fix sensor2&3 selection, enable VBAT (in8) monitoring Module w83781d: Remove as99127f entries for in7-8, pwm3-4, sensor1-3 + Module w83781d: Fis as99127f fan speed (was 66% too high) Module w83781d: Improve beep input checking Program i2cdump: Add Winbond-style bank selection Program isadump: Add Winbond-style bank selection diff --git a/doc/chips/w83781d b/doc/chips/w83781d index b10289dc..897a41fc 100644 --- a/doc/chips/w83781d +++ b/doc/chips/w83781d @@ -148,10 +148,10 @@ AS99127F PROBLEMS ----------------- The as99127f support was developed without the benefit of a datasheet. In most cases it is treated as a w83781d. -This support is BETA. One user has reported problems with fans stopping. +This support is BETA. One user has reported problems with fans stopping +occasionally. Known problems: - - Fans read about 30% low. - -12V readings a little high (-9.5V to -10.5V) - Problems with diode/thermistor settings (supported?) - fan_div register may not really be fan_div. diff --git a/kernel/chips/w83781d.c b/kernel/chips/w83781d.c index 9bc3f078..7e16124c 100644 --- a/kernel/chips/w83781d.c +++ b/kernel/chips/w83781d.c @@ -167,8 +167,18 @@ extern inline u8 FAN_TO_REG(long rpm, int div) return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); } +extern inline u8 AS_FAN_TO_REG(long rpm, int div) +{ + if (rpm == 0) + return 255; + rpm = SENSORS_LIMIT(rpm, 1, 1000000); + return SENSORS_LIMIT((810000 + rpm * div / 2) / (rpm * div), 1, + 254); +} #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) +#define AS_FAN_FROM_REG(val,div) \ + ((val)==0?-1:(val)==255?0:810000/((val)*(div))) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\ ((val)+5)/10),0,255)) @@ -1298,12 +1308,21 @@ void w83781d_init_client(struct i2c_client *client) w83781d_write_value(client, W83781D_REG_VBAT, (w83781d_read_value(client, W83781D_REG_VBAT) | 0x01)); } - w83781d_write_value(client, W83781D_REG_FAN_MIN(1), - FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2)); - w83781d_write_value(client, W83781D_REG_FAN_MIN(2), - FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2)); - w83781d_write_value(client, W83781D_REG_FAN_MIN(3), - FAN_TO_REG(W83781D_INIT_FAN_MIN_3, 2)); + if (type == as99127f) { + w83781d_write_value(client, W83781D_REG_FAN_MIN(1), + AS_FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2)); + w83781d_write_value(client, W83781D_REG_FAN_MIN(2), + AS_FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2)); + w83781d_write_value(client, W83781D_REG_FAN_MIN(3), + AS_FAN_TO_REG(W83781D_INIT_FAN_MIN_3, 2)); + } else { + w83781d_write_value(client, W83781D_REG_FAN_MIN(1), + FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2)); + w83781d_write_value(client, W83781D_REG_FAN_MIN(2), + FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2)); + w83781d_write_value(client, W83781D_REG_FAN_MIN(3), + FAN_TO_REG(W83781D_INIT_FAN_MIN_3, 2)); + } w83781d_write_value(client, W83781D_REG_TEMP_OVER, TEMP_TO_REG(W83781D_INIT_TEMP_OVER)); @@ -1521,20 +1540,29 @@ void w83781d_fan(struct i2c_client *client, int operation, int ctl_name, *nrels_mag = 0; else if (operation == SENSORS_PROC_REAL_READ) { w83781d_update_client(client); - results[0] = FAN_FROM_REG(data->fan_min[nr - 1], - DIV_FROM_REG(data-> - fan_div[nr - 1])); - results[1] = - FAN_FROM_REG(data->fan[nr - 1], - DIV_FROM_REG(data->fan_div[nr - 1])); + if(data->type == as99127f) { + results[0] = AS_FAN_FROM_REG(data->fan_min[nr - 1], + DIV_FROM_REG(data->fan_div[nr - 1])); + results[1] = AS_FAN_FROM_REG(data->fan[nr - 1], + DIV_FROM_REG(data->fan_div[nr - 1])); + } else { + results[0] = FAN_FROM_REG(data->fan_min[nr - 1], + DIV_FROM_REG(data->fan_div[nr - 1])); + results[1] = FAN_FROM_REG(data->fan[nr - 1], + DIV_FROM_REG(data->fan_div[nr - 1])); + } *nrels_mag = 2; } else if (operation == SENSORS_PROC_REAL_WRITE) { if (*nrels_mag >= 1) { - data->fan_min[nr - 1] = FAN_TO_REG(results[0], - DIV_FROM_REG - (data-> - fan_div[nr - - 1])); + if(data->type == as99127f) { + data->fan_min[nr - 1] = + AS_FAN_TO_REG(results[0], + DIV_FROM_REG(data->fan_div[nr-1])); + } else { + data->fan_min[nr - 1] = + FAN_TO_REG(results[0], + DIV_FROM_REG(data->fan_div[nr-1])); + } w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), data->fan_min[nr - 1]);