diff options
author | Yuan Mu <ymu@winbond.com.tw> | 2006-06-04 14:18:05 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-22 14:10:34 -0400 |
commit | 53e2761bb2e4ed58913c266ad13e8c10692aec1e (patch) | |
tree | 163840e48c2a50f4a86f2a584cd9a697c065075a | |
parent | 3dc26c600cbae8e8e7566136148aef5667e8342b (diff) |
[PATCH] w83792d: Fix setting the PWM value
W83792D use pwm register low 4 bits to store PWM/DC value, bit 7
is used to store fan PWM/DC mode. The store_pwm function did not
convert the pwm input correctly, so it may change the fan mode
when new value is set.
This fix the problem. Change the "index" value of pwm*_mode
and pwm* SENSOR_ATTR to simplify code.
Signed-off-by: Yuan Mu <ymu@winbond.com.tw>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/hwmon/w83792d.c | 56 |
1 files changed, 29 insertions, 27 deletions
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 958602e28412..6cdef18b1b27 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -250,8 +250,6 @@ FAN_TO_REG(long rpm, int div) | |||
250 | : (val)) / 1000, 0, 0xff)) | 250 | : (val)) / 1000, 0, 0xff)) |
251 | #define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) | 251 | #define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) |
252 | 252 | ||
253 | #define PWM_FROM_REG(val) (val) | ||
254 | #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) | ||
255 | #define DIV_FROM_REG(val) (1 << (val)) | 253 | #define DIV_FROM_REG(val) (1 << (val)) |
256 | 254 | ||
257 | static inline u8 | 255 | static inline u8 |
@@ -291,7 +289,6 @@ struct w83792d_data { | |||
291 | u8 pwm[7]; /* We only consider the first 3 set of pwm, | 289 | u8 pwm[7]; /* We only consider the first 3 set of pwm, |
292 | although 792 chip has 7 set of pwm. */ | 290 | although 792 chip has 7 set of pwm. */ |
293 | u8 pwmenable[3]; | 291 | u8 pwmenable[3]; |
294 | u8 pwm_mode[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */ | ||
295 | u32 alarms; /* realtime status register encoding,combined */ | 292 | u32 alarms; /* realtime status register encoding,combined */ |
296 | u8 chassis; /* Chassis status */ | 293 | u8 chassis; /* Chassis status */ |
297 | u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ | 294 | u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ |
@@ -627,7 +624,7 @@ show_pwm(struct device *dev, struct device_attribute *attr, | |||
627 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 624 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
628 | int nr = sensor_attr->index; | 625 | int nr = sensor_attr->index; |
629 | struct w83792d_data *data = w83792d_update_device(dev); | 626 | struct w83792d_data *data = w83792d_update_device(dev); |
630 | return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1])); | 627 | return sprintf(buf, "%d\n", (data->pwm[nr] & 0x0f) << 4); |
631 | } | 628 | } |
632 | 629 | ||
633 | static ssize_t | 630 | static ssize_t |
@@ -659,14 +656,16 @@ store_pwm(struct device *dev, struct device_attribute *attr, | |||
659 | const char *buf, size_t count) | 656 | const char *buf, size_t count) |
660 | { | 657 | { |
661 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 658 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
662 | int nr = sensor_attr->index - 1; | 659 | int nr = sensor_attr->index; |
663 | struct i2c_client *client = to_i2c_client(dev); | 660 | struct i2c_client *client = to_i2c_client(dev); |
664 | struct w83792d_data *data = i2c_get_clientdata(client); | 661 | struct w83792d_data *data = i2c_get_clientdata(client); |
665 | u32 val; | 662 | u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255) >> 4; |
666 | 663 | ||
667 | val = simple_strtoul(buf, NULL, 10); | 664 | mutex_lock(&data->update_lock); |
668 | data->pwm[nr] = PWM_TO_REG(val); | 665 | val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0; |
666 | data->pwm[nr] = val; | ||
669 | w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); | 667 | w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); |
668 | mutex_unlock(&data->update_lock); | ||
670 | 669 | ||
671 | return count; | 670 | return count; |
672 | } | 671 | } |
@@ -707,9 +706,9 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, | |||
707 | } | 706 | } |
708 | 707 | ||
709 | static struct sensor_device_attribute sda_pwm[] = { | 708 | static struct sensor_device_attribute sda_pwm[] = { |
710 | SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), | 709 | SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), |
711 | SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), | 710 | SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), |
712 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), | 711 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), |
713 | }; | 712 | }; |
714 | static struct sensor_device_attribute sda_pwm_enable[] = { | 713 | static struct sensor_device_attribute sda_pwm_enable[] = { |
715 | SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | 714 | SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, |
@@ -728,7 +727,7 @@ show_pwm_mode(struct device *dev, struct device_attribute *attr, | |||
728 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 727 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
729 | int nr = sensor_attr->index; | 728 | int nr = sensor_attr->index; |
730 | struct w83792d_data *data = w83792d_update_device(dev); | 729 | struct w83792d_data *data = w83792d_update_device(dev); |
731 | return sprintf(buf, "%d\n", data->pwm_mode[nr-1]); | 730 | return sprintf(buf, "%d\n", data->pwm[nr] >> 7); |
732 | } | 731 | } |
733 | 732 | ||
734 | static ssize_t | 733 | static ssize_t |
@@ -736,29 +735,35 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, | |||
736 | const char *buf, size_t count) | 735 | const char *buf, size_t count) |
737 | { | 736 | { |
738 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 737 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
739 | int nr = sensor_attr->index - 1; | 738 | int nr = sensor_attr->index; |
740 | struct i2c_client *client = to_i2c_client(dev); | 739 | struct i2c_client *client = to_i2c_client(dev); |
741 | struct w83792d_data *data = i2c_get_clientdata(client); | 740 | struct w83792d_data *data = i2c_get_clientdata(client); |
742 | u32 val; | 741 | u32 val; |
743 | u8 pwm_mode_mask = 0; | ||
744 | 742 | ||
745 | val = simple_strtoul(buf, NULL, 10); | 743 | val = simple_strtoul(buf, NULL, 10); |
746 | data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1); | 744 | if (val != 0 && val != 1) |
747 | pwm_mode_mask = w83792d_read_value(client, | 745 | return -EINVAL; |
748 | W83792D_REG_PWM[nr]) & 0x7f; | 746 | |
749 | w83792d_write_value(client, W83792D_REG_PWM[nr], | 747 | mutex_lock(&data->update_lock); |
750 | ((data->pwm_mode[nr]) << 7) | pwm_mode_mask); | 748 | data->pwm[nr] = w83792d_read_value(client, W83792D_REG_PWM[nr]); |
749 | if (val) { /* PWM mode */ | ||
750 | data->pwm[nr] |= 0x80; | ||
751 | } else { /* DC mode */ | ||
752 | data->pwm[nr] &= 0x7f; | ||
753 | } | ||
754 | w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); | ||
755 | mutex_unlock(&data->update_lock); | ||
751 | 756 | ||
752 | return count; | 757 | return count; |
753 | } | 758 | } |
754 | 759 | ||
755 | static struct sensor_device_attribute sda_pwm_mode[] = { | 760 | static struct sensor_device_attribute sda_pwm_mode[] = { |
756 | SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, | 761 | SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, |
757 | show_pwm_mode, store_pwm_mode, 1), | 762 | show_pwm_mode, store_pwm_mode, 0), |
758 | SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, | 763 | SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, |
759 | show_pwm_mode, store_pwm_mode, 2), | 764 | show_pwm_mode, store_pwm_mode, 1), |
760 | SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, | 765 | SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, |
761 | show_pwm_mode, store_pwm_mode, 3), | 766 | show_pwm_mode, store_pwm_mode, 2), |
762 | }; | 767 | }; |
763 | 768 | ||
764 | 769 | ||
@@ -1373,7 +1378,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) | |||
1373 | struct i2c_client *client = to_i2c_client(dev); | 1378 | struct i2c_client *client = to_i2c_client(dev); |
1374 | struct w83792d_data *data = i2c_get_clientdata(client); | 1379 | struct w83792d_data *data = i2c_get_clientdata(client); |
1375 | int i, j; | 1380 | int i, j; |
1376 | u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; | 1381 | u8 reg_array_tmp[4], reg_tmp; |
1377 | 1382 | ||
1378 | mutex_lock(&data->update_lock); | 1383 | mutex_lock(&data->update_lock); |
1379 | 1384 | ||
@@ -1402,10 +1407,8 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) | |||
1402 | data->fan_min[i] = w83792d_read_value(client, | 1407 | data->fan_min[i] = w83792d_read_value(client, |
1403 | W83792D_REG_FAN_MIN[i]); | 1408 | W83792D_REG_FAN_MIN[i]); |
1404 | /* Update the PWM/DC Value and PWM/DC flag */ | 1409 | /* Update the PWM/DC Value and PWM/DC flag */ |
1405 | pwm_array_tmp[i] = w83792d_read_value(client, | 1410 | data->pwm[i] = w83792d_read_value(client, |
1406 | W83792D_REG_PWM[i]); | 1411 | W83792D_REG_PWM[i]); |
1407 | data->pwm[i] = pwm_array_tmp[i] & 0x0f; | ||
1408 | data->pwm_mode[i] = pwm_array_tmp[i] >> 7; | ||
1409 | } | 1412 | } |
1410 | 1413 | ||
1411 | reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG); | 1414 | reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG); |
@@ -1513,7 +1516,6 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev) | |||
1513 | dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); | 1516 | dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); |
1514 | dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); | 1517 | dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); |
1515 | dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); | 1518 | dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); |
1516 | dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]); | ||
1517 | } | 1519 | } |
1518 | dev_dbg(dev, "3 set of Temperatures: =====>\n"); | 1520 | dev_dbg(dev, "3 set of Temperatures: =====>\n"); |
1519 | for (i=0; i<3; i++) { | 1521 | for (i=0; i<3; i++) { |