diff options
| author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2006-11-24 08:47:11 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2006-12-07 01:38:40 -0500 |
| commit | a8b7a6626d7605a795b33317cd730b7d76da3d0a (patch) | |
| tree | 4e6654a1237d4350d3b7ff0a781a7b9a3d939804 | |
| parent | 18ad7996e17649d81c15a2c9dae03c75050a05a8 (diff) | |
ACPI: ibm-acpi: document fan control
This patch documents the ThinkPad fan control strategies. Source of the
data:
0. ibm-acpi source
1. DSDTs for various ThinkPads (770, X31, X40, X41, T43, A21m, T22)
2. http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
3. http://thinkwiki.org/wiki/How_to_control_fan_speed
4. Various threads about windows fan control utilities in thinkpads.com
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
| -rw-r--r-- | drivers/acpi/ibm_acpi.c | 110 |
1 files changed, 108 insertions, 2 deletions
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 187af1bfcb9d..faf78d3eac2d 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c | |||
| @@ -205,7 +205,7 @@ IBM_HANDLE(led, ec, "SLED", /* 570 */ | |||
| 205 | IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ | 205 | IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ |
| 206 | IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */ | 206 | IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */ |
| 207 | IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */ | 207 | IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */ |
| 208 | IBM_HANDLE(fans, ec, "FANS"); /* X31, X40 */ | 208 | IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */ |
| 209 | 209 | ||
| 210 | IBM_HANDLE(gfan, ec, "GFAN", /* 570 */ | 210 | IBM_HANDLE(gfan, ec, "GFAN", /* 570 */ |
| 211 | "\\FSPD", /* 600e/x, 770e, 770x */ | 211 | "\\FSPD", /* 600e/x, 770e, 770x */ |
| @@ -231,6 +231,106 @@ struct ibm_thermal_sensors_struct { | |||
| 231 | s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; | 231 | s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| 234 | /* | ||
| 235 | * FAN ACCESS MODES | ||
| 236 | * | ||
| 237 | * IBMACPI_FAN_RD_ACPI_GFAN: | ||
| 238 | * ACPI GFAN method: returns fan level | ||
| 239 | * | ||
| 240 | * see IBMACPI_FAN_WR_ACPI_SFAN | ||
| 241 | * EC 0x2f not available if GFAN exists | ||
| 242 | * | ||
| 243 | * IBMACPI_FAN_WR_ACPI_SFAN: | ||
| 244 | * ACPI SFAN method: sets fan level, 0 (stop) to 7 (max) | ||
| 245 | * | ||
| 246 | * EC 0x2f might be available *for reading*, but never for writing. | ||
| 247 | * | ||
| 248 | * IBMACPI_FAN_WR_TPEC: | ||
| 249 | * ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported | ||
| 250 | * on almost all ThinkPads | ||
| 251 | * | ||
| 252 | * Fan speed changes of any sort (including those caused by the | ||
| 253 | * disengaged mode) are usually done slowly by the firmware as the | ||
| 254 | * maximum ammount of fan duty cycle change per second seems to be | ||
| 255 | * limited. | ||
| 256 | * | ||
| 257 | * Reading is not available if GFAN exists. | ||
| 258 | * Writing is not available if SFAN exists. | ||
| 259 | * | ||
| 260 | * Bits | ||
| 261 | * 7 automatic mode engaged; | ||
| 262 | * (default operation mode of the ThinkPad) | ||
| 263 | * fan level is ignored in this mode. | ||
| 264 | * 6 disengage mode (takes precedence over bit 7); | ||
| 265 | * not available on all thinkpads. May disable | ||
| 266 | * the tachometer, and speeds up fan to 100% duty-cycle, | ||
| 267 | * which speeds it up far above the standard RPM | ||
| 268 | * levels. It is not impossible that it could cause | ||
| 269 | * hardware damage. | ||
| 270 | * 5-3 unused in some models. Extra bits for fan level | ||
| 271 | * in others, but still useless as all values above | ||
| 272 | * 7 map to the same speed as level 7 in these models. | ||
| 273 | * 2-0 fan level (0..7 usually) | ||
| 274 | * 0x00 = stop | ||
| 275 | * 0x07 = max (set when temperatures critical) | ||
| 276 | * Some ThinkPads may have other levels, see | ||
| 277 | * IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41) | ||
| 278 | * | ||
| 279 | * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at | ||
| 280 | * boot. Apparently the EC does not intialize it, so unless ACPI DSDT | ||
| 281 | * does so, its initial value is meaningless (0x07). | ||
| 282 | * | ||
| 283 | * For firmware bugs, refer to: | ||
| 284 | * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues | ||
| 285 | * | ||
| 286 | * ---- | ||
| 287 | * | ||
| 288 | * ThinkPad EC register 0x84 (LSB), 0x85 (MSB): | ||
| 289 | * Main fan tachometer reading (in RPM) | ||
| 290 | * | ||
| 291 | * This register is present on all ThinkPads with a new-style EC, and | ||
| 292 | * it is known not to be present on the A21m/e, and T22, as there is | ||
| 293 | * something else in offset 0x84 according to the ACPI DSDT. Other | ||
| 294 | * ThinkPads from this same time period (and earlier) probably lack the | ||
| 295 | * tachometer as well. | ||
| 296 | * | ||
| 297 | * Unfortunately a lot of ThinkPads with new-style ECs but whose firwmare | ||
| 298 | * was never fixed by IBM to report the EC firmware version string | ||
| 299 | * probably support the tachometer (like the early X models), so | ||
| 300 | * detecting it is quite hard. We need more data to know for sure. | ||
| 301 | * | ||
| 302 | * FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings | ||
| 303 | * might result. | ||
| 304 | * | ||
| 305 | * FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this | ||
| 306 | * register is not invalidated in ThinkPads that disable tachometer | ||
| 307 | * readings. Thus, the tachometer readings go stale. | ||
| 308 | * | ||
| 309 | * For firmware bugs, refer to: | ||
| 310 | * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues | ||
| 311 | * | ||
| 312 | * IBMACPI_FAN_WR_ACPI_FANS: | ||
| 313 | * ThinkPad X31, X40, X41. Not available in the X60. | ||
| 314 | * | ||
| 315 | * FANS ACPI handle: takes three arguments: low speed, medium speed, | ||
| 316 | * high speed. ACPI DSDT seems to map these three speeds to levels | ||
| 317 | * as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH | ||
| 318 | * (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3") | ||
| 319 | * | ||
| 320 | * The speeds are stored on handles | ||
| 321 | * (FANA:FAN9), (FANC:FANB), (FANE:FAND). | ||
| 322 | * | ||
| 323 | * There are three default speed sets, acessible as handles: | ||
| 324 | * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H | ||
| 325 | * | ||
| 326 | * ACPI DSDT switches which set is in use depending on various | ||
| 327 | * factors. | ||
| 328 | * | ||
| 329 | * IBMACPI_FAN_WR_TPEC is also available and should be used to | ||
| 330 | * command the fan. The X31/X40/X41 seems to have 8 fan levels, | ||
| 331 | * but the ACPI tables just mention level 7. | ||
| 332 | */ | ||
| 333 | |||
| 234 | enum fan_status_access_mode { | 334 | enum fan_status_access_mode { |
| 235 | IBMACPI_FAN_NONE = 0, /* No fan status or control */ | 335 | IBMACPI_FAN_NONE = 0, /* No fan status or control */ |
| 236 | IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ | 336 | IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ |
| @@ -1722,7 +1822,7 @@ static int fan_init(void) | |||
| 1722 | /* all other models implement TP EC 0x2f control */ | 1822 | /* all other models implement TP EC 0x2f control */ |
| 1723 | 1823 | ||
| 1724 | if (fans_handle) { | 1824 | if (fans_handle) { |
| 1725 | /* X31, X40 */ | 1825 | /* X31, X40, X41 */ |
| 1726 | fan_control_access_mode = | 1826 | fan_control_access_mode = |
| 1727 | IBMACPI_FAN_WR_ACPI_FANS; | 1827 | IBMACPI_FAN_WR_ACPI_FANS; |
| 1728 | fan_control_commands |= | 1828 | fan_control_commands |= |
| @@ -1742,6 +1842,9 @@ static int fan_get_status(u8 *status) | |||
| 1742 | { | 1842 | { |
| 1743 | u8 s; | 1843 | u8 s; |
| 1744 | 1844 | ||
| 1845 | /* TODO: | ||
| 1846 | * Add IBMACPI_FAN_RD_ACPI_FANS ? */ | ||
| 1847 | |||
| 1745 | switch (fan_status_access_mode) { | 1848 | switch (fan_status_access_mode) { |
| 1746 | case IBMACPI_FAN_RD_ACPI_GFAN: | 1849 | case IBMACPI_FAN_RD_ACPI_GFAN: |
| 1747 | /* 570, 600e/x, 770e, 770x */ | 1850 | /* 570, 600e/x, 770e, 770x */ |
| @@ -1950,6 +2053,9 @@ static int fan_write_cmd_speed(const char *cmd, int *rc) | |||
| 1950 | { | 2053 | { |
| 1951 | int speed; | 2054 | int speed; |
| 1952 | 2055 | ||
| 2056 | /* TODO: | ||
| 2057 | * Support speed <low> <medium> <high> ? */ | ||
| 2058 | |||
| 1953 | if (sscanf(cmd, "speed %d", &speed) != 1) | 2059 | if (sscanf(cmd, "speed %d", &speed) != 1) |
| 1954 | return 0; | 2060 | return 0; |
| 1955 | 2061 | ||
