diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2009-01-11 00:01:08 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-01-15 13:47:14 -0500 |
commit | 1c2ece758a36b48133717e4db060fbe8fa52c5cd (patch) | |
tree | c0ab4d86ba1726eafee6a713d24ee89e572db8ad /drivers/platform | |
parent | cb4293589855714b6d5079336019bf2af5fc41f8 (diff) |
ACPI: thinkpad-acpi: clean-up fan subdriver quirk
Better document the Unitialized HFSP quirk, and modularize it a bit.
This makes the code flow easier to read and reduces LOC.
Apply the Unitialized HFSP closer to the source (i.e. inside the
get_fan_status()), this fixes a harmless buglet where at driver init
with the quirk active, the user could set the hwmon pwm1 attribute and
switch out of pwm1_mode=2 to pwm1_mode=0 without changing pwm1_mode
directly.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Cc: Tino Keitel <tino.keitel@tikei.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 109 |
1 files changed, 58 insertions, 51 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d7d41ae2f299..213219d938e8 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -5897,6 +5897,60 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */ | |||
5897 | ); /* all others */ | 5897 | ); /* all others */ |
5898 | 5898 | ||
5899 | /* | 5899 | /* |
5900 | * Unitialized HFSP quirk: ACPI DSDT and EC fail to initialize the | ||
5901 | * HFSP register at boot, so it contains 0x07 but the Thinkpad could | ||
5902 | * be in auto mode (0x80). | ||
5903 | * | ||
5904 | * This is corrected by any write to HFSP either by the driver, or | ||
5905 | * by the firmware. | ||
5906 | * | ||
5907 | * We assume 0x07 really means auto mode while this quirk is active, | ||
5908 | * as this is far more likely than the ThinkPad being in level 7, | ||
5909 | * which is only used by the firmware during thermal emergencies. | ||
5910 | */ | ||
5911 | |||
5912 | static void fan_quirk1_detect(void) | ||
5913 | { | ||
5914 | /* In some ThinkPads, neither the EC nor the ACPI | ||
5915 | * DSDT initialize the HFSP register, and it ends up | ||
5916 | * being initially set to 0x07 when it *could* be | ||
5917 | * either 0x07 or 0x80. | ||
5918 | * | ||
5919 | * Enable for TP-1Y (T43), TP-78 (R51e), | ||
5920 | * TP-76 (R52), TP-70 (T43, R52), which are known | ||
5921 | * to be buggy. */ | ||
5922 | if (fan_control_initial_status == 0x07) { | ||
5923 | switch (thinkpad_id.ec_model) { | ||
5924 | case 0x5931: /* TP-1Y */ | ||
5925 | case 0x3837: /* TP-78 */ | ||
5926 | case 0x3637: /* TP-76 */ | ||
5927 | case 0x3037: /* TP-70 */ | ||
5928 | printk(TPACPI_NOTICE | ||
5929 | "fan_init: initial fan status is unknown, " | ||
5930 | "assuming it is in auto mode\n"); | ||
5931 | tp_features.fan_ctrl_status_undef = 1; | ||
5932 | ;; | ||
5933 | } | ||
5934 | } | ||
5935 | } | ||
5936 | |||
5937 | static void fan_quirk1_handle(u8 *fan_status) | ||
5938 | { | ||
5939 | if (unlikely(tp_features.fan_ctrl_status_undef)) { | ||
5940 | if (*fan_status != fan_control_initial_status) { | ||
5941 | /* something changed the HFSP regisnter since | ||
5942 | * driver init time, so it is not undefined | ||
5943 | * anymore */ | ||
5944 | tp_features.fan_ctrl_status_undef = 0; | ||
5945 | } else { | ||
5946 | /* Return most likely status. In fact, it | ||
5947 | * might be the only possible status */ | ||
5948 | *fan_status = TP_EC_FAN_AUTO; | ||
5949 | } | ||
5950 | } | ||
5951 | } | ||
5952 | |||
5953 | /* | ||
5900 | * Call with fan_mutex held | 5954 | * Call with fan_mutex held |
5901 | */ | 5955 | */ |
5902 | static void fan_update_desired_level(u8 status) | 5956 | static void fan_update_desired_level(u8 status) |
@@ -5934,8 +5988,10 @@ static int fan_get_status(u8 *status) | |||
5934 | if (unlikely(!acpi_ec_read(fan_status_offset, &s))) | 5988 | if (unlikely(!acpi_ec_read(fan_status_offset, &s))) |
5935 | return -EIO; | 5989 | return -EIO; |
5936 | 5990 | ||
5937 | if (likely(status)) | 5991 | if (likely(status)) { |
5938 | *status = s; | 5992 | *status = s; |
5993 | fan_quirk1_handle(status); | ||
5994 | } | ||
5939 | 5995 | ||
5940 | break; | 5996 | break; |
5941 | 5997 | ||
@@ -6245,16 +6301,6 @@ static ssize_t fan_pwm1_enable_show(struct device *dev, | |||
6245 | if (res) | 6301 | if (res) |
6246 | return res; | 6302 | return res; |
6247 | 6303 | ||
6248 | if (unlikely(tp_features.fan_ctrl_status_undef)) { | ||
6249 | if (status != fan_control_initial_status) { | ||
6250 | tp_features.fan_ctrl_status_undef = 0; | ||
6251 | } else { | ||
6252 | /* Return most likely status. In fact, it | ||
6253 | * might be the only possible status */ | ||
6254 | status = TP_EC_FAN_AUTO; | ||
6255 | } | ||
6256 | } | ||
6257 | |||
6258 | if (status & TP_EC_FAN_FULLSPEED) { | 6304 | if (status & TP_EC_FAN_FULLSPEED) { |
6259 | mode = 0; | 6305 | mode = 0; |
6260 | } else if (status & TP_EC_FAN_AUTO) { | 6306 | } else if (status & TP_EC_FAN_AUTO) { |
@@ -6319,14 +6365,6 @@ static ssize_t fan_pwm1_show(struct device *dev, | |||
6319 | if (res) | 6365 | if (res) |
6320 | return res; | 6366 | return res; |
6321 | 6367 | ||
6322 | if (unlikely(tp_features.fan_ctrl_status_undef)) { | ||
6323 | if (status != fan_control_initial_status) { | ||
6324 | tp_features.fan_ctrl_status_undef = 0; | ||
6325 | } else { | ||
6326 | status = TP_EC_FAN_AUTO; | ||
6327 | } | ||
6328 | } | ||
6329 | |||
6330 | if ((status & | 6368 | if ((status & |
6331 | (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0) | 6369 | (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0) |
6332 | status = fan_control_desired_level; | 6370 | status = fan_control_desired_level; |
@@ -6458,29 +6496,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
6458 | if (likely(acpi_ec_read(fan_status_offset, | 6496 | if (likely(acpi_ec_read(fan_status_offset, |
6459 | &fan_control_initial_status))) { | 6497 | &fan_control_initial_status))) { |
6460 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; | 6498 | fan_status_access_mode = TPACPI_FAN_RD_TPEC; |
6461 | 6499 | fan_quirk1_detect(); | |
6462 | /* In some ThinkPads, neither the EC nor the ACPI | ||
6463 | * DSDT initialize the fan status, and it ends up | ||
6464 | * being set to 0x07 when it *could* be either | ||
6465 | * 0x07 or 0x80. | ||
6466 | * | ||
6467 | * Enable for TP-1Y (T43), TP-78 (R51e), | ||
6468 | * TP-76 (R52), TP-70 (T43, R52), which are known | ||
6469 | * to be buggy. */ | ||
6470 | if (fan_control_initial_status == 0x07) { | ||
6471 | switch (thinkpad_id.ec_model) { | ||
6472 | case 0x5931: /* TP-1Y */ | ||
6473 | case 0x3837: /* TP-78 */ | ||
6474 | case 0x3637: /* TP-76 */ | ||
6475 | case 0x3037: /* TP-70 */ | ||
6476 | printk(TPACPI_NOTICE | ||
6477 | "fan_init: initial fan status " | ||
6478 | "is unknown, assuming it is " | ||
6479 | "in auto mode\n"); | ||
6480 | tp_features.fan_ctrl_status_undef = 1; | ||
6481 | ;; | ||
6482 | } | ||
6483 | } | ||
6484 | } else { | 6500 | } else { |
6485 | printk(TPACPI_ERR | 6501 | printk(TPACPI_ERR |
6486 | "ThinkPad ACPI EC access misbehaving, " | 6502 | "ThinkPad ACPI EC access misbehaving, " |
@@ -6669,15 +6685,6 @@ static int fan_read(char *p) | |||
6669 | if (rc < 0) | 6685 | if (rc < 0) |
6670 | return rc; | 6686 | return rc; |
6671 | 6687 | ||
6672 | if (unlikely(tp_features.fan_ctrl_status_undef)) { | ||
6673 | if (status != fan_control_initial_status) | ||
6674 | tp_features.fan_ctrl_status_undef = 0; | ||
6675 | else | ||
6676 | /* Return most likely status. In fact, it | ||
6677 | * might be the only possible status */ | ||
6678 | status = TP_EC_FAN_AUTO; | ||
6679 | } | ||
6680 | |||
6681 | len += sprintf(p + len, "status:\t\t%s\n", | 6688 | len += sprintf(p + len, "status:\t\t%s\n", |
6682 | (status != 0) ? "enabled" : "disabled"); | 6689 | (status != 0) ? "enabled" : "disabled"); |
6683 | 6690 | ||