diff options
Diffstat (limited to 'drivers/acpi/ibm_acpi.c')
-rw-r--r-- | drivers/acpi/ibm_acpi.c | 53 |
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 */ | |||
362 | * control */ | 362 | * control */ |
363 | }; | 363 | }; |
364 | 364 | ||
365 | static char* ibm_thinkpad_ec_found = NULL; | 365 | static char *ibm_thinkpad_ec_found = NULL; |
366 | 366 | ||
367 | struct ibm_struct { | 367 | struct ibm_struct { |
368 | char *name; | 368 | char *name; |
@@ -1794,13 +1794,15 @@ static enum fan_status_access_mode fan_status_access_mode; | |||
1794 | static enum fan_control_access_mode fan_control_access_mode; | 1794 | static enum fan_control_access_mode fan_control_access_mode; |
1795 | static enum fan_control_commands fan_control_commands; | 1795 | static enum fan_control_commands fan_control_commands; |
1796 | 1796 | ||
1797 | static int fan_control_status_known; | ||
1798 | static u8 fan_control_initial_status; | ||
1799 | |||
1797 | static int fan_init(void) | 1800 | static int fan_init(void) |
1798 | { | 1801 | { |
1799 | u8 status; | ||
1800 | |||
1801 | fan_status_access_mode = IBMACPI_FAN_NONE; | 1802 | fan_status_access_mode = IBMACPI_FAN_NONE; |
1802 | fan_control_access_mode = IBMACPI_FAN_WR_NONE; | 1803 | fan_control_access_mode = IBMACPI_FAN_WR_NONE; |
1803 | fan_control_commands = 0; | 1804 | fan_control_commands = 0; |
1805 | fan_control_status_known = 1; | ||
1804 | 1806 | ||
1805 | if (gfan_handle) { | 1807 | if (gfan_handle) { |
1806 | /* 570, 600e/x, 770e, 770x */ | 1808 | /* 570, 600e/x, 770e, 770x */ |
@@ -1808,8 +1810,33 @@ static int fan_init(void) | |||
1808 | } else { | 1810 | } else { |
1809 | /* all other ThinkPads: note that even old-style | 1811 | /* all other ThinkPads: note that even old-style |
1810 | * ThinkPad ECs supports the fan control register */ | 1812 | * ThinkPad ECs supports the fan control register */ |
1811 | if (likely(acpi_ec_read(fan_status_offset, &status))) { | 1813 | if (likely(acpi_ec_read(fan_status_offset, |
1814 | &fan_control_initial_status))) { | ||
1812 | fan_status_access_mode = IBMACPI_FAN_RD_TPEC; | 1815 | fan_status_access_mode = IBMACPI_FAN_RD_TPEC; |
1816 | |||
1817 | /* In some ThinkPads, neither the EC nor the ACPI | ||
1818 | * DSDT initialize the fan status, and it ends up | ||
1819 | * being set to 0x07 when it *could* be either | ||
1820 | * 0x07 or 0x80. | ||
1821 | * | ||
1822 | * Enable for TP-1Y (T43), TP-78 (R51e), | ||
1823 | * TP-76 (R52), TP-70 (T43, R52), which are known | ||
1824 | * to be buggy. */ | ||
1825 | if (fan_control_initial_status == 0x07 && | ||
1826 | ibm_thinkpad_ec_found && | ||
1827 | ((ibm_thinkpad_ec_found[0] == '1' && | ||
1828 | ibm_thinkpad_ec_found[1] == 'Y') || | ||
1829 | (ibm_thinkpad_ec_found[0] == '7' && | ||
1830 | (ibm_thinkpad_ec_found[1] == '6' || | ||
1831 | ibm_thinkpad_ec_found[1] == '8' || | ||
1832 | ibm_thinkpad_ec_found[1] == '0')) | ||
1833 | )) { | ||
1834 | printk(IBM_NOTICE | ||
1835 | "fan_init: initial fan status is " | ||
1836 | "unknown, assuming it is in auto " | ||
1837 | "mode\n"); | ||
1838 | fan_control_status_known = 0; | ||
1839 | } | ||
1813 | } else { | 1840 | } else { |
1814 | printk(IBM_ERR | 1841 | printk(IBM_ERR |
1815 | "ThinkPad ACPI EC access misbehaving, " | 1842 | "ThinkPad ACPI EC access misbehaving, " |
@@ -1930,9 +1957,21 @@ static int fan_read(char *p) | |||
1930 | if ((rc = fan_get_status(&status)) < 0) | 1957 | if ((rc = fan_get_status(&status)) < 0) |
1931 | return rc; | 1958 | return rc; |
1932 | 1959 | ||
1960 | if (unlikely(!fan_control_status_known)) { | ||
1961 | if (status != fan_control_initial_status) | ||
1962 | fan_control_status_known = 1; | ||
1963 | else | ||
1964 | /* Return most likely status. In fact, it | ||
1965 | * might be the only possible status */ | ||
1966 | status = IBMACPI_FAN_EC_AUTO; | ||
1967 | } | ||
1968 | |||
1933 | len += sprintf(p + len, "status:\t\t%s\n", | 1969 | len += sprintf(p + len, "status:\t\t%s\n", |
1934 | (status != 0) ? "enabled" : "disabled"); | 1970 | (status != 0) ? "enabled" : "disabled"); |
1935 | 1971 | ||
1972 | /* No ThinkPad boots on disengaged mode, we can safely | ||
1973 | * assume the tachometer is online if fan control status | ||
1974 | * was unknown */ | ||
1936 | if ((rc = fan_get_speed(&speed)) < 0) | 1975 | if ((rc = fan_get_speed(&speed)) < 0) |
1937 | return rc; | 1976 | return rc; |
1938 | 1977 | ||
@@ -1997,6 +2036,8 @@ static int fan_set_level(int level) | |||
1997 | 2036 | ||
1998 | if (!acpi_ec_write(fan_status_offset, level)) | 2037 | if (!acpi_ec_write(fan_status_offset, level)) |
1999 | return -EIO; | 2038 | return -EIO; |
2039 | else | ||
2040 | fan_control_status_known = 1; | ||
2000 | break; | 2041 | break; |
2001 | 2042 | ||
2002 | default: | 2043 | default: |
@@ -2022,6 +2063,8 @@ static int fan_set_enable(void) | |||
2022 | 2063 | ||
2023 | if (!acpi_ec_write(fan_status_offset, s)) | 2064 | if (!acpi_ec_write(fan_status_offset, s)) |
2024 | return -EIO; | 2065 | return -EIO; |
2066 | else | ||
2067 | fan_control_status_known = 1; | ||
2025 | break; | 2068 | break; |
2026 | 2069 | ||
2027 | case IBMACPI_FAN_WR_ACPI_SFAN: | 2070 | case IBMACPI_FAN_WR_ACPI_SFAN: |
@@ -2051,6 +2094,8 @@ static int fan_set_disable(void) | |||
2051 | case IBMACPI_FAN_WR_TPEC: | 2094 | case IBMACPI_FAN_WR_TPEC: |
2052 | if (!acpi_ec_write(fan_status_offset, 0x00)) | 2095 | if (!acpi_ec_write(fan_status_offset, 0x00)) |
2053 | return -EIO; | 2096 | return -EIO; |
2097 | else | ||
2098 | fan_control_status_known = 1; | ||
2054 | break; | 2099 | break; |
2055 | 2100 | ||
2056 | case IBMACPI_FAN_WR_ACPI_SFAN: | 2101 | case IBMACPI_FAN_WR_ACPI_SFAN: |