diff options
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
| -rw-r--r-- | drivers/misc/thinkpad_acpi.c | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 4db1cf9078d9..899766e16fa8 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -4932,16 +4932,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
| 4932 | */ | 4932 | */ |
| 4933 | b = tpacpi_check_std_acpi_brightness_support(); | 4933 | b = tpacpi_check_std_acpi_brightness_support(); |
| 4934 | if (b > 0) { | 4934 | if (b > 0) { |
| 4935 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | 4935 | |
| 4936 | printk(TPACPI_NOTICE | 4936 | if (acpi_video_backlight_support()) { |
| 4937 | "Lenovo BIOS switched to ACPI backlight " | 4937 | if (brightness_enable > 1) { |
| 4938 | "control mode\n"); | 4938 | printk(TPACPI_NOTICE |
| 4939 | } | 4939 | "Standard ACPI backlight interface " |
| 4940 | if (brightness_enable > 1) { | 4940 | "available, not loading native one.\n"); |
| 4941 | printk(TPACPI_NOTICE | 4941 | return 1; |
| 4942 | "standard ACPI backlight interface " | 4942 | } else if (brightness_enable == 1) { |
| 4943 | "available, not loading native one...\n"); | 4943 | printk(TPACPI_NOTICE |
| 4944 | return 1; | 4944 | "Backlight control force enabled, even if standard " |
| 4945 | "ACPI backlight interface is available\n"); | ||
| 4946 | } | ||
| 4947 | } else { | ||
| 4948 | if (brightness_enable > 1) { | ||
| 4949 | printk(TPACPI_NOTICE | ||
| 4950 | "Standard ACPI backlight interface not " | ||
| 4951 | "available, thinkpad_acpi native " | ||
| 4952 | "brightness control enabled\n"); | ||
| 4953 | } | ||
| 4945 | } | 4954 | } |
| 4946 | } | 4955 | } |
| 4947 | 4956 | ||
| @@ -5309,6 +5318,7 @@ static enum fan_control_commands fan_control_commands; | |||
| 5309 | 5318 | ||
| 5310 | static u8 fan_control_initial_status; | 5319 | static u8 fan_control_initial_status; |
| 5311 | static u8 fan_control_desired_level; | 5320 | static u8 fan_control_desired_level; |
| 5321 | static u8 fan_control_resume_level; | ||
| 5312 | static int fan_watchdog_maxinterval; | 5322 | static int fan_watchdog_maxinterval; |
| 5313 | 5323 | ||
| 5314 | static struct mutex fan_mutex; | 5324 | static struct mutex fan_mutex; |
| @@ -5431,8 +5441,8 @@ static int fan_set_level(int level) | |||
| 5431 | 5441 | ||
| 5432 | case TPACPI_FAN_WR_ACPI_FANS: | 5442 | case TPACPI_FAN_WR_ACPI_FANS: |
| 5433 | case TPACPI_FAN_WR_TPEC: | 5443 | case TPACPI_FAN_WR_TPEC: |
| 5434 | if ((level != TP_EC_FAN_AUTO) && | 5444 | if (!(level & TP_EC_FAN_AUTO) && |
| 5435 | (level != TP_EC_FAN_FULLSPEED) && | 5445 | !(level & TP_EC_FAN_FULLSPEED) && |
| 5436 | ((level < 0) || (level > 7))) | 5446 | ((level < 0) || (level > 7))) |
| 5437 | return -EINVAL; | 5447 | return -EINVAL; |
| 5438 | 5448 | ||
| @@ -5996,38 +6006,67 @@ static void fan_exit(void) | |||
| 5996 | 6006 | ||
| 5997 | static void fan_suspend(pm_message_t state) | 6007 | static void fan_suspend(pm_message_t state) |
| 5998 | { | 6008 | { |
| 6009 | int rc; | ||
| 6010 | |||
| 5999 | if (!fan_control_allowed) | 6011 | if (!fan_control_allowed) |
| 6000 | return; | 6012 | return; |
| 6001 | 6013 | ||
| 6002 | /* Store fan status in cache */ | 6014 | /* Store fan status in cache */ |
| 6003 | fan_get_status_safe(NULL); | 6015 | fan_control_resume_level = 0; |
| 6016 | rc = fan_get_status_safe(&fan_control_resume_level); | ||
| 6017 | if (rc < 0) | ||
| 6018 | printk(TPACPI_NOTICE | ||
| 6019 | "failed to read fan level for later " | ||
| 6020 | "restore during resume: %d\n", rc); | ||
| 6021 | |||
| 6022 | /* if it is undefined, don't attempt to restore it. | ||
| 6023 | * KEEP THIS LAST */ | ||
| 6004 | if (tp_features.fan_ctrl_status_undef) | 6024 | if (tp_features.fan_ctrl_status_undef) |
| 6005 | fan_control_desired_level = TP_EC_FAN_AUTO; | 6025 | fan_control_resume_level = 0; |
| 6006 | } | 6026 | } |
| 6007 | 6027 | ||
| 6008 | static void fan_resume(void) | 6028 | static void fan_resume(void) |
| 6009 | { | 6029 | { |
| 6010 | u8 saved_fan_level; | ||
| 6011 | u8 current_level = 7; | 6030 | u8 current_level = 7; |
| 6012 | bool do_set = false; | 6031 | bool do_set = false; |
| 6032 | int rc; | ||
| 6013 | 6033 | ||
| 6014 | /* DSDT *always* updates status on resume */ | 6034 | /* DSDT *always* updates status on resume */ |
| 6015 | tp_features.fan_ctrl_status_undef = 0; | 6035 | tp_features.fan_ctrl_status_undef = 0; |
| 6016 | 6036 | ||
| 6017 | saved_fan_level = fan_control_desired_level; | ||
| 6018 | if (!fan_control_allowed || | 6037 | if (!fan_control_allowed || |
| 6038 | !fan_control_resume_level || | ||
| 6019 | (fan_get_status_safe(¤t_level) < 0)) | 6039 | (fan_get_status_safe(¤t_level) < 0)) |
| 6020 | return; | 6040 | return; |
| 6021 | 6041 | ||
| 6022 | switch (fan_control_access_mode) { | 6042 | switch (fan_control_access_mode) { |
| 6023 | case TPACPI_FAN_WR_ACPI_SFAN: | 6043 | case TPACPI_FAN_WR_ACPI_SFAN: |
| 6024 | do_set = (saved_fan_level > current_level); | 6044 | /* never decrease fan level */ |
| 6045 | do_set = (fan_control_resume_level > current_level); | ||
| 6025 | break; | 6046 | break; |
| 6026 | case TPACPI_FAN_WR_ACPI_FANS: | 6047 | case TPACPI_FAN_WR_ACPI_FANS: |
| 6027 | case TPACPI_FAN_WR_TPEC: | 6048 | case TPACPI_FAN_WR_TPEC: |
| 6028 | do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) || | 6049 | /* never decrease fan level, scale is: |
| 6029 | (saved_fan_level == 7 && | 6050 | * TP_EC_FAN_FULLSPEED > 7 >= TP_EC_FAN_AUTO |
| 6030 | !(current_level & TP_EC_FAN_FULLSPEED))); | 6051 | * |
| 6052 | * We expect the firmware to set either 7 or AUTO, but we | ||
| 6053 | * handle FULLSPEED out of paranoia. | ||
| 6054 | * | ||
| 6055 | * So, we can safely only restore FULLSPEED or 7, anything | ||
| 6056 | * else could slow the fan. Restoring AUTO is useless, at | ||
| 6057 | * best that's exactly what the DSDT already set (it is the | ||
| 6058 | * slower it uses). | ||
| 6059 | * | ||
| 6060 | * Always keep in mind that the DSDT *will* have set the | ||
| 6061 | * fans to what the vendor supposes is the best level. We | ||
| 6062 | * muck with it only to speed the fan up. | ||
| 6063 | */ | ||
| 6064 | if (fan_control_resume_level != 7 && | ||
| 6065 | !(fan_control_resume_level & TP_EC_FAN_FULLSPEED)) | ||
| 6066 | return; | ||
| 6067 | else | ||
| 6068 | do_set = !(current_level & TP_EC_FAN_FULLSPEED) && | ||
| 6069 | (current_level != fan_control_resume_level); | ||
| 6031 | break; | 6070 | break; |
| 6032 | default: | 6071 | default: |
| 6033 | return; | 6072 | return; |
| @@ -6035,8 +6074,11 @@ static void fan_resume(void) | |||
| 6035 | if (do_set) { | 6074 | if (do_set) { |
| 6036 | printk(TPACPI_NOTICE | 6075 | printk(TPACPI_NOTICE |
| 6037 | "restoring fan level to 0x%02x\n", | 6076 | "restoring fan level to 0x%02x\n", |
| 6038 | saved_fan_level); | 6077 | fan_control_resume_level); |
| 6039 | fan_set_level_safe(saved_fan_level); | 6078 | rc = fan_set_level_safe(fan_control_resume_level); |
| 6079 | if (rc < 0) | ||
| 6080 | printk(TPACPI_NOTICE | ||
| 6081 | "failed to restore fan level: %d\n", rc); | ||
| 6040 | } | 6082 | } |
| 6041 | } | 6083 | } |
| 6042 | 6084 | ||
