Commit 53e2761bb2e4ed58913c266ad13e8c10692aec1e

Authored by Yuan Mu
Committed by Greg Kroah-Hartman
1 parent 3dc26c600c

[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>

Showing 1 changed file with 29 additions and 27 deletions Side-by-side Diff

drivers/hwmon/w83792d.c
... ... @@ -250,8 +250,6 @@
250 250 : (val)) / 1000, 0, 0xff))
251 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 253 #define DIV_FROM_REG(val) (1 << (val))
256 254  
257 255 static inline u8
... ... @@ -291,7 +289,6 @@
291 289 u8 pwm[7]; /* We only consider the first 3 set of pwm,
292 290 although 792 chip has 7 set of pwm. */
293 291 u8 pwmenable[3];
294   - u8 pwm_mode[7]; /* indicates PWM or DC mode: 1->PWM; 0->DC */
295 292 u32 alarms; /* realtime status register encoding,combined */
296 293 u8 chassis; /* Chassis status */
297 294 u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */
... ... @@ -627,7 +624,7 @@
627 624 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
628 625 int nr = sensor_attr->index;
629 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 630 static ssize_t
634 631  
635 632  
636 633  
... ... @@ -659,14 +656,16 @@
659 656 const char *buf, size_t count)
660 657 {
661 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 660 struct i2c_client *client = to_i2c_client(dev);
664 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);
668   - data->pwm[nr] = PWM_TO_REG(val);
  664 + mutex_lock(&data->update_lock);
  665 + val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0;
  666 + data->pwm[nr] = val;
669 667 w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
  668 + mutex_unlock(&data->update_lock);
670 669  
671 670 return count;
672 671 }
... ... @@ -707,9 +706,9 @@
707 706 }
708 707  
709 708 static struct sensor_device_attribute sda_pwm[] = {
710   - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
711   - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
712   - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
  709 + SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
  710 + SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
  711 + SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
713 712 };
714 713 static struct sensor_device_attribute sda_pwm_enable[] = {
715 714 SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
... ... @@ -728,7 +727,7 @@
728 727 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
729 728 int nr = sensor_attr->index;
730 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 733 static ssize_t
735 734  
736 735  
737 736  
738 737  
739 738  
740 739  
... ... @@ -736,29 +735,35 @@
736 735 const char *buf, size_t count)
737 736 {
738 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 739 struct i2c_client *client = to_i2c_client(dev);
741 740 struct w83792d_data *data = i2c_get_clientdata(client);
742 741 u32 val;
743   - u8 pwm_mode_mask = 0;
744 742  
745 743 val = simple_strtoul(buf, NULL, 10);
746   - data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1);
747   - pwm_mode_mask = w83792d_read_value(client,
748   - W83792D_REG_PWM[nr]) & 0x7f;
749   - w83792d_write_value(client, W83792D_REG_PWM[nr],
750   - ((data->pwm_mode[nr]) << 7) | pwm_mode_mask);
  744 + if (val != 0 && val != 1)
  745 + return -EINVAL;
751 746  
  747 + mutex_lock(&data->update_lock);
  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);
  756 +
752 757 return count;
753 758 }
754 759  
755 760 static struct sensor_device_attribute sda_pwm_mode[] = {
756 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 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 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 @@
1373 1378 struct i2c_client *client = to_i2c_client(dev);
1374 1379 struct w83792d_data *data = i2c_get_clientdata(client);
1375 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 1383 mutex_lock(&data->update_lock);
1379 1384  
1380 1385  
... ... @@ -1402,10 +1407,8 @@
1402 1407 data->fan_min[i] = w83792d_read_value(client,
1403 1408 W83792D_REG_FAN_MIN[i]);
1404 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 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 1414 reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
... ... @@ -1513,7 +1516,6 @@
1513 1516 dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
1514 1517 dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
1515 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 1520 dev_dbg(dev, "3 set of Temperatures: =====>\n");
1519 1521 for (i=0; i<3; i++) {