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 | ||