diff options
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r-- | drivers/hwmon/it87.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1ed8b7e2c35d..bb16668ad2bd 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -202,6 +202,17 @@ static int DIV_TO_REG(int val) | |||
202 | } | 202 | } |
203 | #define DIV_FROM_REG(val) (1 << (val)) | 203 | #define DIV_FROM_REG(val) (1 << (val)) |
204 | 204 | ||
205 | static const unsigned int pwm_freq[8] = { | ||
206 | 48000000 / 128, | ||
207 | 24000000 / 128, | ||
208 | 12000000 / 128, | ||
209 | 8000000 / 128, | ||
210 | 6000000 / 128, | ||
211 | 3000000 / 128, | ||
212 | 1500000 / 128, | ||
213 | 750000 / 128, | ||
214 | }; | ||
215 | |||
205 | 216 | ||
206 | /* For each registered IT87, we need to keep some data in memory. That | 217 | /* For each registered IT87, we need to keep some data in memory. That |
207 | data is pointed to by it87_list[NR]->data. The structure itself is | 218 | data is pointed to by it87_list[NR]->data. The structure itself is |
@@ -232,6 +243,7 @@ struct it87_data { | |||
232 | u8 vrm; | 243 | u8 vrm; |
233 | u32 alarms; /* Register encoding, combined */ | 244 | u32 alarms; /* Register encoding, combined */ |
234 | u8 fan_main_ctrl; /* Register value */ | 245 | u8 fan_main_ctrl; /* Register value */ |
246 | u8 fan_ctl; /* Register value */ | ||
235 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 247 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ |
236 | }; | 248 | }; |
237 | 249 | ||
@@ -519,6 +531,14 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
519 | struct it87_data *data = it87_update_device(dev); | 531 | struct it87_data *data = it87_update_device(dev); |
520 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 532 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); |
521 | } | 533 | } |
534 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | ||
535 | char *buf) | ||
536 | { | ||
537 | struct it87_data *data = it87_update_device(dev); | ||
538 | int index = (data->fan_ctl >> 4) & 0x07; | ||
539 | |||
540 | return sprintf(buf, "%u\n", pwm_freq[index]); | ||
541 | } | ||
522 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 542 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
523 | const char *buf, size_t count) | 543 | const char *buf, size_t count) |
524 | { | 544 | { |
@@ -639,6 +659,28 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
639 | mutex_unlock(&data->update_lock); | 659 | mutex_unlock(&data->update_lock); |
640 | return count; | 660 | return count; |
641 | } | 661 | } |
662 | static ssize_t set_pwm_freq(struct device *dev, | ||
663 | struct device_attribute *attr, const char *buf, size_t count) | ||
664 | { | ||
665 | struct i2c_client *client = to_i2c_client(dev); | ||
666 | struct it87_data *data = i2c_get_clientdata(client); | ||
667 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
668 | int i; | ||
669 | |||
670 | /* Search for the nearest available frequency */ | ||
671 | for (i = 0; i < 7; i++) { | ||
672 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | ||
673 | break; | ||
674 | } | ||
675 | |||
676 | mutex_lock(&data->update_lock); | ||
677 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f; | ||
678 | data->fan_ctl |= i << 4; | ||
679 | it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl); | ||
680 | mutex_unlock(&data->update_lock); | ||
681 | |||
682 | return count; | ||
683 | } | ||
642 | 684 | ||
643 | #define show_fan_offset(offset) \ | 685 | #define show_fan_offset(offset) \ |
644 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 686 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
@@ -656,7 +698,10 @@ show_fan_offset(3); | |||
656 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | 698 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
657 | show_pwm_enable, set_pwm_enable, offset - 1); \ | 699 | show_pwm_enable, set_pwm_enable, offset - 1); \ |
658 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | 700 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
659 | show_pwm, set_pwm, offset - 1); | 701 | show_pwm, set_pwm, offset - 1); \ |
702 | static DEVICE_ATTR(pwm##offset##_freq, \ | ||
703 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | ||
704 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | ||
660 | 705 | ||
661 | show_pwm_offset(1); | 706 | show_pwm_offset(1); |
662 | show_pwm_offset(2); | 707 | show_pwm_offset(2); |
@@ -1021,7 +1066,13 @@ static int it87_detect(struct i2c_adapter *adapter) | |||
1021 | || (err = device_create_file(&new_client->dev, | 1066 | || (err = device_create_file(&new_client->dev, |
1022 | &sensor_dev_attr_pwm2.dev_attr)) | 1067 | &sensor_dev_attr_pwm2.dev_attr)) |
1023 | || (err = device_create_file(&new_client->dev, | 1068 | || (err = device_create_file(&new_client->dev, |
1024 | &sensor_dev_attr_pwm3.dev_attr))) | 1069 | &sensor_dev_attr_pwm3.dev_attr)) |
1070 | || (err = device_create_file(&new_client->dev, | ||
1071 | &dev_attr_pwm1_freq)) | ||
1072 | || (err = device_create_file(&new_client->dev, | ||
1073 | &dev_attr_pwm2_freq)) | ||
1074 | || (err = device_create_file(&new_client->dev, | ||
1075 | &dev_attr_pwm3_freq))) | ||
1025 | goto ERROR4; | 1076 | goto ERROR4; |
1026 | } | 1077 | } |
1027 | 1078 | ||
@@ -1316,6 +1367,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1316 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | | 1367 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | |
1317 | (it87_read_value(client, IT87_REG_ALARM3) << 16); | 1368 | (it87_read_value(client, IT87_REG_ALARM3) << 16); |
1318 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); | 1369 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); |
1370 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); | ||
1319 | 1371 | ||
1320 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); | 1372 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); |
1321 | /* The 8705 does not have VID capability */ | 1373 | /* The 8705 does not have VID capability */ |