summaryrefslogtreecommitdiff
path: root/drivers/acpi/ibm_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/ibm_acpi.c')
-rw-r--r--drivers/acpi/ibm_acpi.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 3c091c4b461f..56743c5a0439 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -362,7 +362,7 @@ enum { /* Fan control constants */
* control */
};
-static char* ibm_thinkpad_ec_found = NULL;
+static char *ibm_thinkpad_ec_found = NULL;
struct ibm_struct {
char *name;
@@ -1794,13 +1794,15 @@ static enum fan_status_access_mode fan_status_access_mode;
static enum fan_control_access_mode fan_control_access_mode;
static enum fan_control_commands fan_control_commands;
+static int fan_control_status_known;
+static u8 fan_control_initial_status;
+
static int fan_init(void)
{
- u8 status;
-
fan_status_access_mode = IBMACPI_FAN_NONE;
fan_control_access_mode = IBMACPI_FAN_WR_NONE;
fan_control_commands = 0;
+ fan_control_status_known = 1;
if (gfan_handle) {
/* 570, 600e/x, 770e, 770x */
@@ -1808,8 +1810,33 @@ static int fan_init(void)
} else {
/* all other ThinkPads: note that even old-style
* ThinkPad ECs supports the fan control register */
- if (likely(acpi_ec_read(fan_status_offset, &status))) {
+ if (likely(acpi_ec_read(fan_status_offset,
+ &fan_control_initial_status))) {
fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
+
+ /* In some ThinkPads, neither the EC nor the ACPI
+ * DSDT initialize the fan status, and it ends up
+ * being set to 0x07 when it *could* be either
+ * 0x07 or 0x80.
+ *
+ * Enable for TP-1Y (T43), TP-78 (R51e),
+ * TP-76 (R52), TP-70 (T43, R52), which are known
+ * to be buggy. */
+ if (fan_control_initial_status == 0x07 &&
+ ibm_thinkpad_ec_found &&
+ ((ibm_thinkpad_ec_found[0] == '1' &&
+ ibm_thinkpad_ec_found[1] == 'Y') ||
+ (ibm_thinkpad_ec_found[0] == '7' &&
+ (ibm_thinkpad_ec_found[1] == '6' ||
+ ibm_thinkpad_ec_found[1] == '8' ||
+ ibm_thinkpad_ec_found[1] == '0'))
+ )) {
+ printk(IBM_NOTICE
+ "fan_init: initial fan status is "
+ "unknown, assuming it is in auto "
+ "mode\n");
+ fan_control_status_known = 0;
+ }
} else {
printk(IBM_ERR
"ThinkPad ACPI EC access misbehaving, "
@@ -1930,9 +1957,21 @@ static int fan_read(char *p)
if ((rc = fan_get_status(&status)) < 0)
return rc;
+ if (unlikely(!fan_control_status_known)) {
+ if (status != fan_control_initial_status)
+ fan_control_status_known = 1;
+ else
+ /* Return most likely status. In fact, it
+ * might be the only possible status */
+ status = IBMACPI_FAN_EC_AUTO;
+ }
+
len += sprintf(p + len, "status:\t\t%s\n",
(status != 0) ? "enabled" : "disabled");
+ /* No ThinkPad boots on disengaged mode, we can safely
+ * assume the tachometer is online if fan control status
+ * was unknown */
if ((rc = fan_get_speed(&speed)) < 0)
return rc;
@@ -1997,6 +2036,8 @@ static int fan_set_level(int level)
if (!acpi_ec_write(fan_status_offset, level))
return -EIO;
+ else
+ fan_control_status_known = 1;
break;
default:
@@ -2022,6 +2063,8 @@ static int fan_set_enable(void)
if (!acpi_ec_write(fan_status_offset, s))
return -EIO;
+ else
+ fan_control_status_known = 1;
break;
case IBMACPI_FAN_WR_ACPI_SFAN:
@@ -2051,6 +2094,8 @@ static int fan_set_disable(void)
case IBMACPI_FAN_WR_TPEC:
if (!acpi_ec_write(fan_status_offset, 0x00))
return -EIO;
+ else
+ fan_control_status_known = 1;
break;
case IBMACPI_FAN_WR_ACPI_SFAN: