diff options
author | Jean Delvare <khali@linux-fr.org> | 2010-03-05 16:17:15 -0500 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2010-03-05 16:17:15 -0500 |
commit | b99883dcd565e30299a6c5c3250725a4d48a8253 (patch) | |
tree | 98e5353f006b3fe8362d8b8dc4af35b1cb256fb5 /drivers/hwmon/it87.c | |
parent | 53de33427fa3d7dd62cc5ec75ce0d4e6c6d602dd (diff) |
hwmon: (it87) Display fan outputs in automatic mode as such
The it87 driver doesn't yet support automatic fan control. Let it at
least tell the user when a fan output is in automatic mode. Also let
the user switch from automatic mode (possibly set by the BIOS) to
manual mode and back without losing the settings.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r-- | drivers/hwmon/it87.c | 99 |
1 files changed, 61 insertions, 38 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0ffe84d190bb..49022bd2a0a5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -281,7 +281,14 @@ struct it87_data { | |||
281 | u32 alarms; /* Register encoding, combined */ | 281 | u32 alarms; /* Register encoding, combined */ |
282 | u8 fan_main_ctrl; /* Register value */ | 282 | u8 fan_main_ctrl; /* Register value */ |
283 | u8 fan_ctl; /* Register value */ | 283 | u8 fan_ctl; /* Register value */ |
284 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 284 | |
285 | /* The following 3 arrays correspond to the same registers. The | ||
286 | * meaning of bits 6-0 depends on the value of bit 7, and we want | ||
287 | * to preserve settings on mode changes, so we have to track all | ||
288 | * values separately. */ | ||
289 | u8 pwm_ctrl[3]; /* Register value */ | ||
290 | u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */ | ||
291 | u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ | ||
285 | }; | 292 | }; |
286 | 293 | ||
287 | static inline int has_16bit_fans(const struct it87_data *data) | 294 | static inline int has_16bit_fans(const struct it87_data *data) |
@@ -531,6 +538,19 @@ show_sensor_offset(2); | |||
531 | show_sensor_offset(3); | 538 | show_sensor_offset(3); |
532 | 539 | ||
533 | /* 3 Fans */ | 540 | /* 3 Fans */ |
541 | |||
542 | static int pwm_mode(const struct it87_data *data, int nr) | ||
543 | { | ||
544 | int ctrl = data->fan_main_ctrl & (1 << nr); | ||
545 | |||
546 | if (ctrl == 0) /* Full speed */ | ||
547 | return 0; | ||
548 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
549 | return 2; | ||
550 | else /* Manual mode */ | ||
551 | return 1; | ||
552 | } | ||
553 | |||
534 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 554 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
535 | char *buf) | 555 | char *buf) |
536 | { | 556 | { |
@@ -567,7 +587,7 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr | |||
567 | int nr = sensor_attr->index; | 587 | int nr = sensor_attr->index; |
568 | 588 | ||
569 | struct it87_data *data = it87_update_device(dev); | 589 | struct it87_data *data = it87_update_device(dev); |
570 | return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0); | 590 | return sprintf(buf, "%d\n", pwm_mode(data, nr)); |
571 | } | 591 | } |
572 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | 592 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, |
573 | char *buf) | 593 | char *buf) |
@@ -576,7 +596,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
576 | int nr = sensor_attr->index; | 596 | int nr = sensor_attr->index; |
577 | 597 | ||
578 | struct it87_data *data = it87_update_device(dev); | 598 | struct it87_data *data = it87_update_device(dev); |
579 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 599 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr])); |
580 | } | 600 | } |
581 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | 601 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, |
582 | char *buf) | 602 | char *buf) |
@@ -660,6 +680,9 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
660 | struct it87_data *data = dev_get_drvdata(dev); | 680 | struct it87_data *data = dev_get_drvdata(dev); |
661 | int val = simple_strtol(buf, NULL, 10); | 681 | int val = simple_strtol(buf, NULL, 10); |
662 | 682 | ||
683 | if (val < 0 || val > 2) | ||
684 | return -EINVAL; | ||
685 | |||
663 | mutex_lock(&data->update_lock); | 686 | mutex_lock(&data->update_lock); |
664 | 687 | ||
665 | if (val == 0) { | 688 | if (val == 0) { |
@@ -670,15 +693,15 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
670 | /* set on/off mode */ | 693 | /* set on/off mode */ |
671 | data->fan_main_ctrl &= ~(1 << nr); | 694 | data->fan_main_ctrl &= ~(1 << nr); |
672 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 695 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); |
673 | } else if (val == 1) { | 696 | } else { |
697 | if (val == 1) /* Manual mode */ | ||
698 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
699 | else /* Automatic mode */ | ||
700 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
701 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
674 | /* set SmartGuardian mode */ | 702 | /* set SmartGuardian mode */ |
675 | data->fan_main_ctrl |= (1 << nr); | 703 | data->fan_main_ctrl |= (1 << nr); |
676 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 704 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); |
677 | /* set saved pwm value, clear FAN_CTLX PWM mode bit */ | ||
678 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | ||
679 | } else { | ||
680 | mutex_unlock(&data->update_lock); | ||
681 | return -EINVAL; | ||
682 | } | 705 | } |
683 | 706 | ||
684 | mutex_unlock(&data->update_lock); | 707 | mutex_unlock(&data->update_lock); |
@@ -697,9 +720,13 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
697 | return -EINVAL; | 720 | return -EINVAL; |
698 | 721 | ||
699 | mutex_lock(&data->update_lock); | 722 | mutex_lock(&data->update_lock); |
700 | data->manual_pwm_ctl[nr] = val; | 723 | data->pwm_duty[nr] = PWM_TO_REG(val); |
701 | if (data->fan_main_ctrl & (1 << nr)) | 724 | /* If we are in manual mode, write the duty cycle immediately; |
702 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | 725 | * otherwise, just store it for later use. */ |
726 | if (!(data->pwm_ctrl[nr] & 0x80)) { | ||
727 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
728 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
729 | } | ||
703 | mutex_unlock(&data->update_lock); | 730 | mutex_unlock(&data->update_lock); |
704 | return count; | 731 | return count; |
705 | } | 732 | } |
@@ -1387,15 +1414,17 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1387 | int tmp, i; | 1414 | int tmp, i; |
1388 | u8 mask; | 1415 | u8 mask; |
1389 | 1416 | ||
1390 | /* initialize to sane defaults: | 1417 | /* For each PWM channel: |
1391 | * - if the chip is in manual pwm mode, this will be overwritten with | 1418 | * - If it is in automatic mode, setting to manual mode should set |
1392 | * the actual settings on the chip (so in this case, initialization | 1419 | * the fan to full speed by default. |
1393 | * is not needed) | 1420 | * - If it is in manual mode, we need a mapping to temperature |
1394 | * - if in automatic or on/off mode, we could switch to manual mode, | 1421 | * channels to use when later setting to automatic mode later. |
1395 | * read the registers and set manual_pwm_ctl accordingly, but currently | 1422 | * Use a 1:1 mapping by default (we are clueless.) |
1396 | * this is not implemented, so we initialize to something sane */ | 1423 | * In both cases, the value can (and should) be changed by the user |
1424 | * prior to switching to a different mode. */ | ||
1397 | for (i = 0; i < 3; i++) { | 1425 | for (i = 0; i < 3; i++) { |
1398 | data->manual_pwm_ctl[i] = 0xff; | 1426 | data->pwm_temp_map[i] = i; |
1427 | data->pwm_duty[i] = 0x7f; /* Full speed */ | ||
1399 | } | 1428 | } |
1400 | 1429 | ||
1401 | /* Some chips seem to have default value 0xff for all limit | 1430 | /* Some chips seem to have default value 0xff for all limit |
@@ -1461,30 +1490,21 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1461 | /* Fan input pins may be used for alternative functions */ | 1490 | /* Fan input pins may be used for alternative functions */ |
1462 | data->has_fan &= ~sio_data->skip_fan; | 1491 | data->has_fan &= ~sio_data->skip_fan; |
1463 | 1492 | ||
1464 | /* Set current fan mode registers and the default settings for the | ||
1465 | * other mode registers */ | ||
1466 | for (i = 0; i < 3; i++) { | ||
1467 | if (data->fan_main_ctrl & (1 << i)) { | ||
1468 | /* pwm mode */ | ||
1469 | tmp = it87_read_value(data, IT87_REG_PWM(i)); | ||
1470 | if (tmp & 0x80) { | ||
1471 | /* automatic pwm - not yet implemented, but | ||
1472 | * leave the settings made by the BIOS alone | ||
1473 | * until a change is requested via the sysfs | ||
1474 | * interface */ | ||
1475 | } else { | ||
1476 | /* manual pwm */ | ||
1477 | data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp); | ||
1478 | } | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | /* Start monitoring */ | 1493 | /* Start monitoring */ |
1483 | it87_write_value(data, IT87_REG_CONFIG, | 1494 | it87_write_value(data, IT87_REG_CONFIG, |
1484 | (it87_read_value(data, IT87_REG_CONFIG) & 0x36) | 1495 | (it87_read_value(data, IT87_REG_CONFIG) & 0x36) |
1485 | | (update_vbat ? 0x41 : 0x01)); | 1496 | | (update_vbat ? 0x41 : 0x01)); |
1486 | } | 1497 | } |
1487 | 1498 | ||
1499 | static void it87_update_pwm_ctrl(struct it87_data *data, int nr) | ||
1500 | { | ||
1501 | data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); | ||
1502 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
1503 | data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; | ||
1504 | else /* Manual mode */ | ||
1505 | data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; | ||
1506 | } | ||
1507 | |||
1488 | static struct it87_data *it87_update_device(struct device *dev) | 1508 | static struct it87_data *it87_update_device(struct device *dev) |
1489 | { | 1509 | { |
1490 | struct it87_data *data = dev_get_drvdata(dev); | 1510 | struct it87_data *data = dev_get_drvdata(dev); |
@@ -1551,9 +1571,12 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1551 | it87_read_value(data, IT87_REG_ALARM1) | | 1571 | it87_read_value(data, IT87_REG_ALARM1) | |
1552 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | | 1572 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | |
1553 | (it87_read_value(data, IT87_REG_ALARM3) << 16); | 1573 | (it87_read_value(data, IT87_REG_ALARM3) << 16); |
1574 | |||
1554 | data->fan_main_ctrl = it87_read_value(data, | 1575 | data->fan_main_ctrl = it87_read_value(data, |
1555 | IT87_REG_FAN_MAIN_CTRL); | 1576 | IT87_REG_FAN_MAIN_CTRL); |
1556 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); | 1577 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); |
1578 | for (i = 0; i < 3; i++) | ||
1579 | it87_update_pwm_ctrl(data, i); | ||
1557 | 1580 | ||
1558 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1581 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
1559 | /* The 8705 does not have VID capability. | 1582 | /* The 8705 does not have VID capability. |