diff options
| -rw-r--r-- | drivers/acpi/ibm_acpi.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 1703c617c0e8..7d0bd61eebc7 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c | |||
| @@ -231,6 +231,31 @@ struct ibm_thermal_sensors_struct { | |||
| 231 | s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; | 231 | s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| 234 | enum fan_status_access_mode { | ||
| 235 | IBMACPI_FAN_NONE = 0, /* No fan status or control */ | ||
| 236 | IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ | ||
| 237 | IBMACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */ | ||
| 238 | }; | ||
| 239 | |||
| 240 | enum fan_control_access_mode { | ||
| 241 | IBMACPI_FAN_WR_NONE = 0, /* No fan control */ | ||
| 242 | IBMACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */ | ||
| 243 | IBMACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */ | ||
| 244 | IBMACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */ | ||
| 245 | }; | ||
| 246 | |||
| 247 | enum fan_control_commands { | ||
| 248 | IBMACPI_FAN_CMD_SPEED = 0x0001, /* speed command */ | ||
| 249 | IBMACPI_FAN_CMD_LEVEL = 0x0002, /* level command */ | ||
| 250 | IBMACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd */ | ||
| 251 | }; | ||
| 252 | |||
| 253 | enum { /* Fan control constants */ | ||
| 254 | fan_status_offset = 0x2f, /* EC register 0x2f */ | ||
| 255 | fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) | ||
| 256 | * 0x84 must be read before 0x85 */ | ||
| 257 | }; | ||
| 258 | |||
| 234 | static int ibm_thinkpad_ec_found; | 259 | static int ibm_thinkpad_ec_found; |
| 235 | 260 | ||
| 236 | struct ibm_struct { | 261 | struct ibm_struct { |
| @@ -1659,8 +1684,59 @@ static int volume_write(char *buf) | |||
| 1659 | return 0; | 1684 | return 0; |
| 1660 | } | 1685 | } |
| 1661 | 1686 | ||
| 1662 | static int fan_status_offset = 0x2f; | 1687 | static enum fan_status_access_mode fan_status_access_mode; |
| 1663 | static int fan_rpm_offset = 0x84; | 1688 | static enum fan_control_access_mode fan_control_access_mode; |
| 1689 | static enum fan_control_commands fan_control_commands; | ||
| 1690 | |||
| 1691 | static int fan_init(void) | ||
| 1692 | { | ||
| 1693 | u8 status; | ||
| 1694 | |||
| 1695 | fan_status_access_mode = IBMACPI_FAN_NONE; | ||
| 1696 | fan_control_access_mode = IBMACPI_FAN_WR_NONE; | ||
| 1697 | fan_control_commands = 0; | ||
| 1698 | |||
| 1699 | if (gfan_handle) { | ||
| 1700 | /* 570, 600e/x, 770e, 770x */ | ||
| 1701 | fan_status_access_mode = IBMACPI_FAN_RD_ACPI_GFAN; | ||
| 1702 | } else { | ||
| 1703 | /* all other ThinkPads: note that even old-style | ||
| 1704 | * ThinkPad ECs supports the fan control register */ | ||
| 1705 | if (likely(acpi_ec_read(fan_status_offset, &status))) { | ||
| 1706 | fan_status_access_mode = IBMACPI_FAN_RD_TPEC; | ||
| 1707 | } else { | ||
| 1708 | printk(IBM_ERR | ||
| 1709 | "ThinkPad ACPI EC access misbehaving, " | ||
| 1710 | "fan status and control unavailable\n"); | ||
| 1711 | return 0; | ||
| 1712 | } | ||
| 1713 | } | ||
| 1714 | |||
| 1715 | if (sfan_handle) { | ||
| 1716 | /* 570, 770x-JL */ | ||
| 1717 | fan_control_access_mode = IBMACPI_FAN_WR_ACPI_SFAN; | ||
| 1718 | fan_control_commands |= IBMACPI_FAN_CMD_LEVEL; | ||
| 1719 | } else { | ||
| 1720 | if (!gfan_handle) { | ||
| 1721 | /* gfan without sfan means no fan control */ | ||
| 1722 | /* all other models implement TP EC 0x2f control */ | ||
| 1723 | |||
| 1724 | if (fans_handle) { | ||
| 1725 | /* X31, X40 */ | ||
| 1726 | fan_control_access_mode = | ||
| 1727 | IBMACPI_FAN_WR_ACPI_FANS; | ||
| 1728 | fan_control_commands |= | ||
| 1729 | IBMACPI_FAN_CMD_SPEED | | ||
| 1730 | IBMACPI_FAN_CMD_ENABLE; | ||
| 1731 | } else { | ||
| 1732 | fan_control_access_mode = IBMACPI_FAN_WR_TPEC; | ||
| 1733 | fan_control_commands |= IBMACPI_FAN_CMD_ENABLE; | ||
| 1734 | } | ||
| 1735 | } | ||
| 1736 | } | ||
| 1737 | |||
| 1738 | return 0; | ||
| 1739 | } | ||
| 1664 | 1740 | ||
| 1665 | static int fan_read(char *p) | 1741 | static int fan_read(char *p) |
| 1666 | { | 1742 | { |
| @@ -1849,6 +1925,7 @@ static struct ibm_struct ibms[] = { | |||
| 1849 | .name = "fan", | 1925 | .name = "fan", |
| 1850 | .read = fan_read, | 1926 | .read = fan_read, |
| 1851 | .write = fan_write, | 1927 | .write = fan_write, |
| 1928 | .init = fan_init, | ||
| 1852 | .experimental = 1, | 1929 | .experimental = 1, |
| 1853 | }, | 1930 | }, |
| 1854 | }; | 1931 | }; |
